ibm_db 2.5.5 → 2.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,46 +1,326 @@
1
1
  require "cases/helper"
2
- require 'models/topic'
3
2
  require 'models/minimalistic'
3
+ require 'models/developer'
4
+ require 'models/auto_id'
5
+ require 'models/boolean'
6
+ require 'models/computer'
7
+ require 'models/topic'
8
+ require 'models/company'
9
+ require 'models/category'
10
+ require 'models/reply'
4
11
 
5
12
  class AttributeMethodsTest < ActiveRecord::TestCase
6
- fixtures :topics
13
+ fixtures :topics, :developers, :companies, :computers
14
+
7
15
  def setup
8
- @old_suffixes = ActiveRecord::Base.send(:attribute_method_suffixes).dup
16
+ @old_matchers = ActiveRecord::Base.send(:attribute_method_matchers).dup
9
17
  @target = Class.new(ActiveRecord::Base)
10
18
  @target.table_name = 'topics'
11
19
  end
12
-
20
+
13
21
  def teardown
14
- ActiveRecord::Base.send(:attribute_method_suffixes).clear
15
- ActiveRecord::Base.attribute_method_suffix *@old_suffixes
16
- end
17
-
18
- def test_match_attribute_method_query_returns_match_data
19
- assert_not_nil md = @target.match_attribute_method?('title=')
20
- assert_equal 'title', md.pre_match
21
- assert_equal ['='], md.captures
22
-
23
- %w(_hello_world ist! _maybe?).each do |suffix|
24
- @target.class_eval "def attribute#{suffix}(*args) args end"
25
- @target.attribute_method_suffix suffix
26
-
27
- assert_not_nil md = @target.match_attribute_method?("title#{suffix}")
28
- assert_equal 'title', md.pre_match
29
- assert_equal [suffix], md.captures
22
+ ActiveRecord::Base.send(:attribute_method_matchers).clear
23
+ ActiveRecord::Base.send(:attribute_method_matchers).concat(@old_matchers)
24
+ end
25
+
26
+ def test_attribute_present
27
+ t = Topic.new
28
+ t.title = "hello there!"
29
+ t.written_on = Time.now
30
+ assert t.attribute_present?("title")
31
+ assert t.attribute_present?("written_on")
32
+ assert !t.attribute_present?("content")
33
+ end
34
+
35
+ def test_attribute_keys_on_new_instance
36
+ t = Topic.new
37
+ assert_equal nil, t.title, "The topics table has a title column, so it should be nil"
38
+ assert_raise(NoMethodError) { t.title2 }
39
+ end
40
+
41
+ def test_boolean_attributes
42
+ assert ! Topic.find(1).approved?
43
+ assert Topic.find(2).approved?
44
+ end
45
+
46
+ def test_set_attributes
47
+ topic = Topic.find(1)
48
+ topic.attributes = { "title" => "Budget", "author_name" => "Jason" }
49
+ topic.save
50
+ assert_equal("Budget", topic.title)
51
+ assert_equal("Jason", topic.author_name)
52
+ assert_equal(topics(:first).author_email_address, Topic.find(1).author_email_address)
53
+ end
54
+
55
+ def test_set_attributes_without_hash
56
+ topic = Topic.new
57
+ assert_nothing_raised { topic.attributes = '' }
58
+ end
59
+
60
+ def test_integers_as_nil
61
+ test = AutoId.create('value' => '')
62
+ assert_nil AutoId.find(test.id).value
63
+ end
64
+
65
+ def test_set_attributes_with_block
66
+ topic = Topic.new do |t|
67
+ t.title = "Budget"
68
+ t.author_name = "Jason"
30
69
  end
70
+
71
+ assert_equal("Budget", topic.title)
72
+ assert_equal("Jason", topic.author_name)
31
73
  end
32
-
33
- def test_declared_attribute_method_affects_respond_to_and_method_missing
74
+
75
+ def test_respond_to?
76
+ topic = Topic.find(1)
77
+ assert_respond_to topic, "title"
78
+ assert_respond_to topic, "title?"
79
+ assert_respond_to topic, "title="
80
+ assert_respond_to topic, :title
81
+ assert_respond_to topic, :title?
82
+ assert_respond_to topic, :title=
83
+ assert_respond_to topic, "author_name"
84
+ assert_respond_to topic, "attribute_names"
85
+ assert !topic.respond_to?("nothingness")
86
+ assert !topic.respond_to?(:nothingness)
87
+ end
88
+
89
+ def test_array_content
90
+ topic = Topic.new
91
+ topic.content = %w( one two three )
92
+ topic.save
93
+
94
+ assert_equal(%w( one two three ), Topic.find(topic.id).content)
95
+ end
96
+
97
+ def test_read_attributes_before_type_cast
98
+ category = Category.new({:name=>"Test categoty", :type => nil})
99
+ category_attrs = {"name"=>"Test categoty", "type" => nil, "categorizations_count" => nil}
100
+ assert_equal category_attrs , category.attributes_before_type_cast
101
+ end
102
+
103
+ if current_adapter?(:MysqlAdapter)
104
+ def test_read_attributes_before_type_cast_on_boolean
105
+ bool = Boolean.create({ "value" => false })
106
+ assert_equal "0", bool.reload.attributes_before_type_cast["value"]
107
+ end
108
+ end
109
+
110
+ unless current_adapter?(:Mysql2Adapter)
111
+ def test_read_attributes_before_type_cast_on_datetime
112
+ developer = Developer.find(:first)
113
+ # Oracle adapter returns Time before type cast
114
+ unless current_adapter?(:OracleAdapter)
115
+ assert_equal developer.created_at.to_s(:db) , developer.attributes_before_type_cast["created_at"]
116
+ else
117
+ assert_equal developer.created_at.to_s(:db) , developer.attributes_before_type_cast["created_at"].to_s(:db)
118
+
119
+ developer.created_at = "345643456"
120
+ assert_equal developer.created_at_before_type_cast, "345643456"
121
+ assert_equal developer.created_at, nil
122
+
123
+ developer.created_at = "2010-03-21 21:23:32"
124
+ assert_equal developer.created_at_before_type_cast, "2010-03-21 21:23:32"
125
+ assert_equal developer.created_at, Time.parse("2010-03-21 21:23:32")
126
+ end
127
+ end
128
+ end
129
+
130
+ def test_hash_content
131
+ topic = Topic.new
132
+ topic.content = { "one" => 1, "two" => 2 }
133
+ topic.save
134
+
135
+ assert_equal 2, Topic.find(topic.id).content["two"]
136
+
137
+ topic.content_will_change!
138
+ topic.content["three"] = 3
139
+ topic.save
140
+
141
+ assert_equal 3, Topic.find(topic.id).content["three"]
142
+ end
143
+
144
+ def test_update_array_content
145
+ topic = Topic.new
146
+ topic.content = %w( one two three )
147
+
148
+ topic.content.push "four"
149
+ assert_equal(%w( one two three four ), topic.content)
150
+
151
+ topic.save
152
+
153
+ topic = Topic.find(topic.id)
154
+ topic.content << "five"
155
+ assert_equal(%w( one two three four five ), topic.content)
156
+ end
157
+
158
+ def test_case_sensitive_attributes_hash
159
+ # DB2 is not case-sensitive
160
+ return true if current_adapter?(:DB2Adapter)
161
+
162
+ assert_equal @loaded_fixtures['computers']['workstation'].to_hash, Computer.find(:first).attributes
163
+ end
164
+
165
+ def test_hashes_not_mangled
166
+ new_topic = { :title => "New Topic" }
167
+ new_topic_values = { :title => "AnotherTopic" }
168
+
169
+ topic = Topic.new(new_topic)
170
+ assert_equal new_topic[:title], topic.title
171
+
172
+ topic.attributes= new_topic_values
173
+ assert_equal new_topic_values[:title], topic.title
174
+ end
175
+
176
+ def test_create_through_factory
177
+ topic = Topic.create("title" => "New Topic")
178
+ topicReloaded = Topic.find(topic.id)
179
+ assert_equal(topic, topicReloaded)
180
+ end
181
+
182
+ def test_write_attribute
183
+ topic = Topic.new
184
+ topic.send(:write_attribute, :title, "Still another topic")
185
+ assert_equal "Still another topic", topic.title
186
+
187
+ topic.send(:write_attribute, "title", "Still another topic: part 2")
188
+ assert_equal "Still another topic: part 2", topic.title
189
+ end
190
+
191
+ def test_read_attribute
192
+ topic = Topic.new
193
+ topic.title = "Don't change the topic"
194
+ assert_equal "Don't change the topic", topic.send(:read_attribute, "title")
195
+ assert_equal "Don't change the topic", topic["title"]
196
+
197
+ assert_equal "Don't change the topic", topic.send(:read_attribute, :title)
198
+ assert_equal "Don't change the topic", topic[:title]
199
+ end
200
+
201
+ def test_read_attribute_when_false
202
+ topic = topics(:first)
203
+ topic.approved = false
204
+ assert !topic.approved?, "approved should be false"
205
+ topic.approved = "false"
206
+ assert !topic.approved?, "approved should be false"
207
+ end
208
+
209
+ def test_read_attribute_when_true
210
+ topic = topics(:first)
211
+ topic.approved = true
212
+ assert topic.approved?, "approved should be true"
213
+ topic.approved = "true"
214
+ assert topic.approved?, "approved should be true"
215
+ end
216
+
217
+ def test_read_write_boolean_attribute
218
+ topic = Topic.new
219
+ # puts ""
220
+ # puts "New Topic"
221
+ # puts topic.inspect
222
+ topic.approved = "false"
223
+ # puts "Expecting false"
224
+ # puts topic.inspect
225
+ assert !topic.approved?, "approved should be false"
226
+ topic.approved = "false"
227
+ # puts "Expecting false"
228
+ # puts topic.inspect
229
+ assert !topic.approved?, "approved should be false"
230
+ topic.approved = "true"
231
+ # puts "Expecting true"
232
+ # puts topic.inspect
233
+ assert topic.approved?, "approved should be true"
234
+ topic.approved = "true"
235
+ # puts "Expecting true"
236
+ # puts topic.inspect
237
+ assert topic.approved?, "approved should be true"
238
+ # puts ""
239
+ end
240
+
241
+ def test_query_attribute_string
242
+ [nil, "", " "].each do |value|
243
+ assert_equal false, Topic.new(:author_name => value).author_name?
244
+ end
245
+
246
+ assert_equal true, Topic.new(:author_name => "Name").author_name?
247
+ end
248
+
249
+ def test_query_attribute_number
250
+ [nil, 0, "0"].each do |value|
251
+ assert_equal false, Developer.new(:salary => value).salary?
252
+ end
253
+
254
+ assert_equal true, Developer.new(:salary => 1).salary?
255
+ assert_equal true, Developer.new(:salary => "1").salary?
256
+ end
257
+
258
+ def test_query_attribute_boolean
259
+ [nil, "", false, "false", "f", 0].each do |value|
260
+ assert_equal false, Topic.new(:approved => value).approved?
261
+ end
262
+
263
+ [true, "true", "1", 1].each do |value|
264
+ assert_equal true, Topic.new(:approved => value).approved?
265
+ end
266
+ end
267
+
268
+ def test_query_attribute_with_custom_fields
269
+ object = Company.find_by_sql(<<-SQL).first
270
+ SELECT c1.*, c2.ruby_type as string_value, c2.rating as int_value
271
+ FROM companies c1, companies c2
272
+ WHERE c1.firm_id = c2.id
273
+ AND c1.id = 2
274
+ SQL
275
+
276
+ assert_equal "Firm", object.string_value
277
+ assert object.string_value?
278
+
279
+ object.string_value = " "
280
+ assert !object.string_value?
281
+
282
+ assert_equal 1, object.int_value.to_i
283
+ assert object.int_value?
284
+
285
+ object.int_value = "0"
286
+ assert !object.int_value?
287
+ end
288
+
289
+ def test_non_attribute_access_and_assignment
290
+ topic = Topic.new
291
+ assert !topic.respond_to?("mumbo")
292
+ assert_raise(NoMethodError) { topic.mumbo }
293
+ assert_raise(NoMethodError) { topic.mumbo = 5 }
294
+ end
295
+
296
+ def test_undeclared_attribute_method_does_not_affect_respond_to_and_method_missing
34
297
  topic = @target.new(:title => 'Budget')
35
298
  assert topic.respond_to?('title')
36
299
  assert_equal 'Budget', topic.title
37
300
  assert !topic.respond_to?('title_hello_world')
38
301
  assert_raise(NoMethodError) { topic.title_hello_world }
39
-
40
- %w(_hello_world _it! _candidate= able?).each do |suffix|
302
+ end
303
+
304
+ def test_declared_prefixed_attribute_method_affects_respond_to_and_method_missing
305
+ topic = @target.new(:title => 'Budget')
306
+ %w(default_ title_).each do |prefix|
307
+ @target.class_eval "def #{prefix}attribute(*args) args end"
308
+ @target.attribute_method_prefix prefix
309
+
310
+ meth = "#{prefix}title"
311
+ assert topic.respond_to?(meth)
312
+ assert_equal ['title'], topic.send(meth)
313
+ assert_equal ['title', 'a'], topic.send(meth, 'a')
314
+ assert_equal ['title', 1, 2, 3], topic.send(meth, 1, 2, 3)
315
+ end
316
+ end
317
+
318
+ def test_declared_suffixed_attribute_method_affects_respond_to_and_method_missing
319
+ topic = @target.new(:title => 'Budget')
320
+ %w(_default _title_default _it! _candidate= able?).each do |suffix|
41
321
  @target.class_eval "def attribute#{suffix}(*args) args end"
42
322
  @target.attribute_method_suffix suffix
43
-
323
+
44
324
  meth = "title#{suffix}"
45
325
  assert topic.respond_to?(meth)
46
326
  assert_equal ['title'], topic.send(meth)
@@ -48,43 +328,56 @@ class AttributeMethodsTest < ActiveRecord::TestCase
48
328
  assert_equal ['title', 1, 2, 3], topic.send(meth, 1, 2, 3)
49
329
  end
50
330
  end
51
-
331
+
332
+ def test_declared_affixed_attribute_method_affects_respond_to_and_method_missing
333
+ topic = @target.new(:title => 'Budget')
334
+ [['mark_', '_for_update'], ['reset_', '!'], ['default_', '_value?']].each do |prefix, suffix|
335
+ @target.class_eval "def #{prefix}attribute#{suffix}(*args) args end"
336
+ @target.attribute_method_affix({ :prefix => prefix, :suffix => suffix })
337
+
338
+ meth = "#{prefix}title#{suffix}"
339
+ assert topic.respond_to?(meth)
340
+ assert_equal ['title'], topic.send(meth)
341
+ assert_equal ['title', 'a'], topic.send(meth, 'a')
342
+ assert_equal ['title', 1, 2, 3], topic.send(meth, 1, 2, 3)
343
+ end
344
+ end
345
+
52
346
  def test_should_unserialize_attributes_for_frozen_records
53
347
  myobj = {:value1 => :value2}
54
348
  topic = Topic.create("content" => myobj)
55
349
  topic.freeze
56
350
  assert_equal myobj, topic.content
57
351
  end
58
-
352
+
59
353
  def test_typecast_attribute_from_select_to_false
60
354
  topic = Topic.create(:title => 'Budget')
61
- unless current_adapter?(:IBM_DBAdapter)
62
- topic = Topic.find(:first, :select => "topics.*, 1=2 as is_test")
63
- assert !topic.is_test?
355
+ # Oracle does not support boolean expressions in SELECT
356
+ if current_adapter?(:OracleAdapter) || current_adapter?(:IBM_DBAdapter)
357
+ topic = Topic.find(:first, :select => "topics.*, 0 as is_test")
64
358
  else
65
- topic = Topic.find(:first, :select => "topics.approved as is_test")
66
- assert topic.is_test?
359
+ topic = Topic.find(:first, :select => "topics.*, 1=2 as is_test")
67
360
  end
361
+ assert !topic.is_test?
68
362
  end
69
-
70
- unless current_adapter?(:IBM_DBAdapter)
71
- def test_typecast_attribute_from_select_to_true
72
- topic = Topic.create(:title => 'Budget')
363
+
364
+ def test_typecast_attribute_from_select_to_true
365
+ topic = Topic.create(:title => 'Budget')
366
+ # Oracle does not support boolean expressions in SELECT
367
+ if current_adapter?(:OracleAdapter) || current_adapter?(:IBM_DBAdapter)
368
+ topic = Topic.find(:first, :select => "topics.*, 1 as is_test")
369
+ else
73
370
  topic = Topic.find(:first, :select => "topics.*, 2=2 as is_test")
74
- assert topic.is_test?
75
371
  end
372
+ assert topic.is_test?
76
373
  end
77
-
374
+
78
375
  def test_kernel_methods_not_implemented_in_activerecord
79
376
  %w(test name display y).each do |method|
80
377
  assert !ActiveRecord::Base.instance_method_already_implemented?(method), "##{method} is defined"
81
378
  end
82
379
  end
83
-
84
- def test_primary_key_implemented
85
- assert Class.new(ActiveRecord::Base).instance_method_already_implemented?('id')
86
- end
87
-
380
+
88
381
  def test_defined_kernel_methods_implemented_in_model
89
382
  %w(test name display y).each do |method|
90
383
  klass = Class.new ActiveRecord::Base
@@ -92,7 +385,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
92
385
  assert klass.instance_method_already_implemented?(method), "##{method} is not defined"
93
386
  end
94
387
  end
95
-
388
+
96
389
  def test_defined_kernel_methods_implemented_in_model_abstract_subclass
97
390
  %w(test name display y).each do |method|
98
391
  abstract = Class.new ActiveRecord::Base
@@ -102,7 +395,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
102
395
  assert klass.instance_method_already_implemented?(method), "##{method} is not defined"
103
396
  end
104
397
  end
105
-
398
+
106
399
  def test_raises_dangerous_attribute_error_when_defining_activerecord_method_in_model
107
400
  %w(save create_or_update).each do |method|
108
401
  klass = Class.new ActiveRecord::Base
@@ -112,12 +405,12 @@ class AttributeMethodsTest < ActiveRecord::TestCase
112
405
  end
113
406
  end
114
407
  end
115
-
408
+
116
409
  def test_only_time_related_columns_are_meant_to_be_cached_by_default
117
410
  expected = %w(datetime timestamp time date).sort
118
411
  assert_equal expected, ActiveRecord::Base.attribute_types_cached_by_default.map(&:to_s).sort
119
412
  end
120
-
413
+
121
414
  def test_declaring_attributes_as_cached_adds_them_to_the_attributes_cached_by_default
122
415
  default_attributes = Topic.cached_attributes
123
416
  Topic.cache_attributes :replies_count
@@ -125,26 +418,26 @@ class AttributeMethodsTest < ActiveRecord::TestCase
125
418
  assert_equal expected.sort, Topic.cached_attributes.sort
126
419
  Topic.instance_variable_set "@cached_attributes", nil
127
420
  end
128
-
421
+
129
422
  def test_time_related_columns_are_actually_cached
130
423
  column_types = %w(datetime timestamp time date).map(&:to_sym)
131
424
  column_names = Topic.columns.select{|c| column_types.include?(c.type) }.map(&:name)
132
-
425
+
133
426
  assert_equal column_names.sort, Topic.cached_attributes.sort
134
427
  assert_equal time_related_columns_on_topic.sort, Topic.cached_attributes.sort
135
428
  end
136
-
429
+
137
430
  def test_accessing_cached_attributes_caches_the_converted_values_and_nothing_else
138
431
  t = topics(:first)
139
432
  cache = t.instance_variable_get "@attributes_cache"
140
-
433
+
141
434
  assert_not_nil cache
142
435
  assert cache.empty?
143
-
436
+
144
437
  all_columns = Topic.columns.map(&:name)
145
438
  cached_columns = time_related_columns_on_topic
146
439
  uncached_columns = all_columns - cached_columns
147
-
440
+
148
441
  all_columns.each do |attr_name|
149
442
  attribute_gets_cached = Topic.cache_attribute?(attr_name)
150
443
  val = t.send attr_name unless attr_name == "type"
@@ -157,7 +450,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
157
450
  end
158
451
  end
159
452
  end
160
-
453
+
161
454
  def test_time_attributes_are_retrieved_in_current_time_zone
162
455
  in_time_zone "Pacific Time (US & Canada)" do
163
456
  utc_time = Time.utc(2008, 1, 1)
@@ -169,7 +462,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
169
462
  assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time # and represents time values adjusted accordingly
170
463
  end
171
464
  end
172
-
465
+
173
466
  def test_setting_time_zone_aware_attribute_to_utc
174
467
  in_time_zone "Pacific Time (US & Canada)" do
175
468
  utc_time = Time.utc(2008, 1, 1)
@@ -180,7 +473,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
180
473
  assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
181
474
  end
182
475
  end
183
-
476
+
184
477
  def test_setting_time_zone_aware_attribute_in_other_time_zone
185
478
  utc_time = Time.utc(2008, 1, 1)
186
479
  cst_time = utc_time.in_time_zone("Central Time (US & Canada)")
@@ -192,10 +485,10 @@ class AttributeMethodsTest < ActiveRecord::TestCase
192
485
  assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
193
486
  end
194
487
  end
195
-
488
+
196
489
  def test_setting_time_zone_aware_attribute_with_string
197
490
  utc_time = Time.utc(2008, 1, 1)
198
- (-11..13).each do |timezone_offset|
491
+ (-11..13).each do |timezone_offset|
199
492
  time_string = utc_time.in_time_zone(timezone_offset).to_s
200
493
  in_time_zone "Pacific Time (US & Canada)" do
201
494
  record = @target.new
@@ -206,7 +499,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
206
499
  end
207
500
  end
208
501
  end
209
-
502
+
210
503
  def test_setting_time_zone_aware_attribute_to_blank_string_returns_nil
211
504
  in_time_zone "Pacific Time (US & Canada)" do
212
505
  record = @target.new
@@ -214,10 +507,10 @@ class AttributeMethodsTest < ActiveRecord::TestCase
214
507
  assert_nil record.written_on
215
508
  end
216
509
  end
217
-
510
+
218
511
  def test_setting_time_zone_aware_attribute_interprets_time_zone_unaware_string_in_time_zone
219
512
  time_string = 'Tue Jan 01 00:00:00 2008'
220
- (-11..13).each do |timezone_offset|
513
+ (-11..13).each do |timezone_offset|
221
514
  in_time_zone timezone_offset do
222
515
  record = @target.new
223
516
  record.written_on = time_string
@@ -227,7 +520,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
227
520
  end
228
521
  end
229
522
  end
230
-
523
+
231
524
  def test_setting_time_zone_aware_attribute_in_current_time_zone
232
525
  utc_time = Time.utc(2008, 1, 1)
233
526
  in_time_zone "Pacific Time (US & Canada)" do
@@ -238,61 +531,77 @@ class AttributeMethodsTest < ActiveRecord::TestCase
238
531
  assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
239
532
  end
240
533
  end
241
-
534
+
242
535
  def test_setting_time_zone_conversion_for_attributes_should_write_value_on_class_variable
243
536
  Topic.skip_time_zone_conversion_for_attributes = [:field_a]
244
537
  Minimalistic.skip_time_zone_conversion_for_attributes = [:field_b]
245
-
246
- assert_equal [:field_a], Topic.skip_time_zone_conversion_for_attributes
247
- assert_equal [:field_b], Minimalistic.skip_time_zone_conversion_for_attributes
538
+
539
+ assert_equal [:field_a], Topic.skip_time_zone_conversion_for_attributes
540
+ assert_equal [:field_b], Minimalistic.skip_time_zone_conversion_for_attributes
248
541
  end
249
-
542
+
250
543
  def test_read_attributes_respect_access_control
251
544
  privatize("title")
252
-
545
+
253
546
  topic = @target.new(:title => "The pros and cons of programming naked.")
254
547
  assert !topic.respond_to?(:title)
255
548
  exception = assert_raise(NoMethodError) { topic.title }
256
549
  assert_equal "Attempt to call private method", exception.message
257
550
  assert_equal "I'm private", topic.send(:title)
258
551
  end
259
-
552
+
260
553
  def test_write_attributes_respect_access_control
261
554
  privatize("title=(value)")
262
-
555
+
263
556
  topic = @target.new
264
557
  assert !topic.respond_to?(:title=)
265
558
  exception = assert_raise(NoMethodError) { topic.title = "Pants"}
266
559
  assert_equal "Attempt to call private method", exception.message
267
560
  topic.send(:title=, "Very large pants")
268
561
  end
269
-
562
+
270
563
  def test_question_attributes_respect_access_control
271
564
  privatize("title?")
272
-
565
+
273
566
  topic = @target.new(:title => "Isaac Newton's pants")
274
567
  assert !topic.respond_to?(:title?)
275
568
  exception = assert_raise(NoMethodError) { topic.title? }
276
569
  assert_equal "Attempt to call private method", exception.message
277
570
  assert topic.send(:title?)
278
571
  end
279
-
572
+
280
573
  def test_bulk_update_respects_access_control
281
574
  privatize("title=(value)")
282
-
575
+
283
576
  assert_raise(ActiveRecord::UnknownAttributeError) { topic = @target.new(:title => "Rants about pants") }
284
577
  assert_raise(ActiveRecord::UnknownAttributeError) { @target.new.attributes = { :title => "Ants in pants" } }
285
578
  end
286
-
579
+
580
+ def test_read_attribute_overwrites_private_method_not_considered_implemented
581
+ # simulate a model with a db column that shares its name an inherited
582
+ # private method (e.g. Object#system)
583
+ #
584
+ Object.class_eval do
585
+ private
586
+ def title; "private!"; end
587
+ end
588
+ assert !@target.instance_method_already_implemented?(:title)
589
+ topic = @target.new
590
+ assert_nil topic.title
591
+
592
+ Object.send(:undef_method, :title) # remove test method from object
593
+ end
594
+
595
+
287
596
  private
288
597
  def time_related_columns_on_topic
289
598
  Topic.columns.select{|c| [:time, :date, :datetime, :timestamp].include?(c.type)}.map(&:name)
290
599
  end
291
-
600
+
292
601
  def in_time_zone(zone)
293
602
  old_zone = Time.zone
294
603
  old_tz = ActiveRecord::Base.time_zone_aware_attributes
295
-
604
+
296
605
  Time.zone = zone ? ActiveSupport::TimeZone[zone] : nil
297
606
  ActiveRecord::Base.time_zone_aware_attributes = !zone.nil?
298
607
  yield
@@ -300,7 +609,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
300
609
  Time.zone = old_zone
301
610
  ActiveRecord::Base.time_zone_aware_attributes = old_tz
302
611
  end
303
-
612
+
304
613
  def privatize(method_signature)
305
614
  @target.class_eval <<-private_method
306
615
  private