Last active
March 30, 2025 02:34
-
-
Save webuilder240/cd497cb2bfceb5ff19b1019e906e074b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class ValidationFormBuilder < ActionView::Helpers::FormBuilder | |
| include ActionView::Helpers::TagHelper | |
| include ActionView::Context # 必須 | |
| def validation_text_field(attribute, options = {}) | |
| field_with_feedback(:text_field, attribute, options) | |
| end | |
| def validation_email_field(attribute, options = {}) | |
| field_with_feedback(:email_field, attribute, options) | |
| end | |
| def validation_number_field(attribute, options = {}) | |
| field_with_feedback(:number_field, attribute, options) | |
| end | |
| def validation_password_field(attribute, options = {}) | |
| field_with_feedback(:password_field, attribute, options) | |
| end | |
| def validation_text_area(attribute, options = {}) | |
| field_with_feedback(:text_area, attribute, options) | |
| end | |
| private | |
| def field_with_feedback(method, attribute, options) | |
| input_html = send("validatable_#{method}", attribute, options) | |
| feedback_html = error_feedback(attribute) | |
| safe_join([ input_html, feedback_html ]) | |
| end | |
| def error_feedback(attribute) | |
| errors = object.errors[attribute] | |
| model_name = object_name # ← Rails FormBuilder が自動でセットするモデル名 | |
| # 属性名を翻訳 | |
| attribute_name = object.class.human_attribute_name(attribute) | |
| content_tag(:div, id: "#{model_name}_#{attribute}-feedback") do | |
| if errors.present? | |
| # エラーメッセージに属性名を追加 | |
| formatted_errors = errors.map do |error| | |
| # エラーメッセージが既に属性名を含んでいる場合はそのまま使用 | |
| if error.include?(attribute_name) | |
| error | |
| else | |
| "#{attribute_name}#{error}" | |
| end | |
| end | |
| content_tag(:span, formatted_errors.join(", "), class: "error") | |
| else | |
| "".html_safe | |
| end | |
| end | |
| end | |
| def validatable_text_field(attribute, options) | |
| options = add_validation_attributes(attribute, options) | |
| text_field(attribute, options) | |
| end | |
| # validatable_XXX のバリデーション属性を追加する処理(既に作っていたヘルパー相当) | |
| def validatable_email_field(attribute, options) | |
| options = add_validation_attributes(attribute, options) | |
| email_field(attribute, options) | |
| end | |
| def validatable_number_field(attribute, options) | |
| options = add_validation_attributes(attribute, options) | |
| number_field(attribute, options) | |
| end | |
| def validatable_password_field(attribute, options) | |
| options = add_validation_attributes(attribute, options) | |
| password_field(attribute, options) | |
| end | |
| def validatable_text_area(attribute, options) | |
| options = add_validation_attributes(attribute, options) | |
| text_area(attribute, options) | |
| end | |
| def add_validation_attributes(attribute, options) | |
| validators = object.class.validators_on(attribute) | |
| html = options.deep_dup | |
| model_name = object.class.model_name.human | |
| # 属性名を翻訳 | |
| attribute_name = object.class.human_attribute_name(attribute) | |
| if validators.any? { |v| v.is_a?(ActiveModel::Validations::PresenceValidator) } | |
| html[:required] = true | |
| # エラーメッセージを手動で生成 | |
| message = I18n.t("errors.messages.blank") | |
| html[:"data-message-required"] ||= "#{attribute_name}#{message}" | |
| end | |
| if validator = validators.find { |v| v.is_a?(ActiveModel::Validations::LengthValidator) } | |
| if validator.options[:minimum] | |
| html[:minlength] = validator.options[:minimum] | |
| # エラーメッセージを手動で生成 | |
| message = I18n.t("errors.messages.too_short", count: validator.options[:minimum]) | |
| html[:"data-message-too-short"] ||= "#{attribute_name}#{message}" | |
| end | |
| end | |
| if validator = validators.find { |v| v.is_a?(ActiveModel::Validations::NumericalityValidator) } | |
| if min = validator.options[:greater_than_or_equal_to] | |
| html[:min] = min | |
| # エラーメッセージを手動で生成 | |
| message = I18n.t("errors.messages.greater_than_or_equal_to", count: min) | |
| html[:"data-message-range-underflow"] ||= "#{attribute_name}#{message}" | |
| end | |
| if max = validator.options[:less_than_or_equal_to] | |
| html[:max] = max | |
| # エラーメッセージを手動で生成 | |
| message = I18n.t("errors.messages.less_than_or_equal_to", count: max) | |
| html[:"data-message-range-overflow"] ||= "#{attribute_name}#{message}" | |
| end | |
| end | |
| html | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment