activerecord 2.3.3 → 2.3.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (70) hide show
  1. data/CHANGELOG +8 -1
  2. data/Rakefile +32 -15
  3. data/examples/performance.rb +162 -0
  4. data/lib/active_record/associations.rb +37 -5
  5. data/lib/active_record/associations/association_collection.rb +1 -0
  6. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +16 -0
  7. data/lib/active_record/associations/has_many_association.rb +1 -0
  8. data/lib/active_record/associations/has_many_through_association.rb +13 -3
  9. data/lib/active_record/associations/has_one_through_association.rb +8 -2
  10. data/lib/active_record/autosave_association.rb +4 -3
  11. data/lib/active_record/base.rb +18 -10
  12. data/lib/active_record/calculations.rb +2 -0
  13. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +16 -2
  14. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +2 -2
  15. data/lib/active_record/connection_adapters/abstract_adapter.rb +7 -0
  16. data/lib/active_record/connection_adapters/mysql_adapter.rb +17 -8
  17. data/lib/active_record/connection_adapters/postgresql_adapter.rb +32 -13
  18. data/lib/active_record/connection_adapters/sqlite_adapter.rb +12 -0
  19. data/lib/active_record/dirty.rb +1 -1
  20. data/lib/active_record/fixtures.rb +9 -7
  21. data/lib/active_record/i18n_interpolation_deprecation.rb +1 -1
  22. data/lib/active_record/locale/en.yml +4 -0
  23. data/lib/active_record/named_scope.rb +1 -6
  24. data/lib/active_record/reflection.rb +1 -1
  25. data/lib/active_record/schema_dumper.rb +1 -2
  26. data/lib/active_record/serializers/json_serializer.rb +5 -3
  27. data/lib/active_record/serializers/xml_serializer.rb +6 -2
  28. data/lib/active_record/validations.rb +148 -79
  29. data/lib/active_record/version.rb +1 -1
  30. data/test/cases/adapter_test.rb +12 -0
  31. data/test/cases/associations/belongs_to_associations_test.rb +0 -18
  32. data/test/cases/associations/eager_load_nested_include_test.rb +5 -5
  33. data/test/cases/associations/habtm_join_table_test.rb +56 -0
  34. data/test/cases/associations/has_many_associations_test.rb +56 -2
  35. data/test/cases/associations/has_many_through_associations_test.rb +46 -1
  36. data/test/cases/associations/has_one_through_associations_test.rb +10 -0
  37. data/test/cases/associations/join_model_test.rb +4 -4
  38. data/test/cases/base_test.rb +49 -4
  39. data/test/cases/calculations_test.rb +6 -0
  40. data/test/cases/column_definition_test.rb +34 -0
  41. data/test/cases/dirty_test.rb +10 -0
  42. data/test/cases/finder_test.rb +15 -50
  43. data/test/cases/fixtures_test.rb +1 -1
  44. data/test/cases/i18n_test.rb +5 -0
  45. data/test/cases/method_scoping_test.rb +1 -1
  46. data/test/cases/migration_test.rb +39 -11
  47. data/test/cases/modules_test.rb +42 -0
  48. data/test/cases/named_scope_test.rb +6 -4
  49. data/test/cases/pk_test.rb +18 -0
  50. data/test/cases/reflection_test.rb +2 -2
  51. data/test/cases/schema_dumper_test.rb +19 -1
  52. data/test/cases/validations_i18n_test.rb +656 -624
  53. data/test/cases/validations_test.rb +12 -2
  54. data/test/cases/xml_serialization_test.rb +20 -0
  55. data/test/fixtures/fixture_database.sqlite +0 -0
  56. data/test/fixtures/fixture_database.sqlite3 +0 -0
  57. data/test/fixtures/fixture_database_2.sqlite +0 -0
  58. data/test/fixtures/fixture_database_2.sqlite3 +0 -0
  59. data/test/fixtures/posts.yml +3 -0
  60. data/test/models/author.rb +1 -0
  61. data/test/models/comment.rb +5 -1
  62. data/test/models/company.rb +2 -0
  63. data/test/models/company_in_module.rb +1 -1
  64. data/test/models/contract.rb +5 -0
  65. data/test/models/organization.rb +2 -0
  66. data/test/models/topic.rb +0 -2
  67. data/test/schema/postgresql_specific_schema.rb +13 -2
  68. data/test/schema/schema.rb +4 -0
  69. metadata +12 -54
  70. data/test/debug.log +0 -415
@@ -1,32 +1,20 @@
1
1
  require "cases/helper"
2
2
  require 'models/topic'
3
3
  require 'models/reply'
4
+ require 'models/person'
4
5
 
5
- class ActiveRecordValidationsI18nTests < ActiveSupport::TestCase
6
- def setup
7
- reset_callbacks Topic
8
- @topic = Topic.new
9
- @old_load_path, @old_backend = I18n.load_path, I18n.backend
10
- I18n.load_path.clear
11
- I18n.backend = I18n::Backend::Simple.new
12
- I18n.backend.store_translations('en', :activerecord => {:errors => {:messages => {:custom => nil}}})
13
- end
14
-
15
- def teardown
16
- reset_callbacks Topic
17
- I18n.load_path.replace @old_load_path
18
- I18n.backend = @old_backend
19
- end
20
-
21
- def unique_topic
22
- @unique ||= Topic.create :title => 'unique!'
6
+ module ActiveRecordValidationsI18nTestHelper
7
+ def store_translations(*args)
8
+ data = args.extract_options!
9
+ locale = args.shift || 'en'
10
+ I18n.backend.send(:init_translations)
11
+ I18n.backend.store_translations(locale, :activerecord => data)
23
12
  end
24
13
 
25
- def replied_topic
26
- @replied_topic ||= begin
27
- topic = Topic.create(:title => "topic")
28
- topic.replies << Reply.new
29
- topic
14
+ def delete_translation(key)
15
+ I18n.backend.instance_eval do
16
+ keys = I18n.send(:normalize_translation_keys, 'en', key, nil)
17
+ keys.inject(translations) { |result, k| keys.last == k ? result.delete(k.to_sym) : result[k.to_sym] }
30
18
  end
31
19
  end
32
20
 
@@ -37,879 +25,923 @@ class ActiveRecordValidationsI18nTests < ActiveSupport::TestCase
37
25
  model.instance_variable_set("@validate_on_update_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
38
26
  end
39
27
  end
28
+ end
29
+
30
+ # DEPRECATIONS
40
31
 
41
- def test_default_error_messages_is_deprecated
32
+ class ActiveRecordValidationsI18nDeprecationsTests < ActiveSupport::TestCase
33
+ test "default_error_messages is deprecated and can be removed in Rails 3 / ActiveModel" do
42
34
  assert_deprecated('ActiveRecord::Errors.default_error_messages') do
43
35
  ActiveRecord::Errors.default_error_messages
44
36
  end
45
37
  end
46
38
 
47
- def test_percent_s_interpolation_syntax_in_error_messages_still_works
39
+ test "%s interpolation syntax in error messages still works" do
48
40
  ActiveSupport::Deprecation.silence do
49
41
  result = I18n.t :does_not_exist, :default => "%s interpolation syntax is deprecated", :value => 'this'
50
42
  assert_equal result, "this interpolation syntax is deprecated"
51
43
  end
52
44
  end
53
45
 
54
- def test_percent_s_interpolation_syntax_in_error_messages_is_deprecated
46
+ test "%s interpolation syntax in error messages is deprecated" do
55
47
  assert_deprecated('using %s in messages') do
56
48
  I18n.t :does_not_exist, :default => "%s interpolation syntax is deprected", :value => 'this'
57
49
  end
58
50
  end
59
51
 
60
- def test_percent_d_interpolation_syntax_in_error_messages_still_works
52
+ test "%d interpolation syntax in error messages still works" do
61
53
  ActiveSupport::Deprecation.silence do
62
54
  result = I18n.t :does_not_exist, :default => "%d interpolation syntaxes are deprecated", :count => 2
63
55
  assert_equal result, "2 interpolation syntaxes are deprecated"
64
56
  end
65
57
  end
66
58
 
67
- def test_percent_d_interpolation_syntax_in_error_messages_is_deprecated
59
+ test "%d interpolation syntax in error messages is deprecated" do
68
60
  assert_deprecated('using %d in messages') do
69
61
  I18n.t :does_not_exist, :default => "%d interpolation syntaxes are deprected", :count => 2
70
62
  end
71
63
  end
64
+ end
72
65
 
73
- # ActiveRecord::Errors
74
- def test_errors_generate_message_translates_custom_model_attribute_key
75
-
76
- I18n.expects(:translate).with(
77
- :topic,
78
- { :count => 1,
79
- :default => ['Topic'],
80
- :scope => [:activerecord, :models]
81
- }
82
- ).returns('Topic')
83
-
84
- I18n.expects(:translate).with(
85
- :"topic.title",
86
- { :count => 1,
87
- :default => ['Title'],
88
- :scope => [:activerecord, :attributes]
89
- }
90
- ).returns('Title')
91
-
92
- I18n.expects(:translate).with(
93
- :"models.topic.attributes.title.invalid",
94
- :value => nil,
95
- :scope => [:activerecord, :errors],
96
- :default => [
97
- :"models.topic.invalid",
98
- 'default from class def error 1',
99
- :"messages.invalid"],
100
- :attribute => "Title",
101
- :model => "Topic"
102
- ).returns('default from class def error 1')
103
-
104
- @topic.errors.generate_message :title, :invalid, :default => 'default from class def error 1'
105
- end
106
-
107
- def test_errors_generate_message_translates_custom_model_attribute_keys_with_sti
108
-
109
- I18n.expects(:translate).with(
110
- :reply,
111
- { :count => 1,
112
- :default => [:topic, 'Reply'],
113
- :scope => [:activerecord, :models]
114
- }
115
- ).returns('Reply')
116
-
117
- I18n.expects(:translate).with(
118
- :"reply.title",
119
- { :count => 1,
120
- :default => [:'topic.title', 'Title'],
121
- :scope => [:activerecord, :attributes]
122
- }
123
- ).returns('Title')
124
66
 
125
- I18n.expects(:translate).with(
126
- :"models.reply.attributes.title.invalid",
127
- :value => nil,
128
- :scope => [:activerecord, :errors],
129
- :default => [
130
- :"models.reply.invalid",
131
- :"models.topic.attributes.title.invalid",
132
- :"models.topic.invalid",
133
- 'default from class def',
134
- :"messages.invalid"],
135
- :model => 'Reply',
136
- :attribute => 'Title'
137
- ).returns("default from class def")
67
+ # ACTIVERECORD VALIDATIONS
68
+ #
69
+ # For each validation:
70
+ #
71
+ # * test expect that it adds an error with the appropriate arguments
72
+ # * test that it looks up the correct default message
138
73
 
139
- Reply.new.errors.generate_message :title, :invalid, :default => 'default from class def'
74
+ class ActiveRecordValidationsI18nTests < ActiveSupport::TestCase
75
+ include ActiveRecordValidationsI18nTestHelper
140
76
 
77
+ def setup
78
+ reset_callbacks(Topic)
79
+ @topic = Topic.new
80
+ @reply = Reply.new
81
+ @old_load_path, @old_backend = I18n.load_path, I18n.backend
82
+ I18n.load_path.clear
83
+ I18n.backend = I18n::Backend::Simple.new
84
+ I18n.backend.store_translations('en', :activerecord => {:errors => {:messages => {:custom => nil}}})
141
85
  end
142
86
 
143
- def test_errors_add_on_empty_generates_message
144
- @topic.errors.expects(:generate_message).with(:title, :empty, {:default => nil})
145
- @topic.errors.add_on_empty :title
87
+ def teardown
88
+ reset_callbacks(Topic)
89
+ I18n.load_path.replace(@old_load_path)
90
+ I18n.backend = @old_backend
146
91
  end
147
92
 
148
- def test_errors_add_on_empty_generates_message_with_custom_default_message
149
- @topic.errors.expects(:generate_message).with(:title, :empty, {:default => 'custom'})
150
- @topic.errors.add_on_empty :title, 'custom'
93
+ def expect_error_added(model, attribute, type, options)
94
+ model.errors.expects(:add).with(attribute, type, options)
95
+ yield
96
+ model.valid?
151
97
  end
152
98
 
153
- def test_errors_add_on_blank_generates_message
154
- @topic.errors.expects(:generate_message).with(:title, :blank, {:default => nil})
155
- @topic.errors.add_on_blank :title
99
+ def assert_message_translations(model, attribute, type, &block)
100
+ assert_default_message_translation(model, attribute, type, &block)
101
+ reset_callbacks(model.class)
102
+ model.errors.clear
103
+ assert_custom_message_translation(model, attribute, type, &block)
156
104
  end
157
105
 
158
- def test_errors_add_on_blank_generates_message_with_custom_default_message
159
- @topic.errors.expects(:generate_message).with(:title, :blank, {:default => 'custom'})
160
- @topic.errors.add_on_blank :title, 'custom'
106
+ def assert_custom_message_translation(model, attribute, type)
107
+ store_translations(:errors => { :models => { model.class.name.underscore => { :attributes => { attribute => { type => 'custom message' } } } } })
108
+ yield
109
+ model.valid?
110
+ assert_equal 'custom message', model.errors.on(attribute)
161
111
  end
162
112
 
163
- def test_errors_full_messages_translates_human_attribute_name_for_model_attributes
164
- @topic.errors.instance_variable_set :@errors, { 'title' => ['empty'] }
165
- I18n.expects(:translate).with(:"topic.title", :default => ['Title'], :scope => [:activerecord, :attributes], :count => 1).returns('Title')
166
- @topic.errors.full_messages :locale => 'en'
113
+ def assert_default_message_translation(model, attribute, type)
114
+ store_translations(:errors => { :messages => { type => 'default message' } })
115
+ yield
116
+ model.valid?
117
+ assert_equal 'default message', model.errors.on(attribute)
167
118
  end
168
119
 
169
- # ActiveRecord::Validations
170
- # validates_confirmation_of w/ mocha
171
- def test_validates_confirmation_of_generates_message
172
- Topic.validates_confirmation_of :title
173
- @topic.title_confirmation = 'foo'
174
- @topic.errors.expects(:generate_message).with(:title, :confirmation, {:default => nil})
175
- @topic.valid?
120
+ def unique_topic
121
+ @unique ||= Topic.create(:title => 'unique!')
176
122
  end
177
123
 
178
- def test_validates_confirmation_of_generates_message_with_custom_default_message
179
- Topic.validates_confirmation_of :title, :message => 'custom'
180
- @topic.title_confirmation = 'foo'
181
- @topic.errors.expects(:generate_message).with(:title, :confirmation, {:default => 'custom'})
182
- @topic.valid?
124
+ def replied_topic
125
+ @replied_topic ||= begin
126
+ topic = Topic.create(:title => "topic")
127
+ topic.replies << Reply.new
128
+ topic
129
+ end
183
130
  end
184
131
 
185
- # validates_acceptance_of w/ mocha
132
+ # validates_confirmation_of
186
133
 
187
- def test_validates_acceptance_of_generates_message
188
- Topic.validates_acceptance_of :title, :allow_nil => false
189
- @topic.errors.expects(:generate_message).with(:title, :accepted, {:default => nil})
190
- @topic.valid?
191
- end
192
-
193
- def test_validates_acceptance_of_generates_message_with_custom_default_message
194
- Topic.validates_acceptance_of :title, :message => 'custom', :allow_nil => false
195
- @topic.errors.expects(:generate_message).with(:title, :accepted, {:default => 'custom'})
196
- @topic.valid?
134
+ test "#validates_confirmation_of given no custom message" do
135
+ expect_error_added(@topic, :title, :confirmation, :default => nil) do
136
+ Topic.validates_confirmation_of :title
137
+ @topic.title = 'title'
138
+ @topic.title_confirmation = 'foo'
139
+ end
197
140
  end
198
141
 
199
- # validates_presence_of w/ mocha
200
-
201
- def test_validates_presence_of_generates_message
202
- Topic.validates_presence_of :title
203
- @topic.errors.expects(:generate_message).with(:title, :blank, {:default => nil})
204
- @topic.valid?
142
+ test "#validates_confirmation_of given a custom message" do
143
+ expect_error_added(@topic, :title, :confirmation, :default => 'custom') do
144
+ Topic.validates_confirmation_of :title, :message => 'custom'
145
+ @topic.title_confirmation = 'foo'
146
+ end
205
147
  end
206
148
 
207
- def test_validates_presence_of_generates_message_with_custom_default_message
208
- Topic.validates_presence_of :title, :message => 'custom'
209
- @topic.errors.expects(:generate_message).with(:title, :blank, {:default => 'custom'})
210
- @topic.valid?
149
+ test "#validates_confirmation_of finds the correct message translations" do
150
+ assert_message_translations(@topic, :title, :confirmation) do
151
+ Topic.validates_confirmation_of :title
152
+ @topic.title_confirmation = 'foo'
153
+ end
211
154
  end
212
155
 
213
- def test_validates_length_of_within_generates_message_with_title_too_short
214
- Topic.validates_length_of :title, :within => 3..5
215
- @topic.errors.expects(:generate_message).with(:title, :too_short, {:count => 3, :default => nil})
216
- @topic.valid?
217
- end
156
+ # validates_acceptance_of
218
157
 
219
- def test_validates_length_of_within_generates_message_with_title_too_short_and_custom_default_message
220
- Topic.validates_length_of :title, :within => 3..5, :too_short => 'custom'
221
- @topic.errors.expects(:generate_message).with(:title, :too_short, {:count => 3, :default => 'custom'})
222
- @topic.valid?
158
+ test "#validates_acceptance_of given no custom message" do
159
+ expect_error_added(@topic, :title, :accepted, :default => nil) do
160
+ Topic.validates_acceptance_of :title, :allow_nil => false
161
+ end
223
162
  end
224
163
 
225
- def test_validates_length_of_within_generates_message_with_title_too_long
226
- Topic.validates_length_of :title, :within => 3..5
227
- @topic.title = 'this title is too long'
228
- @topic.errors.expects(:generate_message).with(:title, :too_long, {:count => 5, :default => nil})
229
- @topic.valid?
164
+ test "#validates_acceptance_of given a custom message" do
165
+ expect_error_added(@topic, :title, :accepted, :default => 'custom') do
166
+ Topic.validates_acceptance_of :title, :message => 'custom', :allow_nil => false
167
+ end
230
168
  end
231
169
 
232
- def test_validates_length_of_within_generates_message_with_title_too_long_and_custom_default_message
233
- Topic.validates_length_of :title, :within => 3..5, :too_long => 'custom'
234
- @topic.title = 'this title is too long'
235
- @topic.errors.expects(:generate_message).with(:title, :too_long, {:count => 5, :default => 'custom'})
236
- @topic.valid?
170
+ test "#validates_acceptance_of finds the correct message translations" do
171
+ assert_message_translations(@topic, :title, :accepted) do
172
+ Topic.validates_acceptance_of :title, :allow_nil => false
173
+ end
237
174
  end
238
175
 
239
- # validates_length_of :within w/ mocha
240
-
241
- def test_validates_length_of_within_generates_message_with_title_too_short
242
- Topic.validates_length_of :title, :within => 3..5
243
- @topic.errors.expects(:generate_message).with(:title, :too_short, {:count => 3, :default => nil})
244
- @topic.valid?
245
- end
176
+ # validates_presence_of
246
177
 
247
- def test_validates_length_of_within_generates_message_with_title_too_short_and_custom_default_message
248
- Topic.validates_length_of :title, :within => 3..5, :too_short => 'custom'
249
- @topic.errors.expects(:generate_message).with(:title, :too_short, {:count => 3, :default => 'custom'})
250
- @topic.valid?
178
+ test "#validates_presence_of given no custom message" do
179
+ expect_error_added(@topic, :title, :blank, :default => nil) do
180
+ Topic.validates_presence_of :title
181
+ end
251
182
  end
252
183
 
253
- def test_validates_length_of_within_generates_message_with_title_too_long
254
- Topic.validates_length_of :title, :within => 3..5
255
- @topic.title = 'this title is too long'
256
- @topic.errors.expects(:generate_message).with(:title, :too_long, {:count => 5, :default => nil})
257
- @topic.valid?
184
+ test "#validates_presence_of given a custom message" do
185
+ expect_error_added(@topic, :title, :blank, :default => 'custom') do
186
+ Topic.validates_presence_of :title, :message => 'custom'
187
+ end
258
188
  end
259
189
 
260
- def test_validates_length_of_within_generates_message_with_title_too_long_and_custom_default_message
261
- Topic.validates_length_of :title, :within => 3..5, :too_long => 'custom'
262
- @topic.title = 'this title is too long'
263
- @topic.errors.expects(:generate_message).with(:title, :too_long, {:count => 5, :default => 'custom'})
264
- @topic.valid?
190
+ test "#validates_presence_of finds the correct message translations" do
191
+ assert_message_translations(@topic, :title, :blank) do
192
+ Topic.validates_presence_of :title
193
+ end
265
194
  end
266
195
 
267
- # validates_length_of :is w/ mocha
196
+ # validates_length_of :too_short
268
197
 
269
- def test_validates_length_of_is_generates_message
270
- Topic.validates_length_of :title, :is => 5
271
- @topic.errors.expects(:generate_message).with(:title, :wrong_length, {:count => 5, :default => nil})
272
- @topic.valid?
198
+ test "#validates_length_of (:too_short) and no custom message" do
199
+ expect_error_added(@topic, :title, :too_short, :default => nil, :count => 3) do
200
+ Topic.validates_length_of :title, :within => 3..5
201
+ end
273
202
  end
274
203
 
275
- def test_validates_length_of_is_generates_message_with_custom_default_message
276
- Topic.validates_length_of :title, :is => 5, :message => 'custom'
277
- @topic.errors.expects(:generate_message).with(:title, :wrong_length, {:count => 5, :default => 'custom'})
278
- @topic.valid?
204
+ test "#validates_length_of (:too_short) and a custom message" do
205
+ expect_error_added(@topic, :title, :too_short, :default => 'custom', :count => 3) do
206
+ Topic.validates_length_of :title, :within => 3..5, :too_short => 'custom'
207
+ end
279
208
  end
280
209
 
281
- # validates_uniqueness_of w/ mocha
282
-
283
- def test_validates_uniqueness_of_generates_message
284
- Topic.validates_uniqueness_of :title
285
- @topic.title = unique_topic.title
286
- @topic.errors.expects(:generate_message).with(:title, :taken, {:default => nil, :value => 'unique!'})
287
- @topic.valid?
210
+ test "#validates_length_of (:too_short) finds the correct message translations" do
211
+ assert_message_translations(@topic, :title, :too_short) do
212
+ Topic.validates_length_of :title, :within => 3..5
213
+ end
288
214
  end
289
215
 
290
- def test_validates_uniqueness_of_generates_message_with_custom_default_message
291
- Topic.validates_uniqueness_of :title, :message => 'custom'
292
- @topic.title = unique_topic.title
293
- @topic.errors.expects(:generate_message).with(:title, :taken, {:default => 'custom', :value => 'unique!'})
294
- @topic.valid?
295
- end
216
+ # validates_length_of :too_long
296
217
 
297
- # validates_format_of w/ mocha
218
+ test "#validates_length_of (:too_long) and no custom message" do
219
+ expect_error_added(@topic, :title, :too_long, :default => nil, :count => 5) do
220
+ Topic.validates_length_of :title, :within => 3..5
221
+ @topic.title = 'this title is too long'
222
+ end
223
+ end
298
224
 
299
- def test_validates_format_of_generates_message
300
- Topic.validates_format_of :title, :with => /^[1-9][0-9]*$/
301
- @topic.title = '72x'
302
- @topic.errors.expects(:generate_message).with(:title, :invalid, {:value => '72x', :default => nil})
303
- @topic.valid?
225
+ test "#validates_length_of (:too_long) and a custom message" do
226
+ expect_error_added(@topic, :title, :too_long, :default => 'custom', :count => 5) do
227
+ Topic.validates_length_of :title, :within => 3..5, :too_long => 'custom'
228
+ @topic.title = 'this title is too long'
229
+ end
304
230
  end
305
231
 
306
- def test_validates_format_of_generates_message_with_custom_default_message
307
- Topic.validates_format_of :title, :with => /^[1-9][0-9]*$/, :message => 'custom'
308
- @topic.title = '72x'
309
- @topic.errors.expects(:generate_message).with(:title, :invalid, {:value => '72x', :default => 'custom'})
310
- @topic.valid?
232
+ test "#validates_length_of (:too_long) finds the correct message translations" do
233
+ assert_message_translations(@topic, :title, :too_long) do
234
+ Topic.validates_length_of :title, :within => 3..5
235
+ @topic.title = 'this title is too long'
236
+ end
311
237
  end
312
238
 
313
- # validates_inclusion_of w/ mocha
239
+ # validates_length_of :is
314
240
 
315
- def test_validates_inclusion_of_generates_message
316
- Topic.validates_inclusion_of :title, :in => %w(a b c)
317
- @topic.title = 'z'
318
- @topic.errors.expects(:generate_message).with(:title, :inclusion, {:value => 'z', :default => nil})
319
- @topic.valid?
241
+ test "#validates_length_of (:is) and no custom message" do
242
+ expect_error_added(@topic, :title, :wrong_length, :default => nil, :count => 5) do
243
+ Topic.validates_length_of :title, :is => 5
244
+ @topic.title = 'this title has the wrong length'
245
+ end
320
246
  end
321
247
 
322
- def test_validates_inclusion_of_generates_message_with_custom_default_message
323
- Topic.validates_inclusion_of :title, :in => %w(a b c), :message => 'custom'
324
- @topic.title = 'z'
325
- @topic.errors.expects(:generate_message).with(:title, :inclusion, {:value => 'z', :default => 'custom'})
326
- @topic.valid?
248
+ test "#validates_length_of (:is) and a custom message" do
249
+ expect_error_added(@topic, :title, :wrong_length, :default => 'custom', :count => 5) do
250
+ Topic.validates_length_of :title, :is => 5, :wrong_length => 'custom'
251
+ @topic.title = 'this title has the wrong length'
252
+ end
327
253
  end
328
254
 
329
- # validates_exclusion_of w/ mocha
330
-
331
- def test_validates_exclusion_of_generates_message
332
- Topic.validates_exclusion_of :title, :in => %w(a b c)
333
- @topic.title = 'a'
334
- @topic.errors.expects(:generate_message).with(:title, :exclusion, {:value => 'a', :default => nil})
335
- @topic.valid?
255
+ test "#validates_length_of (:is) finds the correct message translations" do
256
+ assert_message_translations(@topic, :title, :wrong_length) do
257
+ Topic.validates_length_of :title, :is => 5
258
+ @topic.title = 'this title has the wrong length'
259
+ end
336
260
  end
337
261
 
338
- def test_validates_exclusion_of_generates_message_with_custom_default_message
339
- Topic.validates_exclusion_of :title, :in => %w(a b c), :message => 'custom'
340
- @topic.title = 'a'
341
- @topic.errors.expects(:generate_message).with(:title, :exclusion, {:value => 'a', :default => 'custom'})
342
- @topic.valid?
343
- end
262
+ # validates_uniqueness_of
344
263
 
345
- # validates_numericality_of without :only_integer w/ mocha
264
+ test "#validates_uniqueness_of and no custom message" do
265
+ expect_error_added(@topic, :title, :taken, :default => nil, :value => 'unique!') do
266
+ Topic.validates_uniqueness_of :title
267
+ @topic.title = unique_topic.title
268
+ end
269
+ end
346
270
 
347
- def test_validates_numericality_of_generates_message
348
- Topic.validates_numericality_of :title
349
- @topic.title = 'a'
350
- @topic.errors.expects(:generate_message).with(:title, :not_a_number, {:value => 'a', :default => nil})
351
- @topic.valid?
271
+ test "#validates_uniqueness_of and a custom message" do
272
+ expect_error_added(@topic, :title, :taken, :default => 'custom', :value => 'unique!') do
273
+ Topic.validates_uniqueness_of :title, :message => 'custom'
274
+ @topic.title = unique_topic.title
275
+ end
352
276
  end
353
277
 
354
- def test_validates_numericality_of_generates_message_with_custom_default_message
355
- Topic.validates_numericality_of :title, :message => 'custom'
356
- @topic.title = 'a'
357
- @topic.errors.expects(:generate_message).with(:title, :not_a_number, {:value => 'a', :default => 'custom'})
358
- @topic.valid?
278
+ test "#validates_uniqueness_of finds the correct message translations" do
279
+ assert_message_translations(@topic, :title, :taken) do
280
+ Topic.validates_uniqueness_of :title
281
+ @topic.title = unique_topic.title
282
+ end
359
283
  end
360
284
 
361
- # validates_numericality_of with :only_integer w/ mocha
285
+ # validates_format_of
362
286
 
363
- def test_validates_numericality_of_only_integer_generates_message
364
- Topic.validates_numericality_of :title, :only_integer => true
365
- @topic.title = 'a'
366
- @topic.errors.expects(:generate_message).with(:title, :not_a_number, {:value => 'a', :default => nil})
367
- @topic.valid?
287
+ test "#validates_format_of and no custom message" do
288
+ expect_error_added(@topic, :title, :invalid, :default => nil, :value => '72x') do
289
+ Topic.validates_format_of :title, :with => /^[1-9][0-9]*$/
290
+ @topic.title = '72x'
291
+ end
368
292
  end
369
293
 
370
- def test_validates_numericality_of_only_integer_generates_message_with_custom_default_message
371
- Topic.validates_numericality_of :title, :only_integer => true, :message => 'custom'
372
- @topic.title = 'a'
373
- @topic.errors.expects(:generate_message).with(:title, :not_a_number, {:value => 'a', :default => 'custom'})
374
- @topic.valid?
294
+ test "#validates_format_of and a custom message" do
295
+ expect_error_added(@topic, :title, :invalid, :default => 'custom', :value => '72x') do
296
+ Topic.validates_format_of :title, :with => /^[1-9][0-9]*$/, :message => 'custom'
297
+ @topic.title = '72x'
298
+ end
375
299
  end
376
300
 
377
- # validates_numericality_of :odd w/ mocha
378
-
379
- def test_validates_numericality_of_odd_generates_message
380
- Topic.validates_numericality_of :title, :only_integer => true, :odd => true
381
- @topic.title = 0
382
- @topic.errors.expects(:generate_message).with(:title, :odd, {:value => 0, :default => nil})
383
- @topic.valid?
301
+ test "#validates_format_of finds the correct message translations" do
302
+ assert_message_translations(@topic, :title, :invalid) do
303
+ Topic.validates_format_of :title, :with => /^[1-9][0-9]*$/
304
+ @topic.title = '72x'
305
+ end
384
306
  end
385
307
 
386
- def test_validates_numericality_of_odd_generates_message_with_custom_default_message
387
- Topic.validates_numericality_of :title, :only_integer => true, :odd => true, :message => 'custom'
388
- @topic.title = 0
389
- @topic.errors.expects(:generate_message).with(:title, :odd, {:value => 0, :default => 'custom'})
390
- @topic.valid?
391
- end
308
+ # validates_inclusion_of
392
309
 
393
- # validates_numericality_of :less_than w/ mocha
310
+ test "#validates_inclusion_of and no custom message" do
311
+ list = %w(a b c)
312
+ expect_error_added(@topic, :title, :inclusion, :default => nil, :value => 'z') do
313
+ Topic.validates_inclusion_of :title, :in => list
314
+ @topic.title = 'z'
315
+ end
316
+ end
394
317
 
395
- def test_validates_numericality_of_less_than_generates_message
396
- Topic.validates_numericality_of :title, :only_integer => true, :less_than => 0
397
- @topic.title = 1
398
- @topic.errors.expects(:generate_message).with(:title, :less_than, {:value => 1, :count => 0, :default => nil})
399
- @topic.valid?
318
+ test "#validates_inclusion_of and a custom message" do
319
+ list = %w(a b c)
320
+ expect_error_added(@topic, :title, :inclusion, :default => 'custom', :value => 'z') do
321
+ Topic.validates_inclusion_of :title, :in => list, :message => 'custom'
322
+ @topic.title = 'z'
323
+ end
400
324
  end
401
325
 
402
- def test_validates_numericality_of_odd_generates_message_with_custom_default_message
403
- Topic.validates_numericality_of :title, :only_integer => true, :less_than => 0, :message => 'custom'
404
- @topic.title = 1
405
- @topic.errors.expects(:generate_message).with(:title, :less_than, {:value => 1, :count => 0, :default => 'custom'})
406
- @topic.valid?
326
+ test "#validates_inclusion_of finds the correct message translations" do
327
+ list = %w(a b c)
328
+ assert_message_translations(@topic, :title, :inclusion) do
329
+ Topic.validates_inclusion_of :title, :in => list
330
+ @topic.title = 'z'
331
+ end
407
332
  end
408
333
 
409
- # validates_associated w/ mocha
334
+ # validates_exclusion_of
410
335
 
411
- def test_validates_associated_generates_message
412
- Topic.validates_associated :replies
413
- replied_topic.errors.expects(:generate_message).with(:replies, :invalid, {:value => replied_topic.replies, :default => nil})
414
- replied_topic.valid?
336
+ test "#validates_exclusion_of and no custom message" do
337
+ list = %w(a b c)
338
+ expect_error_added(@topic, :title, :exclusion, :default => nil, :value => 'a') do
339
+ Topic.validates_exclusion_of :title, :in => list
340
+ @topic.title = 'a'
341
+ end
415
342
  end
416
343
 
417
- def test_validates_associated_generates_message_with_custom_default_message
418
- Topic.validates_associated :replies
419
- replied_topic.errors.expects(:generate_message).with(:replies, :invalid, {:value => replied_topic.replies, :default => nil})
420
- replied_topic.valid?
344
+ test "#validates_exclusion_of and a custom message" do
345
+ list = %w(a b c)
346
+ expect_error_added(@topic, :title, :exclusion, :default => 'custom', :value => 'a') do
347
+ Topic.validates_exclusion_of :title, :in => list, :message => 'custom'
348
+ @topic.title = 'a'
349
+ end
421
350
  end
422
351
 
423
- # validates_confirmation_of w/o mocha
352
+ test "#validates_exclusion_of finds the correct message translations" do
353
+ list = %w(a b c)
354
+ assert_message_translations(@topic, :title, :exclusion) do
355
+ Topic.validates_exclusion_of :title, :in => list
356
+ @topic.title = 'a'
357
+ end
358
+ end
424
359
 
425
- def test_validates_confirmation_of_finds_custom_model_key_translation
426
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:models => {:topic => {:attributes => {:title => {:confirmation => 'custom message'}}}}}}
427
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:confirmation => 'global message'}}}
360
+ # validates_numericality_of :not_a_number, without :only_integer
428
361
 
429
- Topic.validates_confirmation_of :title
430
- @topic.title_confirmation = 'foo'
431
- @topic.valid?
432
- assert_equal 'custom message', @topic.errors.on(:title)
362
+ test "#validates_numericality_of (:not_a_number, w/o :only_integer) no custom message" do
363
+ expect_error_added(@topic, :title, :not_a_number, :default => nil, :value => 'a') do
364
+ Topic.validates_numericality_of :title
365
+ @topic.title = 'a'
366
+ end
433
367
  end
434
368
 
435
- def test_validates_confirmation_of_finds_global_default_translation
436
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:confirmation => 'global message'}}}
437
-
438
- Topic.validates_confirmation_of :title
439
- @topic.title_confirmation = 'foo'
440
- @topic.valid?
441
- assert_equal 'global message', @topic.errors.on(:title)
369
+ test "#validates_numericality_of (:not_a_number, w/o :only_integer) and a custom message" do
370
+ expect_error_added(@topic, :title, :not_a_number, :default => 'custom', :value => 'a') do
371
+ Topic.validates_numericality_of :title, :message => 'custom'
372
+ @topic.title = 'a'
373
+ end
442
374
  end
443
375
 
444
- # validates_acceptance_of w/o mocha
376
+ test "#validates_numericality_of (:not_a_number, w/o :only_integer) finds the correct message translations" do
377
+ assert_message_translations(@topic, :title, :not_a_number) do
378
+ Topic.validates_numericality_of :title
379
+ @topic.title = 'a'
380
+ end
381
+ end
445
382
 
446
- def test_validates_acceptance_of_finds_custom_model_key_translation
447
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:models => {:topic => {:attributes => {:title => {:accepted => 'custom message'}}}}}}
448
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:accepted => 'global message'}}}
383
+ # validates_numericality_of :not_a_number, with :only_integer
449
384
 
450
- Topic.validates_acceptance_of :title, :allow_nil => false
451
- @topic.valid?
452
- assert_equal 'custom message', @topic.errors.on(:title)
385
+ test "#validates_numericality_of (:not_a_number, with :only_integer) no custom message" do
386
+ expect_error_added(@topic, :title, :not_a_number, :default => nil, :value => 'a') do
387
+ Topic.validates_numericality_of :title, :only_integer => true
388
+ @topic.title = 'a'
389
+ end
453
390
  end
454
391
 
455
- def test_validates_acceptance_of_finds_global_default_translation
456
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:accepted => 'global message'}}}
457
-
458
- Topic.validates_acceptance_of :title, :allow_nil => false
459
- @topic.valid?
460
- assert_equal 'global message', @topic.errors.on(:title)
392
+ test "#validates_numericality_of (:not_a_number, with :only_integer) and a custom message" do
393
+ expect_error_added(@topic, :title, :not_a_number, :default => 'custom', :value => 'a') do
394
+ Topic.validates_numericality_of :title, :only_integer => true, :message => 'custom'
395
+ @topic.title = 'a'
396
+ end
461
397
  end
462
398
 
463
- # validates_presence_of w/o mocha
399
+ test "#validates_numericality_of (:not_a_number, with :only_integer) finds the correct message translations" do
400
+ assert_message_translations(@topic, :title, :not_a_number) do
401
+ Topic.validates_numericality_of :title, :only_integer => true
402
+ @topic.title = 'a'
403
+ end
404
+ end
464
405
 
465
- def test_validates_presence_of_finds_custom_model_key_translation
466
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:models => {:topic => {:attributes => {:title => {:blank => 'custom message'}}}}}}
467
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:blank => 'global message'}}}
406
+ # validates_numericality_of :odd
468
407
 
469
- Topic.validates_presence_of :title
470
- @topic.valid?
471
- assert_equal 'custom message', @topic.errors.on(:title)
408
+ test "#validates_numericality_of (:odd) no custom message" do
409
+ expect_error_added(@topic, :title, :odd, :default => nil, :value => 0) do
410
+ Topic.validates_numericality_of :title, :only_integer => true, :odd => true
411
+ @topic.title = 0
412
+ end
472
413
  end
473
414
 
474
- def test_validates_presence_of_finds_global_default_translation
475
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:blank => 'global message'}}}
476
-
477
- Topic.validates_presence_of :title
478
- @topic.valid?
479
- assert_equal 'global message', @topic.errors.on(:title)
415
+ test "#validates_numericality_of (:odd) and a custom message" do
416
+ expect_error_added(@topic, :title, :odd, :default => 'custom', :value => 0) do
417
+ Topic.validates_numericality_of :title, :only_integer => true, :odd => true, :message => 'custom'
418
+ @topic.title = 0
419
+ end
480
420
  end
481
421
 
482
- # validates_length_of :within w/o mocha
422
+ test "#validates_numericality_of (:odd) finds the correct message translations" do
423
+ assert_message_translations(@topic, :title, :odd) do
424
+ Topic.validates_numericality_of :title, :only_integer => true, :odd => true
425
+ @topic.title = 0
426
+ end
427
+ end
483
428
 
484
- def test_validates_length_of_within_finds_custom_model_key_translation
485
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:models => {:topic => {:attributes => {:title => {:too_short => 'custom message'}}}}}}
486
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:too_short => 'global message'}}}
429
+ # validates_numericality_of :even
487
430
 
488
- Topic.validates_length_of :title, :within => 3..5
489
- @topic.valid?
490
- assert_equal 'custom message', @topic.errors.on(:title)
431
+ test "#validates_numericality_of (:even) no custom message" do
432
+ expect_error_added(@topic, :title, :even, :default => nil, :value => 1) do
433
+ Topic.validates_numericality_of :title, :only_integer => true, :even => true
434
+ @topic.title = 1
435
+ end
491
436
  end
492
437
 
493
- def test_validates_length_of_within_finds_global_default_translation
494
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:too_short => 'global message'}}}
495
-
496
- Topic.validates_length_of :title, :within => 3..5
497
- @topic.valid?
498
- assert_equal 'global message', @topic.errors.on(:title)
438
+ test "#validates_numericality_of (:even) and a custom message" do
439
+ expect_error_added(@topic, :title, :even, :default => 'custom', :value => 1) do
440
+ Topic.validates_numericality_of :title, :only_integer => true, :even => true, :message => 'custom'
441
+ @topic.title = 1
442
+ end
499
443
  end
500
444
 
501
- # validates_length_of :is w/o mocha
445
+ test "#validates_numericality_of (:even) finds the correct message translations" do
446
+ assert_message_translations(@topic, :title, :even) do
447
+ Topic.validates_numericality_of :title, :only_integer => true, :even => true
448
+ @topic.title = 1
449
+ end
450
+ end
502
451
 
503
- def test_validates_length_of_is_finds_custom_model_key_translation
504
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:models => {:topic => {:attributes => {:title => {:wrong_length => 'custom message'}}}}}}
505
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:wrong_length => 'global message'}}}
452
+ # validates_numericality_of :less_than
506
453
 
507
- Topic.validates_length_of :title, :is => 5
508
- @topic.valid?
509
- assert_equal 'custom message', @topic.errors.on(:title)
454
+ test "#validates_numericality_of (:less_than) no custom message" do
455
+ expect_error_added(@topic, :title, :less_than, :default => nil, :value => 1, :count => 0) do
456
+ Topic.validates_numericality_of :title, :only_integer => true, :less_than => 0
457
+ @topic.title = 1
458
+ end
510
459
  end
511
460
 
512
- def test_validates_length_of_is_finds_global_default_translation
513
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:wrong_length => 'global message'}}}
514
-
515
- Topic.validates_length_of :title, :is => 5
516
- @topic.valid?
517
- assert_equal 'global message', @topic.errors.on(:title)
461
+ test "#validates_numericality_of (:less_than) and a custom message" do
462
+ expect_error_added(@topic, :title, :less_than, :default => 'custom', :value => 1, :count => 0) do
463
+ Topic.validates_numericality_of :title, :only_integer => true, :less_than => 0, :message => 'custom'
464
+ @topic.title = 1
465
+ end
518
466
  end
519
467
 
520
- # validates_uniqueness_of w/o mocha
468
+ test "#validates_numericality_of (:less_than) finds the correct message translations" do
469
+ assert_message_translations(@topic, :title, :less_than) do
470
+ Topic.validates_numericality_of :title, :only_integer => true, :less_than => 0
471
+ @topic.title = 1
472
+ end
473
+ end
521
474
 
522
- def test_validates_length_of_is_finds_custom_model_key_translation
523
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:models => {:topic => {:attributes => {:title => {:wrong_length => 'custom message'}}}}}}
524
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:wrong_length => 'global message'}}}
475
+ # validates_associated
525
476
 
526
- Topic.validates_length_of :title, :is => 5
527
- @topic.valid?
528
- assert_equal 'custom message', @topic.errors.on(:title)
477
+ test "#validates_associated no custom message" do
478
+ expect_error_added(replied_topic, :replies, :invalid, :default => nil, :value => replied_topic.replies) do
479
+ Topic.validates_associated :replies
480
+ end
529
481
  end
530
482
 
531
- def test_validates_length_of_is_finds_global_default_translation
532
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:wrong_length => 'global message'}}}
483
+ test "#validates_associated and a custom message" do
484
+ expect_error_added(replied_topic, :replies, :invalid, :default => 'custom', :value => replied_topic.replies) do
485
+ Topic.validates_associated :replies, :message => 'custom'
486
+ end
487
+ end
533
488
 
534
- Topic.validates_length_of :title, :is => 5
535
- @topic.valid?
536
- assert_equal 'global message', @topic.errors.on(:title)
489
+ test "#validates_associated finds the correct message translations" do
490
+ assert_message_translations(replied_topic, :replies, :invalid) do
491
+ Topic.validates_associated :replies
492
+ end
537
493
  end
494
+ end
538
495
 
539
496
 
540
- # validates_format_of w/o mocha
497
+ # ACTIVERECORD ERROR
498
+ #
499
+ # * test that it passes given interpolation arguments, the human model name and human attribute name
500
+ # * test that it looks messages up with the the correct keys
501
+ # * test that it looks up the correct default messages
541
502
 
542
- def test_validates_format_of_finds_custom_model_key_translation
543
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:models => {:topic => {:attributes => {:title => {:invalid => 'custom message'}}}}}}
544
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:invalid => 'global message'}}}
503
+ class ActiveRecordErrorI18nTests < ActiveSupport::TestCase
504
+ include ActiveRecordValidationsI18nTestHelper
545
505
 
546
- Topic.validates_format_of :title, :with => /^[1-9][0-9]*$/
547
- @topic.valid?
548
- assert_equal 'custom message', @topic.errors.on(:title)
506
+ def setup
507
+ @reply = Reply.new
508
+ @old_backend, I18n.backend = I18n.backend, I18n::Backend::Simple.new
549
509
  end
550
510
 
551
- def test_validates_format_of_finds_global_default_translation
552
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:invalid => 'global message'}}}
553
-
554
- Topic.validates_format_of :title, :with => /^[1-9][0-9]*$/
555
- @topic.valid?
556
- assert_equal 'global message', @topic.errors.on(:title)
511
+ def teardown
512
+ I18n.backend = @old_backend
513
+ I18n.locale = nil
557
514
  end
558
515
 
559
- # validates_inclusion_of w/o mocha
560
-
561
- def test_validates_inclusion_of_finds_custom_model_key_translation
562
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:models => {:topic => {:attributes => {:title => {:inclusion => 'custom message'}}}}}}
563
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:inclusion => 'global message'}}}
516
+ def assert_error_message(message, *args)
517
+ assert_equal message, ActiveRecord::Error.new(@reply, *args).message
518
+ end
564
519
 
565
- Topic.validates_inclusion_of :title, :in => %w(a b c)
566
- @topic.valid?
567
- assert_equal 'custom message', @topic.errors.on(:title)
520
+ def assert_full_message(message, *args)
521
+ assert_equal message, ActiveRecord::Error.new(@reply, *args).full_message
568
522
  end
569
523
 
570
- def test_validates_inclusion_of_finds_global_default_translation
571
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:inclusion => 'global message'}}}
524
+ test "#generate_message passes the model attribute value for interpolation" do
525
+ store_translations(:errors => { :messages => { :foo => "You fooed: {{value}}." } })
526
+ @reply.title = "da title"
527
+ assert_error_message 'You fooed: da title.', :title, :foo
528
+ end
572
529
 
573
- Topic.validates_inclusion_of :title, :in => %w(a b c)
574
- @topic.valid?
575
- assert_equal 'global message', @topic.errors.on(:title)
530
+ test "#generate_message passes the human_name of the model for interpolation" do
531
+ store_translations(
532
+ :errors => { :messages => { :foo => "You fooed: {{model}}." } },
533
+ :models => { :topic => 'da topic' }
534
+ )
535
+ assert_error_message 'You fooed: da topic.', :title, :foo
576
536
  end
577
537
 
578
- # validates_exclusion_of w/o mocha
538
+ test "#generate_message passes the human_name of the attribute for interpolation" do
539
+ store_translations(
540
+ :errors => { :messages => { :foo => "You fooed: {{attribute}}." } },
541
+ :attributes => { :topic => { :title => 'da topic title' } }
542
+ )
543
+ assert_error_message 'You fooed: da topic title.', :title, :foo
544
+ end
579
545
 
580
- def test_validates_exclusion_of_finds_custom_model_key_translation
581
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:models => {:topic => {:attributes => {:title => {:exclusion => 'custom message'}}}}}}
582
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:exclusion => 'global message'}}}
546
+ # generate_message will look up the key for the error message (e.g. :blank) in these namespaces:
547
+ #
548
+ # activerecord.errors.models.reply.attributes.title
549
+ # activerecord.errors.models.reply
550
+ # activerecord.errors.models.topic.attributes.title
551
+ # activerecord.errors.models.topic
552
+ # [default from class level :validates_foo statement if this is a String]
553
+ # activerecord.errors.messages
583
554
 
584
- Topic.validates_exclusion_of :title, :in => %w(a b c)
585
- @topic.title = 'a'
586
- @topic.valid?
587
- assert_equal 'custom message', @topic.errors.on(:title)
588
- end
555
+ test "#generate_message key fallbacks (given a String as key)" do
556
+ store_translations(
557
+ :errors => {
558
+ :models => {
559
+ :reply => {
560
+ :attributes => { :title => { :custom => 'activerecord.errors.models.reply.attributes.title.custom' } },
561
+ :custom => 'activerecord.errors.models.reply.custom'
562
+ },
563
+ :topic => {
564
+ :attributes => { :title => { :custom => 'activerecord.errors.models.topic.attributes.title.custom' } },
565
+ :custom => 'activerecord.errors.models.topic.custom'
566
+ }
567
+ },
568
+ :messages => {
569
+ :custom => 'activerecord.errors.messages.custom',
570
+ :kaputt => 'activerecord.errors.messages.kaputt'
571
+ }
572
+ }
573
+ )
589
574
 
590
- def test_validates_exclusion_of_finds_global_default_translation
591
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:exclusion => 'global message'}}}
575
+ assert_error_message 'activerecord.errors.models.reply.attributes.title.custom', :title, :kaputt, :message => 'custom'
576
+ delete_translation :'activerecord.errors.models.reply.attributes.title.custom'
592
577
 
593
- Topic.validates_exclusion_of :title, :in => %w(a b c)
594
- @topic.title = 'a'
595
- @topic.valid?
596
- assert_equal 'global message', @topic.errors.on(:title)
597
- end
578
+ assert_error_message 'activerecord.errors.models.reply.custom', :title, :kaputt, :message => 'custom'
579
+ delete_translation :'activerecord.errors.models.reply.custom'
598
580
 
599
- # validates_numericality_of without :only_integer w/o mocha
581
+ assert_error_message 'activerecord.errors.models.topic.attributes.title.custom', :title, :kaputt, :message => 'custom'
582
+ delete_translation :'activerecord.errors.models.topic.attributes.title.custom'
600
583
 
601
- def test_validates_numericality_of_finds_custom_model_key_translation
602
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:models => {:topic => {:attributes => {:title => {:not_a_number => 'custom message'}}}}}}
603
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:not_a_number => 'global message'}}}
584
+ assert_error_message 'activerecord.errors.models.topic.custom', :title, :kaputt, :message => 'custom'
585
+ delete_translation :'activerecord.errors.models.topic.custom'
604
586
 
605
- Topic.validates_numericality_of :title
606
- @topic.title = 'a'
607
- @topic.valid?
608
- assert_equal 'custom message', @topic.errors.on(:title)
609
- end
587
+ assert_error_message 'activerecord.errors.messages.custom', :title, :kaputt, :message => 'custom'
588
+ delete_translation :'activerecord.errors.messages.custom'
610
589
 
611
- def test_validates_numericality_of_finds_global_default_translation
612
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:not_a_number => 'global message'}}}
590
+ # Implementing this would clash with the AR default behaviour of using validates_foo :message => 'foo'
591
+ # as an untranslated string. I.e. at this point we can either fall back to the given string from the
592
+ # class-level macro (validates_*) or fall back to the default message for this validation type.
593
+ # assert_error_message 'activerecord.errors.messages.kaputt', :title, :kaputt, :message => 'custom'
613
594
 
614
- Topic.validates_numericality_of :title, :only_integer => true
615
- @topic.title = 'a'
616
- @topic.valid?
617
- assert_equal 'global message', @topic.errors.on(:title)
595
+ assert_error_message 'custom', :title, :kaputt, :message => 'custom'
618
596
  end
619
597
 
620
- # validates_numericality_of with :only_integer w/o mocha
598
+ test "#generate_message key fallbacks (given a Symbol as key)" do
599
+ store_translations(
600
+ :errors => {
601
+ :models => {
602
+ :reply => {
603
+ :attributes => { :title => { :kaputt => 'activerecord.errors.models.reply.attributes.title.kaputt' } },
604
+ :kaputt => 'activerecord.errors.models.reply.kaputt'
605
+ },
606
+ :topic => {
607
+ :attributes => { :title => { :kaputt => 'activerecord.errors.models.topic.attributes.title.kaputt' } },
608
+ :kaputt => 'activerecord.errors.models.topic.kaputt'
609
+ }
610
+ },
611
+ :messages => {
612
+ :kaputt => 'activerecord.errors.messages.kaputt'
613
+ }
614
+ }
615
+ )
616
+
617
+ assert_error_message 'activerecord.errors.models.reply.attributes.title.kaputt', :title, :kaputt
618
+ delete_translation :'activerecord.errors.models.reply.attributes.title.kaputt'
621
619
 
622
- def test_validates_numericality_of_only_integer_finds_custom_model_key_translation
623
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:models => {:topic => {:attributes => {:title => {:not_a_number => 'custom message'}}}}}}
624
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:not_a_number => 'global message'}}}
620
+ assert_error_message 'activerecord.errors.models.reply.kaputt', :title, :kaputt
621
+ delete_translation :'activerecord.errors.models.reply.kaputt'
625
622
 
626
- Topic.validates_numericality_of :title, :only_integer => true
627
- @topic.title = 'a'
628
- @topic.valid?
629
- assert_equal 'custom message', @topic.errors.on(:title)
630
- end
623
+ assert_error_message 'activerecord.errors.models.topic.attributes.title.kaputt', :title, :kaputt
624
+ delete_translation :'activerecord.errors.models.topic.attributes.title.kaputt'
631
625
 
632
- def test_validates_numericality_of_only_integer_finds_global_default_translation
633
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:not_a_number => 'global message'}}}
626
+ assert_error_message 'activerecord.errors.models.topic.kaputt', :title, :kaputt
627
+ delete_translation :'activerecord.errors.models.topic.kaputt'
634
628
 
635
- Topic.validates_numericality_of :title, :only_integer => true
636
- @topic.title = 'a'
637
- @topic.valid?
638
- assert_equal 'global message', @topic.errors.on(:title)
629
+ assert_error_message 'activerecord.errors.messages.kaputt', :title, :kaputt
639
630
  end
640
631
 
641
- # validates_numericality_of :odd w/o mocha
632
+ # full_messages
642
633
 
643
- def test_validates_numericality_of_odd_finds_custom_model_key_translation
644
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:models => {:topic => {:attributes => {:title => {:odd => 'custom message'}}}}}}
645
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:odd => 'global message'}}}
634
+ test "#full_message with no format present" do
635
+ store_translations(:errors => { :messages => { :kaputt => 'is kaputt' } })
636
+ assert_full_message 'Title is kaputt', :title, :kaputt
637
+ end
646
638
 
647
- Topic.validates_numericality_of :title, :only_integer => true, :odd => true
648
- @topic.title = 0
649
- @topic.valid?
650
- assert_equal 'custom message', @topic.errors.on(:title)
639
+ test "#full_message with a format present" do
640
+ store_translations(:errors => { :messages => { :kaputt => 'is kaputt' }, :full_messages => { :format => '{{attribute}}: {{message}}' } })
641
+ assert_full_message 'Title: is kaputt', :title, :kaputt
651
642
  end
652
643
 
653
- def test_validates_numericality_of_odd_finds_global_default_translation
654
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:odd => 'global message'}}}
644
+ test "#full_message with a type specific format present" do
645
+ store_translations(:errors => { :messages => { :kaputt => 'is kaputt' }, :full_messages => { :kaputt => '{{attribute}} {{message}}!' } })
646
+ assert_full_message 'Title is kaputt!', :title, :kaputt
647
+ end
655
648
 
656
- Topic.validates_numericality_of :title, :only_integer => true, :odd => true
657
- @topic.title = 0
658
- @topic.valid?
659
- assert_equal 'global message', @topic.errors.on(:title)
649
+ test "#full_message with class-level specified custom message" do
650
+ store_translations(:errors => { :messages => { :broken => 'is kaputt' }, :full_messages => { :broken => '{{attribute}} {{message}}?!' } })
651
+ assert_full_message 'Title is kaputt?!', :title, :kaputt, :message => :broken
660
652
  end
661
653
 
662
- # validates_numericality_of :less_than w/o mocha
654
+ # switch locales
663
655
 
664
- def test_validates_numericality_of_less_than_finds_custom_model_key_translation
665
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:models => {:topic => {:attributes => {:title => {:less_than => 'custom message'}}}}}}
666
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:less_than => 'global message'}}}
656
+ test "#message allows to switch locales" do
657
+ store_translations(:en, :errors => { :messages => { :kaputt => 'is kaputt' } })
658
+ store_translations(:de, :errors => { :messages => { :kaputt => 'ist kaputt' } })
667
659
 
668
- Topic.validates_numericality_of :title, :only_integer => true, :less_than => 0
669
- @topic.title = 1
670
- @topic.valid?
671
- assert_equal 'custom message', @topic.errors.on(:title)
660
+ assert_error_message 'is kaputt', :title, :kaputt
661
+ I18n.locale = :de
662
+ assert_error_message 'ist kaputt', :title, :kaputt
663
+ I18n.locale = :en
664
+ assert_error_message 'is kaputt', :title, :kaputt
672
665
  end
673
666
 
674
- def test_validates_numericality_of_less_than_finds_global_default_translation
675
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:less_than => 'global message'}}}
667
+ test "#full_message allows to switch locales" do
668
+ store_translations(:en, :errors => { :messages => { :kaputt => 'is kaputt' } }, :attributes => { :topic => { :title => 'The title' } })
669
+ store_translations(:de, :errors => { :messages => { :kaputt => 'ist kaputt' } }, :attributes => { :topic => { :title => 'Der Titel' } })
676
670
 
677
- Topic.validates_numericality_of :title, :only_integer => true, :less_than => 0
678
- @topic.title = 1
679
- @topic.valid?
680
- assert_equal 'global message', @topic.errors.on(:title)
671
+ assert_full_message 'The title is kaputt', :title, :kaputt
672
+ I18n.locale = :de
673
+ assert_full_message 'Der Titel ist kaputt', :title, :kaputt
674
+ I18n.locale = :en
675
+ assert_full_message 'The title is kaputt', :title, :kaputt
681
676
  end
677
+ end
682
678
 
679
+ # ACTIVERECORD DEFAULT ERROR MESSAGES
680
+ #
681
+ # * test that Error generates the default error messages
683
682
 
684
- # validates_associated w/o mocha
685
-
686
- def test_validates_associated_finds_custom_model_key_translation
687
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:models => {:topic => {:attributes => {:replies => {:invalid => 'custom message'}}}}}}
688
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:invalid => 'global message'}}}
689
-
690
- Topic.validates_associated :replies
691
- replied_topic.valid?
692
- assert_equal 'custom message', replied_topic.errors.on(:replies)
683
+ class ActiveRecordDefaultErrorMessagesI18nTests < ActiveSupport::TestCase
684
+ def assert_default_error_message(message, *args)
685
+ assert_equal message, error_message(*args)
693
686
  end
694
687
 
695
- def test_validates_associated_finds_global_default_translation
696
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:invalid => 'global message'}}}
688
+ def error_message(*args)
689
+ ActiveRecord::Error.new(Topic.new, :title, *args).message
690
+ end
697
691
 
698
- Topic.validates_associated :replies
699
- replied_topic.valid?
700
- assert_equal 'global message', replied_topic.errors.on(:replies)
692
+ # used by: validates_inclusion_of
693
+ test "default error message: inclusion" do
694
+ assert_default_error_message 'is not included in the list', :inclusion, :value => 'title'
701
695
  end
702
696
 
703
- def test_validations_with_message_symbol_must_translate
704
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:custom_error => "I am a custom error"}}}
705
- Topic.validates_presence_of :title, :message => :custom_error
706
- @topic.title = nil
707
- @topic.valid?
708
- assert_equal "I am a custom error", @topic.errors.on(:title)
697
+ # used by: validates_exclusion_of
698
+ test "default error message: exclusion" do
699
+ assert_default_error_message 'is reserved', :exclusion, :value => 'title'
709
700
  end
710
701
 
711
- def test_validates_with_message_symbol_must_translate_per_attribute
712
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:models => {:topic => {:attributes => {:title => {:custom_error => "I am a custom error"}}}}}}
713
- Topic.validates_presence_of :title, :message => :custom_error
714
- @topic.title = nil
715
- @topic.valid?
716
- assert_equal "I am a custom error", @topic.errors.on(:title)
702
+ # used by: validates_associated and validates_format_of
703
+ test "default error message: invalid" do
704
+ assert_default_error_message 'is invalid', :invalid, :value => 'title'
717
705
  end
718
706
 
719
- def test_validates_with_message_symbol_must_translate_per_model
720
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:models => {:topic => {:custom_error => "I am a custom error"}}}}
721
- Topic.validates_presence_of :title, :message => :custom_error
722
- @topic.title = nil
723
- @topic.valid?
724
- assert_equal "I am a custom error", @topic.errors.on(:title)
707
+ # used by: validates_confirmation_of
708
+ test "default error message: confirmation" do
709
+ assert_default_error_message "doesn't match confirmation", :confirmation, :default => nil
725
710
  end
726
711
 
727
- def test_validates_with_message_string
728
- Topic.validates_presence_of :title, :message => "I am a custom error"
729
- @topic.title = nil
730
- @topic.valid?
731
- assert_equal "I am a custom error", @topic.errors.on(:title)
712
+ # used by: validates_acceptance_of
713
+ test "default error message: accepted" do
714
+ assert_default_error_message "must be accepted", :accepted
732
715
  end
733
716
 
734
- end
717
+ # used by: add_on_empty
718
+ test "default error message: empty" do
719
+ assert_default_error_message "can't be empty", :empty
720
+ end
735
721
 
736
- class ActiveRecordValidationsGenerateMessageI18nTests < Test::Unit::TestCase
737
- def setup
738
- reset_callbacks Topic
739
- @topic = Topic.new
740
- I18n.backend.store_translations :'en', {
741
- :activerecord => {
742
- :errors => {
743
- :messages => {
744
- :inclusion => "is not included in the list",
745
- :exclusion => "is reserved",
746
- :invalid => "is invalid",
747
- :confirmation => "doesn't match confirmation",
748
- :accepted => "must be accepted",
749
- :empty => "can't be empty",
750
- :blank => "can't be blank",
751
- :too_long => "is too long (maximum is {{count}} characters)",
752
- :too_short => "is too short (minimum is {{count}} characters)",
753
- :wrong_length => "is the wrong length (should be {{count}} characters)",
754
- :taken => "has already been taken",
755
- :not_a_number => "is not a number",
756
- :greater_than => "must be greater than {{count}}",
757
- :greater_than_or_equal_to => "must be greater than or equal to {{count}}",
758
- :equal_to => "must be equal to {{count}}",
759
- :less_than => "must be less than {{count}}",
760
- :less_than_or_equal_to => "must be less than or equal to {{count}}",
761
- :odd => "must be odd",
762
- :even => "must be even"
763
- }
764
- }
765
- }
766
- }
722
+ # used by: add_on_blank
723
+ test "default error message: blank" do
724
+ assert_default_error_message "can't be blank", :blank
767
725
  end
768
726
 
769
- def reset_callbacks(*models)
770
- models.each do |model|
771
- model.instance_variable_set("@validate_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
772
- model.instance_variable_set("@validate_on_create_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
773
- model.instance_variable_set("@validate_on_update_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
774
- end
727
+ # used by: validates_length_of
728
+ test "default error message: too_long" do
729
+ assert_default_error_message "is too long (maximum is 10 characters)", :too_long, :count => 10
775
730
  end
776
731
 
777
- # validates_inclusion_of: generate_message(attr_name, :inclusion, :default => configuration[:message], :value => value)
778
- def test_generate_message_inclusion_with_default_message
779
- assert_equal 'is not included in the list', @topic.errors.generate_message(:title, :inclusion, :default => nil, :value => 'title')
732
+ # used by: validates_length_of
733
+ test "default error message: too_short" do
734
+ assert_default_error_message "is too short (minimum is 10 characters)", :too_short, :count => 10
780
735
  end
781
736
 
782
- def test_generate_message_inclusion_with_custom_message
783
- assert_equal 'custom message title', @topic.errors.generate_message(:title, :inclusion, :default => 'custom message {{value}}', :value => 'title')
737
+ # used by: validates_length_of
738
+ test "default error message: wrong_length" do
739
+ assert_default_error_message "is the wrong length (should be 10 characters)", :wrong_length, :count => 10
784
740
  end
785
741
 
786
- # validates_exclusion_of: generate_message(attr_name, :exclusion, :default => configuration[:message], :value => value)
787
- def test_generate_message_exclusion_with_default_message
788
- assert_equal 'is reserved', @topic.errors.generate_message(:title, :exclusion, :default => nil, :value => 'title')
742
+ # used by: validates_uniqueness_of
743
+ test "default error message: taken" do
744
+ assert_default_error_message "has already been taken", :taken, :value => 'title'
789
745
  end
790
746
 
791
- def test_generate_message_exclusion_with_custom_message
792
- assert_equal 'custom message title', @topic.errors.generate_message(:title, :exclusion, :default => 'custom message {{value}}', :value => 'title')
747
+ # used by: validates_numericality_of
748
+ test "default error message: not_a_number" do
749
+ assert_default_error_message "is not a number", :not_a_number, :value => 'title'
793
750
  end
794
751
 
795
- # validates_associated: generate_message(attr_name, :invalid, :default => configuration[:message], :value => value)
796
- # validates_format_of: generate_message(attr_name, :invalid, :default => configuration[:message], :value => value)
797
- def test_generate_message_invalid_with_default_message
798
- assert_equal 'is invalid', @topic.errors.generate_message(:title, :invalid, :default => nil, :value => 'title')
752
+ # used by: validates_numericality_of
753
+ test "default error message: greater_than" do
754
+ assert_default_error_message "must be greater than 10", :greater_than, :value => 'title', :count => 10
799
755
  end
800
756
 
801
- def test_generate_message_invalid_with_custom_message
802
- assert_equal 'custom message title', @topic.errors.generate_message(:title, :invalid, :default => 'custom message {{value}}', :value => 'title')
757
+ # used by: validates_numericality_of
758
+ test "default error message: greater_than_or_equal_to" do
759
+ assert_default_error_message "must be greater than or equal to 10", :greater_than_or_equal_to, :value => 'title', :count => 10
803
760
  end
804
761
 
805
- # validates_confirmation_of: generate_message(attr_name, :confirmation, :default => configuration[:message])
806
- def test_generate_message_confirmation_with_default_message
807
- assert_equal "doesn't match confirmation", @topic.errors.generate_message(:title, :confirmation, :default => nil)
762
+ # used by: validates_numericality_of
763
+ test "default error message: equal_to" do
764
+ assert_default_error_message "must be equal to 10", :equal_to, :value => 'title', :count => 10
808
765
  end
809
766
 
810
- def test_generate_message_confirmation_with_custom_message
811
- assert_equal 'custom message', @topic.errors.generate_message(:title, :confirmation, :default => 'custom message')
767
+ # used by: validates_numericality_of
768
+ test "default error message: less_than" do
769
+ assert_default_error_message "must be less than 10", :less_than, :value => 'title', :count => 10
812
770
  end
813
771
 
814
- # validates_acceptance_of: generate_message(attr_name, :accepted, :default => configuration[:message])
815
- def test_generate_message_accepted_with_default_message
816
- assert_equal "must be accepted", @topic.errors.generate_message(:title, :accepted, :default => nil)
772
+ # used by: validates_numericality_of
773
+ test "default error message: less_than_or_equal_to" do
774
+ assert_default_error_message "must be less than or equal to 10", :less_than_or_equal_to, :value => 'title', :count => 10
817
775
  end
818
776
 
819
- def test_generate_message_accepted_with_custom_message
820
- assert_equal 'custom message', @topic.errors.generate_message(:title, :accepted, :default => 'custom message')
777
+ # used by: validates_numericality_of
778
+ test "default error message: odd" do
779
+ assert_default_error_message "must be odd", :odd, :value => 'title', :count => 10
821
780
  end
822
781
 
823
- # add_on_empty: generate_message(attr, :empty, :default => custom_message)
824
- def test_generate_message_empty_with_default_message
825
- assert_equal "can't be empty", @topic.errors.generate_message(:title, :empty, :default => nil)
782
+ # used by: validates_numericality_of
783
+ test "default error message: even" do
784
+ assert_default_error_message "must be even", :even, :value => 'title', :count => 10
826
785
  end
827
786
 
828
- def test_generate_message_empty_with_custom_message
829
- assert_equal 'custom message', @topic.errors.generate_message(:title, :empty, :default => 'custom message')
787
+ test "custom message string interpolation" do
788
+ assert_equal 'custom message title', error_message(:invalid, :default => 'custom message {{value}}', :value => 'title')
830
789
  end
790
+ end
791
+
792
+ # ACTIVERECORD VALIDATION ERROR MESSAGES - FULL STACK
793
+ #
794
+ # * test a few combinations full stack to ensure the tests above are correct
831
795
 
832
- # add_on_blank: generate_message(attr, :blank, :default => custom_message)
833
- def test_generate_message_blank_with_default_message
834
- assert_equal "can't be blank", @topic.errors.generate_message(:title, :blank, :default => nil)
796
+ class I18nPerson < Person
797
+ end
798
+
799
+ class ActiveRecordValidationsI18nFullStackTests < ActiveSupport::TestCase
800
+ include ActiveRecordValidationsI18nTestHelper
801
+
802
+ def setup
803
+ reset_callbacks(I18nPerson)
804
+ @old_backend, I18n.backend = I18n.backend, I18n::Backend::Simple.new
805
+ @person = I18nPerson.new
835
806
  end
836
807
 
837
- def test_generate_message_blank_with_custom_message
838
- assert_equal 'custom message', @topic.errors.generate_message(:title, :blank, :default => 'custom message')
808
+ def teardown
809
+ reset_callbacks(I18nPerson)
810
+ I18n.backend = @old_backend
839
811
  end
840
812
 
841
- # validates_length_of: generate_message(attr, :too_long, :default => options[:too_long], :count => option_value.end)
842
- def test_generate_message_too_long_with_default_message
843
- assert_equal "is too long (maximum is 10 characters)", @topic.errors.generate_message(:title, :too_long, :default => nil, :count => 10)
813
+ def assert_name_invalid(message)
814
+ yield
815
+ @person.valid?
816
+ assert_equal message, @person.errors.on(:name)
844
817
  end
845
818
 
846
- def test_generate_message_too_long_with_custom_message
847
- assert_equal 'custom message 10', @topic.errors.generate_message(:title, :too_long, :default => 'custom message {{count}}', :count => 10)
819
+ # Symbols as class-level validation messages
820
+
821
+ test "Symbol as class level validation message translated per attribute (translation on child class)" do
822
+ assert_name_invalid("is broken") do
823
+ store_translations :errors => {:models => {:i18n_person => {:attributes => {:name => {:broken => "is broken"}}}}}
824
+ I18nPerson.validates_presence_of :name, :message => :broken
825
+ end
848
826
  end
849
827
 
850
- # validates_length_of: generate_message(attr, :too_short, :default => options[:too_short], :count => option_value.begin)
851
- def test_generate_message_too_short_with_default_message
852
- assert_equal "is too short (minimum is 10 characters)", @topic.errors.generate_message(:title, :too_short, :default => nil, :count => 10)
828
+ test "Symbol as class level validation message translated per attribute (translation on base class)" do
829
+ assert_name_invalid("is broken") do
830
+ store_translations :errors => {:models => {:person => {:attributes => {:name => {:broken => "is broken"}}}}}
831
+ I18nPerson.validates_presence_of :name, :message => :broken
832
+ end
853
833
  end
854
834
 
855
- def test_generate_message_too_short_with_custom_message
856
- assert_equal 'custom message 10', @topic.errors.generate_message(:title, :too_short, :default => 'custom message {{count}}', :count => 10)
835
+ test "Symbol as class level validation message translated per model (translation on child class)" do
836
+ assert_name_invalid("is broken") do
837
+ store_translations :errors => {:models => {:i18n_person => {:broken => "is broken"}}}
838
+ I18nPerson.validates_presence_of :name, :message => :broken
839
+ end
857
840
  end
858
841
 
859
- # validates_length_of: generate_message(attr, key, :default => custom_message, :count => option_value)
860
- def test_generate_message_wrong_length_with_default_message
861
- assert_equal "is the wrong length (should be 10 characters)", @topic.errors.generate_message(:title, :wrong_length, :default => nil, :count => 10)
842
+ test "Symbol as class level validation message translated per model (translation on base class)" do
843
+ assert_name_invalid("is broken") do
844
+ store_translations :errors => {:models => {:person => {:broken => "is broken"}}}
845
+ I18nPerson.validates_presence_of :name, :message => :broken
846
+ end
862
847
  end
863
848
 
864
- def test_generate_message_wrong_length_with_custom_message
865
- assert_equal 'custom message 10', @topic.errors.generate_message(:title, :wrong_length, :default => 'custom message {{count}}', :count => 10)
849
+ test "Symbol as class level validation message translated as error message" do
850
+ assert_name_invalid("is broken") do
851
+ store_translations :errors => {:messages => {:broken => "is broken"}}
852
+ I18nPerson.validates_presence_of :name, :message => :broken
853
+ end
866
854
  end
867
855
 
868
- # validates_uniqueness_of: generate_message(attr_name, :taken, :default => configuration[:message])
869
- def test_generate_message_taken_with_default_message
870
- assert_equal "has already been taken", @topic.errors.generate_message(:title, :taken, :default => nil, :value => 'title')
856
+ # Strings as class-level validation messages
857
+
858
+ test "String as class level validation message translated per attribute (translation on child class)" do
859
+ assert_name_invalid("is broken") do
860
+ store_translations :errors => {:models => {:i18n_person => {:attributes => {:name => {"is broken" => "is broken"}}}}}
861
+ I18nPerson.validates_presence_of :name, :message => "is broken"
862
+ end
871
863
  end
872
864
 
873
- def test_generate_message_taken_with_custom_message
874
- assert_equal 'custom message title', @topic.errors.generate_message(:title, :taken, :default => 'custom message {{value}}', :value => 'title')
865
+ test "String as class level validation message translated per attribute (translation on base class)" do
866
+ assert_name_invalid("is broken") do
867
+ store_translations :errors => {:models => {:person => {:attributes => {:name => {"is broken" => "is broken"}}}}}
868
+ I18nPerson.validates_presence_of :name, :message => "is broken"
869
+ end
875
870
  end
876
871
 
877
- # validates_numericality_of: generate_message(attr_name, :not_a_number, :value => raw_value, :default => configuration[:message])
878
- def test_generate_message_not_a_number_with_default_message
879
- assert_equal "is not a number", @topic.errors.generate_message(:title, :not_a_number, :default => nil, :value => 'title')
872
+ test "String as class level validation message translated per model (translation on child class)" do
873
+ assert_name_invalid("is broken") do
874
+ store_translations :errors => {:models => {:i18n_person => {"is broken" => "is broken"}}}
875
+ I18nPerson.validates_presence_of :name, :message => "is broken"
876
+ end
880
877
  end
881
878
 
882
- def test_generate_message_not_a_number_with_custom_message
883
- assert_equal 'custom message title', @topic.errors.generate_message(:title, :not_a_number, :default => 'custom message {{value}}', :value => 'title')
879
+ test "String as class level validation message translated per model (translation on base class)" do
880
+ assert_name_invalid("is broken") do
881
+ store_translations :errors => {:models => {:person => {"is broken" => "is broken"}}}
882
+ I18nPerson.validates_presence_of :name, :message => "is broken"
883
+ end
884
884
  end
885
885
 
886
- # validates_numericality_of: generate_message(attr_name, option, :value => raw_value, :default => configuration[:message])
887
- def test_generate_message_greater_than_with_default_message
888
- assert_equal "must be greater than 10", @topic.errors.generate_message(:title, :greater_than, :default => nil, :value => 'title', :count => 10)
886
+ test "String as class level validation message translated as error message" do
887
+ assert_name_invalid("is broken") do
888
+ store_translations :errors => {:messages => {"is broken" => "is broken"}}
889
+ I18nPerson.validates_presence_of :name, :message => "is broken"
890
+ end
889
891
  end
890
892
 
891
- def test_generate_message_greater_than_or_equal_to_with_default_message
892
- assert_equal "must be greater than or equal to 10", @topic.errors.generate_message(:title, :greater_than_or_equal_to, :default => nil, :value => 'title', :count => 10)
893
+ test "String as class level validation message not translated (uses message as default)" do
894
+ assert_name_invalid("is broken!") do
895
+ I18nPerson.validates_presence_of :name, :message => "is broken!"
896
+ end
893
897
  end
898
+ end
899
+
900
+ class ActiveRecordValidationsI18nFullMessagesFullStackTests < ActiveSupport::TestCase
901
+ include ActiveRecordValidationsI18nTestHelper
894
902
 
895
- def test_generate_message_equal_to_with_default_message
896
- assert_equal "must be equal to 10", @topic.errors.generate_message(:title, :equal_to, :default => nil, :value => 'title', :count => 10)
903
+ def setup
904
+ reset_callbacks(I18nPerson)
905
+ @old_backend, I18n.backend = I18n.backend, I18n::Backend::Simple.new
906
+ @person = I18nPerson.new
897
907
  end
898
908
 
899
- def test_generate_message_less_than_with_default_message
900
- assert_equal "must be less than 10", @topic.errors.generate_message(:title, :less_than, :default => nil, :value => 'title', :count => 10)
909
+ def teardown
910
+ reset_callbacks(I18nPerson)
911
+ I18n.backend = @old_backend
901
912
  end
902
913
 
903
- def test_generate_message_less_than_or_equal_to_with_default_message
904
- assert_equal "must be less than or equal to 10", @topic.errors.generate_message(:title, :less_than_or_equal_to, :default => nil, :value => 'title', :count => 10)
914
+ def assert_full_message(message)
915
+ yield
916
+ @person.valid?
917
+ assert_equal message, @person.errors.full_messages.join
905
918
  end
906
919
 
907
- def test_generate_message_odd_with_default_message
908
- assert_equal "must be odd", @topic.errors.generate_message(:title, :odd, :default => nil, :value => 'title', :count => 10)
920
+ test "full_message format stored per custom error message key" do
921
+ assert_full_message("Name is broken!") do
922
+ store_translations :errors => { :messages => { :broken => 'is broken' }, :full_messages => { :broken => '{{attribute}} {{message}}!' } }
923
+ I18nPerson.validates_presence_of :name, :message => :broken
924
+ end
909
925
  end
910
926
 
911
- def test_generate_message_even_with_default_message
912
- assert_equal "must be even", @topic.errors.generate_message(:title, :even, :default => nil, :value => 'title', :count => 10)
927
+ test "full_message format stored per error type" do
928
+ assert_full_message("Name can't be blank!") do
929
+ store_translations :errors => { :full_messages => { :blank => '{{attribute}} {{message}}!' } }
930
+ I18nPerson.validates_presence_of :name
931
+ end
913
932
  end
933
+ # ActiveRecord#RecordInvalid exception
914
934
 
935
+ test "full_message format stored as default" do
936
+ assert_full_message("Name: can't be blank") do
937
+ store_translations :errors => { :full_messages => { :format => '{{attribute}}: {{message}}' } }
938
+ I18nPerson.validates_presence_of :name
939
+ end
940
+ end
941
+ test "RecordInvalid exception can be localized" do
942
+ topic = Topic.new
943
+ topic.errors.add(:title, :invalid)
944
+ topic.errors.add(:title, :blank)
945
+ assert_equal "Validation failed: Title is invalid, Title can't be blank", ActiveRecord::RecordInvalid.new(topic).message
946
+ end
915
947
  end