Skip to content

Commit

Permalink
Added ability to add format to model attribute error key
Browse files Browse the repository at this point in the history
  • Loading branch information
i.tsoy committed Jun 27, 2022
1 parent d51b171 commit 1e0cee1
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 4 deletions.
13 changes: 9 additions & 4 deletions activemodel/lib/active_model/error.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class Error

class_attribute :i18n_customize_full_message, default: false

def self.full_message(attribute, message, base) # :nodoc:
def self.full_message(attribute, message, base, raw_type = nil) # :nodoc:
return message if attribute == :base

base_class = base.class
Expand All @@ -28,13 +28,15 @@ def self.full_message(attribute, message, base) # :nodoc:
if namespace
defaults = base_class.lookup_ancestors.map do |klass|
[
:"#{attributes_scope}.#{klass.model_name.i18n_key}/#{namespace}.attributes.#{attribute_name}.#{raw_type}.format",
:"#{attributes_scope}.#{klass.model_name.i18n_key}/#{namespace}.attributes.#{attribute_name}.format",
:"#{attributes_scope}.#{klass.model_name.i18n_key}/#{namespace}.format",
]
end
else
defaults = base_class.lookup_ancestors.map do |klass|
[
:"#{attributes_scope}.#{klass.model_name.i18n_key}.attributes.#{attribute_name}.#{raw_type}.format",
:"#{attributes_scope}.#{klass.model_name.i18n_key}.attributes.#{attribute_name}.format",
:"#{attributes_scope}.#{klass.model_name.i18n_key}.format",
]
Expand Down Expand Up @@ -77,8 +79,11 @@ def self.generate_message(attribute, type, base, options) # :nodoc:
attribute = attribute.to_s.remove(/\[\d+\]/)

defaults = base.class.lookup_ancestors.flat_map do |klass|
[ :"#{i18n_scope}.errors.models.#{klass.model_name.i18n_key}.attributes.#{attribute}.#{type}",
:"#{i18n_scope}.errors.models.#{klass.model_name.i18n_key}.#{type}" ]
[
:"#{i18n_scope}.errors.models.#{klass.model_name.i18n_key}.attributes.#{attribute}.#{type}.message",
:"#{i18n_scope}.errors.models.#{klass.model_name.i18n_key}.attributes.#{attribute}.#{type}",
:"#{i18n_scope}.errors.models.#{klass.model_name.i18n_key}.#{type}"
]
end
defaults << :"#{i18n_scope}.errors.messages.#{type}"

Expand Down Expand Up @@ -156,7 +161,7 @@ def details
# error.full_message
# # => "Name is too short (minimum is 5 characters)"
def full_message
self.class.full_message(attribute, message, @base)
self.class.full_message(attribute, message, @base, raw_type)
end

# See if error matches provided +attribute+, +type+, and +options+.
Expand Down
111 changes: 111 additions & 0 deletions activemodel/test/cases/error_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,18 @@ def test_initialize
assert_equal({ foo: :bar }, error.options)
end

def with_i18n_customize_full_message
ActiveModel::Error.i18n_customize_full_message = true
yield
ActiveModel::Error.i18n_customize_full_message = false
end

def with_custom_translations
yield
I18n.backend.reload!
I18n.backend.translations(do_init: true)
end

test "initialize without type" do
error = ActiveModel::Error.new(Person.new, :name)
assert_equal :invalid, error.type
Expand Down Expand Up @@ -190,6 +202,105 @@ def test_initialize
}
end

test "full_message uses custom format of models" do
with_i18n_customize_full_message do
errors = ActiveModel::Errors.new(Manager.new)
errors.add(:name, :custom_error_name)
errors.add(:age, :custom_error_age)

with_custom_translations do
I18n.backend.store_translations(:en,
activemodel: {
errors: {
models: {
"error_test/manager" => {
format: "%{message}",
attributes: {
name: { custom_error_name: "custom_error_name" },
age: { custom_error_age: "custom_error_age" }
}
}
}
}
}
)
I18n.with_locale(:en) {
assert_equal ["custom_error_name", "custom_error_age"],
errors.full_messages
}
end
end
end


test "full_message uses custom format of model attributes" do
with_i18n_customize_full_message do
errors = ActiveModel::Errors.new(Manager.new)
errors.add(:name, :custom_error_name_1)
errors.add(:name, :custom_error_name_2)
errors.add(:age, :custom_error_age)

with_custom_translations do
I18n.backend.store_translations(:en,
activemodel: {
errors: {
models: {
"error_test/manager" => {
attributes: {
name: {
format: "%{message}",
custom_error_name_1: "custom_error_name_1",
custom_error_name_2: "custom_error_name_2"
},
age: { custom_error_age: "custom_error_age" }
}
}
}
}
}
)
I18n.with_locale(:en) {
assert_equal ["custom_error_name_1", "custom_error_name_2", "age custom_error_age"],
errors.full_messages
}
end
end
end

test "full_message uses custom format of model attribute error keys" do
with_i18n_customize_full_message do
errors = ActiveModel::Errors.new(Manager.new)
errors.add(:name, :custom_error_name_1)
errors.add(:name, :custom_error_name_2)

with_custom_translations do
I18n.backend.store_translations(:en,
activemodel: {
errors: {
models: {
"error_test/manager" => {
attributes: {
name: {
custom_error_name_1: {
format: "%{message}",
message: "custom_error_name_1"
},
custom_error_name_2: "custom_error_name_2"
}
}
}
}
}
}
)
I18n.with_locale(:en) {
assert_equal ["custom_error_name_1", "name custom_error_name_2"],
errors.full_messages
}
end
end
end

test "equality by base attribute, type and options" do
person = Person.new

Expand Down

0 comments on commit 1e0cee1

Please sign in to comment.