ibm_db 1.0.2 → 1.0.5
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 +8 -0
- data/README +1 -1
- data/ext/ibm_db.c +9 -6
- data/ext/ruby_ibm_db.h +9 -1
- data/lib/active_record/connection_adapters/ibm_db_adapter.rb +33 -16
- data/test/cases/associations/cascaded_eager_loading_test.rb +8 -0
- data/test/cases/associations/eager_test.rb +140 -8
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +77 -28
- data/test/cases/associations/has_many_through_associations_test.rb +39 -7
- data/test/cases/associations/join_model_test.rb +5 -7
- data/test/cases/attribute_methods_test.rb +312 -0
- data/test/cases/base_test.rb +44 -24
- data/test/cases/calculations_test.rb +37 -17
- data/test/cases/finder_test.rb +79 -44
- data/test/cases/fixtures_test.rb +15 -19
- data/test/cases/migration_test.rb +91 -67
- data/test/cases/query_cache_test.rb +20 -24
- data/test/cases/schema_dumper_test.rb +0 -1
- data/test/cases/validations_test.rb +228 -178
- data/test/schema/schema.rb +484 -451
- metadata +4 -3
@@ -1,11 +1,19 @@
|
|
1
1
|
require "cases/helper"
|
2
2
|
require 'models/post'
|
3
3
|
require 'models/person'
|
4
|
+
require 'models/reference'
|
5
|
+
require 'models/job'
|
4
6
|
require 'models/reader'
|
5
7
|
require 'models/comment'
|
8
|
+
require 'models/tag'
|
9
|
+
require 'models/tagging'
|
10
|
+
require 'models/author'
|
11
|
+
require 'models/owner'
|
12
|
+
require 'models/pet'
|
13
|
+
require 'models/toy'
|
6
14
|
|
7
15
|
class HasManyThroughAssociationsTest < ActiveRecord::TestCase
|
8
|
-
fixtures :posts, :readers, :people, :comments, :authors
|
16
|
+
fixtures :posts, :readers, :people, :comments, :authors, :owners, :pets, :toys
|
9
17
|
|
10
18
|
def test_associate_existing
|
11
19
|
assert_queries(2) { posts(:thinking);people(:david) }
|
@@ -84,6 +92,24 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
|
|
84
92
|
assert posts(:welcome).reload.people(true).empty?
|
85
93
|
end
|
86
94
|
|
95
|
+
def test_destroy_association
|
96
|
+
assert_difference "Person.count", -1 do
|
97
|
+
posts(:welcome).people.destroy(people(:michael))
|
98
|
+
end
|
99
|
+
|
100
|
+
assert posts(:welcome).reload.people.empty?
|
101
|
+
assert posts(:welcome).people(true).empty?
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_destroy_all
|
105
|
+
assert_difference "Person.count", -1 do
|
106
|
+
posts(:welcome).people.destroy_all
|
107
|
+
end
|
108
|
+
|
109
|
+
assert posts(:welcome).reload.people.empty?
|
110
|
+
assert posts(:welcome).people(true).empty?
|
111
|
+
end
|
112
|
+
|
87
113
|
def test_replace_association
|
88
114
|
assert_queries(4){posts(:welcome);people(:david);people(:michael); posts(:welcome).people(true)}
|
89
115
|
|
@@ -203,6 +229,10 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
|
|
203
229
|
assert_equal 2, people(:michael).posts.count(:include => :readers)
|
204
230
|
end
|
205
231
|
|
232
|
+
def test_inner_join_with_quoted_table_name
|
233
|
+
assert_equal 2, people(:michael).jobs.size
|
234
|
+
end
|
235
|
+
|
206
236
|
def test_get_ids
|
207
237
|
assert_equal [posts(:welcome).id, posts(:authorless).id].sort, people(:michael).post_ids.sort
|
208
238
|
end
|
@@ -223,12 +253,10 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
|
|
223
253
|
assert !person.posts.loaded?
|
224
254
|
end
|
225
255
|
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
# nothing
|
231
|
-
end
|
256
|
+
def test_association_proxy_transaction_method_starts_transaction_in_association_class
|
257
|
+
Tag.expects(:transaction)
|
258
|
+
Post.find(:first).tags.transaction do
|
259
|
+
# nothing
|
232
260
|
end
|
233
261
|
end
|
234
262
|
|
@@ -246,4 +274,8 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
|
|
246
274
|
author.author_favorites.create(:favorite_author_id => 3)
|
247
275
|
assert_equal post.author.author_favorites, post.author_favorites
|
248
276
|
end
|
277
|
+
|
278
|
+
def test_has_many_association_through_a_has_many_association_with_nonstandard_primary_keys
|
279
|
+
assert_equal 1, owners(:blackbeard).toys.count
|
280
|
+
end
|
249
281
|
end
|
@@ -568,13 +568,11 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
|
|
568
568
|
assert !author.comments.loaded?
|
569
569
|
end
|
570
570
|
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
assert !author.comments.loaded?
|
577
|
-
end
|
571
|
+
def test_has_many_through_collection_size_uses_counter_cache_if_it_exists
|
572
|
+
author = authors(:david)
|
573
|
+
author.stubs(:read_attribute).with('comments_count').returns(100)
|
574
|
+
assert_equal 100, author.comments.size
|
575
|
+
assert !author.comments.loaded?
|
578
576
|
end
|
579
577
|
|
580
578
|
def test_adding_junk_to_has_many_through_should_raise_type_mismatch
|
@@ -0,0 +1,312 @@
|
|
1
|
+
require "cases/helper"
|
2
|
+
require 'models/topic'
|
3
|
+
require 'models/minimalistic'
|
4
|
+
|
5
|
+
class AttributeMethodsTest < ActiveRecord::TestCase
|
6
|
+
fixtures :topics
|
7
|
+
def setup
|
8
|
+
@old_suffixes = ActiveRecord::Base.send(:attribute_method_suffixes).dup
|
9
|
+
@target = Class.new(ActiveRecord::Base)
|
10
|
+
@target.table_name = 'topics'
|
11
|
+
end
|
12
|
+
|
13
|
+
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
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_declared_attribute_method_affects_respond_to_and_method_missing
|
34
|
+
topic = @target.new(:title => 'Budget')
|
35
|
+
assert topic.respond_to?('title')
|
36
|
+
assert_equal 'Budget', topic.title
|
37
|
+
assert !topic.respond_to?('title_hello_world')
|
38
|
+
assert_raise(NoMethodError) { topic.title_hello_world }
|
39
|
+
|
40
|
+
%w(_hello_world _it! _candidate= able?).each do |suffix|
|
41
|
+
@target.class_eval "def attribute#{suffix}(*args) args end"
|
42
|
+
@target.attribute_method_suffix suffix
|
43
|
+
|
44
|
+
meth = "title#{suffix}"
|
45
|
+
assert topic.respond_to?(meth)
|
46
|
+
assert_equal ['title'], topic.send(meth)
|
47
|
+
assert_equal ['title', 'a'], topic.send(meth, 'a')
|
48
|
+
assert_equal ['title', 1, 2, 3], topic.send(meth, 1, 2, 3)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_should_unserialize_attributes_for_frozen_records
|
53
|
+
myobj = {:value1 => :value2}
|
54
|
+
topic = Topic.create("content" => myobj)
|
55
|
+
topic.freeze
|
56
|
+
assert_equal myobj, topic.content
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_typecast_attribute_from_select_to_false
|
60
|
+
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?
|
64
|
+
else
|
65
|
+
topic = Topic.find(:first, :select => "topics.approved as is_test")
|
66
|
+
assert topic.is_test?
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
unless current_adapter?(:IBM_DBAdapter)
|
71
|
+
def test_typecast_attribute_from_select_to_true
|
72
|
+
topic = Topic.create(:title => 'Budget')
|
73
|
+
topic = Topic.find(:first, :select => "topics.*, 2=2 as is_test")
|
74
|
+
assert topic.is_test?
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_kernel_methods_not_implemented_in_activerecord
|
79
|
+
%w(test name display y).each do |method|
|
80
|
+
assert !ActiveRecord::Base.instance_method_already_implemented?(method), "##{method} is defined"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_primary_key_implemented
|
85
|
+
assert Class.new(ActiveRecord::Base).instance_method_already_implemented?('id')
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_defined_kernel_methods_implemented_in_model
|
89
|
+
%w(test name display y).each do |method|
|
90
|
+
klass = Class.new ActiveRecord::Base
|
91
|
+
klass.class_eval "def #{method}() 'defined #{method}' end"
|
92
|
+
assert klass.instance_method_already_implemented?(method), "##{method} is not defined"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_defined_kernel_methods_implemented_in_model_abstract_subclass
|
97
|
+
%w(test name display y).each do |method|
|
98
|
+
abstract = Class.new ActiveRecord::Base
|
99
|
+
abstract.class_eval "def #{method}() 'defined #{method}' end"
|
100
|
+
abstract.abstract_class = true
|
101
|
+
klass = Class.new abstract
|
102
|
+
assert klass.instance_method_already_implemented?(method), "##{method} is not defined"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_raises_dangerous_attribute_error_when_defining_activerecord_method_in_model
|
107
|
+
%w(save create_or_update).each do |method|
|
108
|
+
klass = Class.new ActiveRecord::Base
|
109
|
+
klass.class_eval "def #{method}() 'defined #{method}' end"
|
110
|
+
assert_raise ActiveRecord::DangerousAttributeError do
|
111
|
+
klass.instance_method_already_implemented?(method)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_only_time_related_columns_are_meant_to_be_cached_by_default
|
117
|
+
expected = %w(datetime timestamp time date).sort
|
118
|
+
assert_equal expected, ActiveRecord::Base.attribute_types_cached_by_default.map(&:to_s).sort
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_declaring_attributes_as_cached_adds_them_to_the_attributes_cached_by_default
|
122
|
+
default_attributes = Topic.cached_attributes
|
123
|
+
Topic.cache_attributes :replies_count
|
124
|
+
expected = default_attributes + ["replies_count"]
|
125
|
+
assert_equal expected.sort, Topic.cached_attributes.sort
|
126
|
+
Topic.instance_variable_set "@cached_attributes", nil
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_time_related_columns_are_actually_cached
|
130
|
+
column_types = %w(datetime timestamp time date).map(&:to_sym)
|
131
|
+
column_names = Topic.columns.select{|c| column_types.include?(c.type) }.map(&:name)
|
132
|
+
|
133
|
+
assert_equal column_names.sort, Topic.cached_attributes.sort
|
134
|
+
assert_equal time_related_columns_on_topic.sort, Topic.cached_attributes.sort
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_accessing_cached_attributes_caches_the_converted_values_and_nothing_else
|
138
|
+
t = topics(:first)
|
139
|
+
cache = t.instance_variable_get "@attributes_cache"
|
140
|
+
|
141
|
+
assert_not_nil cache
|
142
|
+
assert cache.empty?
|
143
|
+
|
144
|
+
all_columns = Topic.columns.map(&:name)
|
145
|
+
cached_columns = time_related_columns_on_topic
|
146
|
+
uncached_columns = all_columns - cached_columns
|
147
|
+
|
148
|
+
all_columns.each do |attr_name|
|
149
|
+
attribute_gets_cached = Topic.cache_attribute?(attr_name)
|
150
|
+
val = t.send attr_name unless attr_name == "type"
|
151
|
+
if attribute_gets_cached
|
152
|
+
assert cached_columns.include?(attr_name)
|
153
|
+
assert_equal val, cache[attr_name]
|
154
|
+
else
|
155
|
+
assert uncached_columns.include?(attr_name)
|
156
|
+
assert !cache.include?(attr_name)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def test_time_attributes_are_retrieved_in_current_time_zone
|
162
|
+
in_time_zone "Pacific Time (US & Canada)" do
|
163
|
+
utc_time = Time.utc(2008, 1, 1)
|
164
|
+
record = @target.new
|
165
|
+
record[:written_on] = utc_time
|
166
|
+
assert_equal utc_time, record.written_on # record.written on is equal to (i.e., simultaneous with) utc_time
|
167
|
+
assert_kind_of ActiveSupport::TimeWithZone, record.written_on # but is a TimeWithZone
|
168
|
+
assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone # and is in the current Time.zone
|
169
|
+
assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time # and represents time values adjusted accordingly
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_setting_time_zone_aware_attribute_to_utc
|
174
|
+
in_time_zone "Pacific Time (US & Canada)" do
|
175
|
+
utc_time = Time.utc(2008, 1, 1)
|
176
|
+
record = @target.new
|
177
|
+
record.written_on = utc_time
|
178
|
+
assert_equal utc_time, record.written_on
|
179
|
+
assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
|
180
|
+
assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def test_setting_time_zone_aware_attribute_in_other_time_zone
|
185
|
+
utc_time = Time.utc(2008, 1, 1)
|
186
|
+
cst_time = utc_time.in_time_zone("Central Time (US & Canada)")
|
187
|
+
in_time_zone "Pacific Time (US & Canada)" do
|
188
|
+
record = @target.new
|
189
|
+
record.written_on = cst_time
|
190
|
+
assert_equal utc_time, record.written_on
|
191
|
+
assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
|
192
|
+
assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def test_setting_time_zone_aware_attribute_with_string
|
197
|
+
utc_time = Time.utc(2008, 1, 1)
|
198
|
+
(-11..13).each do |timezone_offset|
|
199
|
+
time_string = utc_time.in_time_zone(timezone_offset).to_s
|
200
|
+
in_time_zone "Pacific Time (US & Canada)" do
|
201
|
+
record = @target.new
|
202
|
+
record.written_on = time_string
|
203
|
+
assert_equal Time.zone.parse(time_string), record.written_on
|
204
|
+
assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
|
205
|
+
assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def test_setting_time_zone_aware_attribute_to_blank_string_returns_nil
|
211
|
+
in_time_zone "Pacific Time (US & Canada)" do
|
212
|
+
record = @target.new
|
213
|
+
record.written_on = ' '
|
214
|
+
assert_nil record.written_on
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def test_setting_time_zone_aware_attribute_interprets_time_zone_unaware_string_in_time_zone
|
219
|
+
time_string = 'Tue Jan 01 00:00:00 2008'
|
220
|
+
(-11..13).each do |timezone_offset|
|
221
|
+
in_time_zone timezone_offset do
|
222
|
+
record = @target.new
|
223
|
+
record.written_on = time_string
|
224
|
+
assert_equal Time.zone.parse(time_string), record.written_on
|
225
|
+
assert_equal ActiveSupport::TimeZone[timezone_offset], record.written_on.time_zone
|
226
|
+
assert_equal Time.utc(2008, 1, 1), record.written_on.time
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def test_setting_time_zone_aware_attribute_in_current_time_zone
|
232
|
+
utc_time = Time.utc(2008, 1, 1)
|
233
|
+
in_time_zone "Pacific Time (US & Canada)" do
|
234
|
+
record = @target.new
|
235
|
+
record.written_on = utc_time.in_time_zone
|
236
|
+
assert_equal utc_time, record.written_on
|
237
|
+
assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
|
238
|
+
assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def test_setting_time_zone_conversion_for_attributes_should_write_value_on_class_variable
|
243
|
+
Topic.skip_time_zone_conversion_for_attributes = [:field_a]
|
244
|
+
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
|
248
|
+
end
|
249
|
+
|
250
|
+
def test_read_attributes_respect_access_control
|
251
|
+
privatize("title")
|
252
|
+
|
253
|
+
topic = @target.new(:title => "The pros and cons of programming naked.")
|
254
|
+
assert !topic.respond_to?(:title)
|
255
|
+
exception = assert_raise(NoMethodError) { topic.title }
|
256
|
+
assert_equal "Attempt to call private method", exception.message
|
257
|
+
assert_equal "I'm private", topic.send(:title)
|
258
|
+
end
|
259
|
+
|
260
|
+
def test_write_attributes_respect_access_control
|
261
|
+
privatize("title=(value)")
|
262
|
+
|
263
|
+
topic = @target.new
|
264
|
+
assert !topic.respond_to?(:title=)
|
265
|
+
exception = assert_raise(NoMethodError) { topic.title = "Pants"}
|
266
|
+
assert_equal "Attempt to call private method", exception.message
|
267
|
+
topic.send(:title=, "Very large pants")
|
268
|
+
end
|
269
|
+
|
270
|
+
def test_question_attributes_respect_access_control
|
271
|
+
privatize("title?")
|
272
|
+
|
273
|
+
topic = @target.new(:title => "Isaac Newton's pants")
|
274
|
+
assert !topic.respond_to?(:title?)
|
275
|
+
exception = assert_raise(NoMethodError) { topic.title? }
|
276
|
+
assert_equal "Attempt to call private method", exception.message
|
277
|
+
assert topic.send(:title?)
|
278
|
+
end
|
279
|
+
|
280
|
+
def test_bulk_update_respects_access_control
|
281
|
+
privatize("title=(value)")
|
282
|
+
|
283
|
+
assert_raise(ActiveRecord::UnknownAttributeError) { topic = @target.new(:title => "Rants about pants") }
|
284
|
+
assert_raise(ActiveRecord::UnknownAttributeError) { @target.new.attributes = { :title => "Ants in pants" } }
|
285
|
+
end
|
286
|
+
|
287
|
+
private
|
288
|
+
def time_related_columns_on_topic
|
289
|
+
Topic.columns.select{|c| [:time, :date, :datetime, :timestamp].include?(c.type)}.map(&:name)
|
290
|
+
end
|
291
|
+
|
292
|
+
def in_time_zone(zone)
|
293
|
+
old_zone = Time.zone
|
294
|
+
old_tz = ActiveRecord::Base.time_zone_aware_attributes
|
295
|
+
|
296
|
+
Time.zone = zone ? ActiveSupport::TimeZone[zone] : nil
|
297
|
+
ActiveRecord::Base.time_zone_aware_attributes = !zone.nil?
|
298
|
+
yield
|
299
|
+
ensure
|
300
|
+
Time.zone = old_zone
|
301
|
+
ActiveRecord::Base.time_zone_aware_attributes = old_tz
|
302
|
+
end
|
303
|
+
|
304
|
+
def privatize(method_signature)
|
305
|
+
@target.class_eval <<-private_method
|
306
|
+
private
|
307
|
+
def #{method_signature}
|
308
|
+
"I'm private"
|
309
|
+
end
|
310
|
+
private_method
|
311
|
+
end
|
312
|
+
end
|
data/test/cases/base_test.rb
CHANGED
@@ -16,6 +16,7 @@ require 'models/post'
|
|
16
16
|
require 'models/comment'
|
17
17
|
require 'models/minimalistic'
|
18
18
|
require 'models/warehouse_thing'
|
19
|
+
require 'models/parrot'
|
19
20
|
require 'rexml/document'
|
20
21
|
|
21
22
|
class Category < ActiveRecord::Base; end
|
@@ -423,8 +424,8 @@ class BasicsTest < ActiveRecord::TestCase
|
|
423
424
|
def test_non_attribute_access_and_assignment
|
424
425
|
topic = Topic.new
|
425
426
|
assert !topic.respond_to?("mumbo")
|
426
|
-
|
427
|
-
|
427
|
+
assert_raise(NoMethodError) { topic.mumbo }
|
428
|
+
assert_raise(NoMethodError) { topic.mumbo = 5 }
|
428
429
|
end
|
429
430
|
|
430
431
|
def test_preserving_date_objects
|
@@ -489,7 +490,7 @@ class BasicsTest < ActiveRecord::TestCase
|
|
489
490
|
end
|
490
491
|
|
491
492
|
def test_record_not_found_exception
|
492
|
-
|
493
|
+
assert_raise(ActiveRecord::RecordNotFound) { topicReloaded = Topic.find(99999) }
|
493
494
|
end
|
494
495
|
|
495
496
|
def test_initialize_with_attributes
|
@@ -638,6 +639,13 @@ class BasicsTest < ActiveRecord::TestCase
|
|
638
639
|
category.reload
|
639
640
|
assert_not_nil category.categorizations_count
|
640
641
|
assert_equal 4, category.categorizations_count
|
642
|
+
|
643
|
+
category_2 = categories(:technology)
|
644
|
+
count_1, count_2 = (category.categorizations_count || 0), (category_2.categorizations_count || 0)
|
645
|
+
Category.update_counters([category.id, category_2.id], "categorizations_count" => 2)
|
646
|
+
category.reload; category_2.reload
|
647
|
+
assert_equal count_1 + 2, category.categorizations_count
|
648
|
+
assert_equal count_2 + 2, category_2.categorizations_count
|
641
649
|
end
|
642
650
|
|
643
651
|
def test_update_all
|
@@ -840,7 +848,7 @@ class BasicsTest < ActiveRecord::TestCase
|
|
840
848
|
client.delete
|
841
849
|
assert client.frozen?
|
842
850
|
assert_kind_of Firm, client.firm
|
843
|
-
|
851
|
+
assert_raise(ActiveSupport::FrozenObjectError) { client.name = "something else" }
|
844
852
|
end
|
845
853
|
|
846
854
|
def test_destroy_new_record
|
@@ -854,7 +862,7 @@ class BasicsTest < ActiveRecord::TestCase
|
|
854
862
|
client.destroy
|
855
863
|
assert client.frozen?
|
856
864
|
assert_kind_of Firm, client.firm
|
857
|
-
|
865
|
+
assert_raise(ActiveSupport::FrozenObjectError) { client.name = "something else" }
|
858
866
|
end
|
859
867
|
|
860
868
|
def test_update_attribute
|
@@ -902,8 +910,8 @@ class BasicsTest < ActiveRecord::TestCase
|
|
902
910
|
|
903
911
|
def test_mass_assignment_should_raise_exception_if_accessible_and_protected_attribute_writers_are_both_used
|
904
912
|
topic = TopicWithProtectedContentAndAccessibleAuthorName.new
|
905
|
-
|
906
|
-
|
913
|
+
assert_raise(RuntimeError) { topic.attributes = { "author_name" => "me" } }
|
914
|
+
assert_raise(RuntimeError) { topic.attributes = { "content" => "stuff" } }
|
907
915
|
end
|
908
916
|
|
909
917
|
def test_mass_assignment_protection
|
@@ -941,7 +949,7 @@ class BasicsTest < ActiveRecord::TestCase
|
|
941
949
|
def test_mass_assigning_invalid_attribute
|
942
950
|
firm = Firm.new
|
943
951
|
|
944
|
-
|
952
|
+
assert_raise(ActiveRecord::UnknownAttributeError) do
|
945
953
|
firm.attributes = { "id" => 5, "type" => "Client", "i_dont_even_exist" => 20 }
|
946
954
|
end
|
947
955
|
end
|
@@ -1196,7 +1204,12 @@ class BasicsTest < ActiveRecord::TestCase
|
|
1196
1204
|
b_true = Booleantest.find(true_id)
|
1197
1205
|
assert b_true.value?
|
1198
1206
|
end
|
1199
|
-
|
1207
|
+
|
1208
|
+
def test_new_record_returns_boolean
|
1209
|
+
assert_equal Topic.new.new_record?, true
|
1210
|
+
assert_equal Topic.find(1).new_record?, false
|
1211
|
+
end
|
1212
|
+
|
1200
1213
|
def test_clone
|
1201
1214
|
topic = Topic.find(1)
|
1202
1215
|
cloned_topic = nil
|
@@ -1396,7 +1409,7 @@ class BasicsTest < ActiveRecord::TestCase
|
|
1396
1409
|
end
|
1397
1410
|
|
1398
1411
|
def test_sql_injection_via_find
|
1399
|
-
|
1412
|
+
assert_raise(ActiveRecord::RecordNotFound, ActiveRecord::StatementInvalid) do
|
1400
1413
|
Topic.find("123456 OR id > 0")
|
1401
1414
|
end
|
1402
1415
|
end
|
@@ -1748,7 +1761,14 @@ class BasicsTest < ActiveRecord::TestCase
|
|
1748
1761
|
assert developers[i-1].salary >= developers[i].salary
|
1749
1762
|
end
|
1750
1763
|
end
|
1751
|
-
|
1764
|
+
|
1765
|
+
def test_scoped_find_with_group_and_having
|
1766
|
+
developers = Developer.with_scope(:find => { :group => 'salary', :having => "SUM(salary) > 10000", :select => "SUM(salary) as salary" }) do
|
1767
|
+
Developer.find(:all)
|
1768
|
+
end
|
1769
|
+
assert_equal 3, developers.size
|
1770
|
+
end
|
1771
|
+
|
1752
1772
|
def test_find_last
|
1753
1773
|
last = Developer.find :last
|
1754
1774
|
assert_equal last, Developer.find(:first, :order => 'id desc')
|
@@ -1776,7 +1796,12 @@ class BasicsTest < ActiveRecord::TestCase
|
|
1776
1796
|
last = Developer.find :last, :order => 'developers.name, developers.salary DESC'
|
1777
1797
|
assert_equal last, Developer.find(:all, :order => 'developers.name, developers.salary DESC').last
|
1778
1798
|
end
|
1779
|
-
|
1799
|
+
|
1800
|
+
def test_find_symbol_ordered_last
|
1801
|
+
last = Developer.find :last, :order => :salary
|
1802
|
+
assert_equal last, Developer.find(:all, :order => :salary).last
|
1803
|
+
end
|
1804
|
+
|
1780
1805
|
def test_find_scoped_ordered_last
|
1781
1806
|
last_developer = Developer.with_scope(:find => { :order => 'developers.salary ASC' }) do
|
1782
1807
|
Developer.find(:last)
|
@@ -2078,17 +2103,12 @@ class BasicsTest < ActiveRecord::TestCase
|
|
2078
2103
|
ActiveRecord::Base.logger = original_logger
|
2079
2104
|
end
|
2080
2105
|
|
2081
|
-
|
2082
|
-
|
2083
|
-
|
2084
|
-
|
2085
|
-
|
2086
|
-
|
2087
|
-
ensure
|
2088
|
-
$KCODE = orig_kcode
|
2089
|
-
end
|
2090
|
-
else
|
2091
|
-
yield
|
2092
|
-
end
|
2106
|
+
def test_create_with_custom_timestamps
|
2107
|
+
custom_datetime = 1.hour.ago.beginning_of_day
|
2108
|
+
|
2109
|
+
%w(created_at created_on updated_at updated_on).each do |attribute|
|
2110
|
+
parrot = LiveParrot.create(:name => "colombian", attribute => custom_datetime)
|
2111
|
+
assert_equal custom_datetime, parrot[attribute]
|
2093
2112
|
end
|
2113
|
+
end
|
2094
2114
|
end
|