From bc7b73089163b49fa2d0ae94938cd76f4c26c139 Mon Sep 17 00:00:00 2001 From: Filipe Sabella Date: Thu, 22 Oct 2020 16:40:45 -0300 Subject: [PATCH 1/2] Pass in base to Error.human_attribute_names There are validation cases in which the human_attribute_name depends on other fields of the base class. For instance, an Address model that depends on the selected country to localize the attribute name to be shown in error messages. E.g. the :address1 and :address2 attributes can be displayed as very different strings depending on whether the address is in the US or in Japan. --- activemodel/lib/active_model/error.rb | 13 +++++++++---- activemodel/lib/active_model/errors.rb | 2 +- .../test/cases/validations/i18n_validation_test.rb | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/activemodel/lib/active_model/error.rb b/activemodel/lib/active_model/error.rb index b6dbeb01f5..c3fb2cb3b6 100644 --- a/activemodel/lib/active_model/error.rb +++ b/activemodel/lib/active_model/error.rb @@ -12,8 +12,10 @@ module ActiveModel class_attribute :i18n_customize_full_message, default: false - def self.full_message(attribute, message, base_class) # :nodoc: + def self.full_message(attribute, message, base) # :nodoc: return message if attribute == :base + + base_class = base.class attribute = attribute.to_s if i18n_customize_full_message && base_class.respond_to?(:i18n_scope) @@ -48,7 +50,10 @@ module ActiveModel defaults << "%{attribute} %{message}" attr_name = attribute.tr(".", "_").humanize - attr_name = base_class.human_attribute_name(attribute, default: attr_name) + attr_name = base_class.human_attribute_name(attribute, { + default: attr_name, + base: base, + }) I18n.t(defaults.shift, default: defaults, @@ -62,7 +67,7 @@ module ActiveModel options = { model: base.model_name.human, - attribute: base.class.human_attribute_name(attribute), + attribute: base.class.human_attribute_name(attribute, { base: base }), value: value, object: base }.merge!(options) @@ -151,7 +156,7 @@ module ActiveModel # error.full_message # # => "Name is too short (minimum is 5 characters)" def full_message - self.class.full_message(attribute, message, @base.class) + self.class.full_message(attribute, message, @base) end # See if error matches provided +attribute+, +type+ and +options+. diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index e9812b9385..deb03231ae 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -511,7 +511,7 @@ module ActiveModel # # person.errors.full_message(:name, 'is invalid') # => "Name is invalid" def full_message(attribute, message) - Error.full_message(attribute, message, @base.class) + Error.full_message(attribute, message, @base) end # Translates an error message in its default scope diff --git a/activemodel/test/cases/validations/i18n_validation_test.rb b/activemodel/test/cases/validations/i18n_validation_test.rb index 2dc3e681c4..0717e6bb6d 100644 --- a/activemodel/test/cases/validations/i18n_validation_test.rb +++ b/activemodel/test/cases/validations/i18n_validation_test.rb @@ -37,7 +37,7 @@ class I18nValidationTest < ActiveModel::TestCase def test_errors_full_messages_translates_human_attribute_name_for_model_attributes @person.errors.add(:name, "not found") - assert_called_with(person_class, :human_attribute_name, ["name", default: "Name"], returns: "Person's name") do + assert_called_with(person_class, :human_attribute_name, ["name", default: "Name", base: @person], returns: "Person's name") do assert_equal ["Person's name not found"], @person.errors.full_messages end end From ac677fb1e3235920f666a3253be3eea167dc7972 Mon Sep 17 00:00:00 2001 From: Filipe Sabella Date: Thu, 22 Oct 2020 16:45:53 -0300 Subject: [PATCH 2/2] Update CHANGELOG --- activemodel/CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md index e0d40a196c..64535f5ce4 100644 --- a/activemodel/CHANGELOG.md +++ b/activemodel/CHANGELOG.md @@ -1,3 +1,11 @@ +* Pass in `base` instead of `base_class` to Error.human_attribute_name + + *Filipe Sabella* + + This is useful in cases where the `human_attribute_name` method depends + on other attributes' values of the class under validation to derive what the + attirbute name should be. + * Deprecate marshalling load from legacy attributes format. *Ryuta Kamizono*