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.
- data/CHANGES +5 -0
- data/README +4 -2
- data/ext/ibm_db.c +144 -12
- data/ext/ruby_ibm_db_cli.h +1 -0
- data/lib/IBM_DB.rb +1 -1
- data/lib/active_record/connection_adapters/ibm_db_pstmt.rb +62 -1
- data/test/cases/adapter_test.rb +41 -19
- data/test/cases/associations/belongs_to_associations_test.rb +486 -0
- data/test/cases/associations/cascaded_eager_loading_test.rb +53 -3
- data/test/cases/associations/eager_test.rb +42 -22
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +114 -71
- data/test/cases/associations/has_many_through_associations_test.rb +214 -34
- data/test/cases/associations/join_model_test.rb +26 -34
- data/test/cases/attribute_methods_test.rb +387 -78
- data/test/cases/base_test.rb +555 -1183
- data/test/cases/calculations_test.rb +55 -43
- data/test/cases/finder_test.rb +218 -222
- data/test/cases/fixtures_test.rb +44 -20
- data/test/cases/migration_test.rb +638 -242
- data/test/cases/schema_dumper_test.rb +38 -3
- data/test/cases/validations/uniqueness_validation_test.rb +283 -0
- data/test/schema/i5/ibm_db_specific_schema.rb +1 -0
- data/test/schema/ids/ibm_db_specific_schema.rb +1 -0
- data/test/schema/luw/ibm_db_specific_schema.rb +2 -1
- data/test/schema/schema.rb +157 -10
- data/test/schema/zOS/ibm_db_specific_schema.rb +1 -0
- metadata +5 -5
- data/test/cases/helper.rb +0 -75
- data/test/cases/validations_test.rb +0 -1604
@@ -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
|
-
@
|
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(:
|
15
|
-
ActiveRecord::Base.
|
16
|
-
end
|
17
|
-
|
18
|
-
def
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
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
|
-
|
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
|
-
|
62
|
-
|
63
|
-
|
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
|
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
|
-
|
71
|
-
|
72
|
-
|
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
|
-
|
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
|
-
|
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
|