activerecord 2.1.2 → 2.2.2
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.
- data/CHANGELOG +32 -6
- data/README +0 -0
- data/Rakefile +4 -5
- data/lib/active_record.rb +11 -10
- data/lib/active_record/aggregations.rb +110 -38
- data/lib/active_record/association_preload.rb +104 -15
- data/lib/active_record/associations.rb +427 -212
- data/lib/active_record/associations/association_collection.rb +101 -16
- data/lib/active_record/associations/association_proxy.rb +65 -13
- data/lib/active_record/associations/belongs_to_association.rb +2 -2
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +13 -3
- data/lib/active_record/associations/has_many_association.rb +28 -28
- data/lib/active_record/associations/has_many_through_association.rb +21 -19
- data/lib/active_record/associations/has_one_association.rb +24 -7
- data/lib/active_record/associations/has_one_through_association.rb +3 -4
- data/lib/active_record/attribute_methods.rb +13 -5
- data/lib/active_record/base.rb +435 -212
- data/lib/active_record/calculations.rb +12 -5
- data/lib/active_record/callbacks.rb +28 -9
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +355 -0
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +42 -215
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +30 -5
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -1
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +48 -7
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +10 -4
- data/lib/active_record/connection_adapters/abstract_adapter.rb +67 -26
- data/lib/active_record/connection_adapters/mysql_adapter.rb +71 -45
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +155 -84
- data/lib/active_record/dirty.rb +25 -7
- data/lib/active_record/dynamic_finder_match.rb +41 -0
- data/lib/active_record/fixtures.rb +10 -9
- data/lib/active_record/i18n_interpolation_deprecation.rb +26 -0
- data/lib/active_record/locale/en.yml +54 -0
- data/lib/active_record/migration.rb +47 -10
- data/lib/active_record/named_scope.rb +29 -16
- data/lib/active_record/reflection.rb +118 -54
- data/lib/active_record/schema_dumper.rb +13 -7
- data/lib/active_record/test_case.rb +18 -5
- data/lib/active_record/transactions.rb +89 -34
- data/lib/active_record/validations.rb +270 -180
- data/lib/active_record/version.rb +1 -1
- data/test/cases/active_schema_test_mysql.rb +5 -0
- data/test/cases/adapter_test.rb +6 -0
- data/test/cases/aggregations_test.rb +39 -0
- data/test/cases/associations/belongs_to_associations_test.rb +10 -0
- data/test/cases/associations/eager_load_nested_include_test.rb +30 -12
- data/test/cases/associations/eager_test.rb +54 -5
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +77 -10
- data/test/cases/associations/has_many_associations_test.rb +74 -7
- data/test/cases/associations/has_many_through_associations_test.rb +50 -3
- data/test/cases/associations/has_one_associations_test.rb +17 -0
- data/test/cases/associations/has_one_through_associations_test.rb +49 -1
- data/test/cases/associations_test.rb +0 -0
- data/test/cases/attribute_methods_test.rb +59 -4
- data/test/cases/base_test.rb +93 -21
- data/test/cases/binary_test.rb +1 -5
- data/test/cases/calculations_test.rb +5 -0
- data/test/cases/callbacks_observers_test.rb +38 -0
- data/test/cases/connection_test_mysql.rb +1 -1
- data/test/cases/defaults_test.rb +32 -1
- data/test/cases/deprecated_finder_test.rb +0 -0
- data/test/cases/dirty_test.rb +13 -0
- data/test/cases/finder_test.rb +162 -12
- data/test/cases/fixtures_test.rb +32 -3
- data/test/cases/helper.rb +15 -0
- data/test/cases/i18n_test.rb +41 -0
- data/test/cases/inheritance_test.rb +2 -2
- data/test/cases/lifecycle_test.rb +0 -0
- data/test/cases/locking_test.rb +4 -9
- data/test/cases/method_scoping_test.rb +109 -2
- data/test/cases/migration_test.rb +43 -8
- data/test/cases/multiple_db_test.rb +25 -0
- data/test/cases/named_scope_test.rb +74 -0
- data/test/cases/pooled_connections_test.rb +103 -0
- data/test/cases/readonly_test.rb +0 -0
- data/test/cases/reflection_test.rb +11 -3
- data/test/cases/reload_models_test.rb +20 -0
- data/test/cases/sanitize_test.rb +25 -0
- data/test/cases/schema_authorization_test_postgresql.rb +2 -2
- data/test/cases/transactions_test.rb +62 -12
- data/test/cases/unconnected_test.rb +0 -0
- data/test/cases/validations_i18n_test.rb +921 -0
- data/test/cases/validations_test.rb +44 -33
- data/test/connections/native_mysql/connection.rb +1 -3
- data/test/fixtures/companies.yml +1 -0
- data/test/fixtures/customers.yml +10 -1
- data/test/fixtures/fixture_database.sqlite3 +0 -0
- data/test/fixtures/fixture_database_2.sqlite3 +0 -0
- data/test/fixtures/organizations.yml +5 -0
- data/test/migrations/broken/100_migration_that_raises_exception.rb +10 -0
- data/test/models/author.rb +3 -0
- data/test/models/category.rb +3 -0
- data/test/models/club.rb +6 -0
- data/test/models/company.rb +25 -1
- data/test/models/customer.rb +19 -1
- data/test/models/member.rb +2 -0
- data/test/models/member_detail.rb +4 -0
- data/test/models/organization.rb +4 -0
- data/test/models/parrot.rb +1 -0
- data/test/models/post.rb +3 -0
- data/test/models/reply.rb +0 -0
- data/test/models/topic.rb +3 -0
- data/test/schema/schema.rb +12 -1
- metadata +22 -10
- data/lib/active_record/vendor/mysql.rb +0 -1214
- data/test/cases/adapter_test_sqlserver.rb +0 -95
- data/test/cases/table_name_test_sqlserver.rb +0 -23
- data/test/cases/threaded_connections_test.rb +0 -48
- data/test/schema/sqlserver_specific_schema.rb +0 -5
@@ -2,15 +2,18 @@ require "cases/helper"
|
|
2
2
|
require 'models/post'
|
3
3
|
require 'models/person'
|
4
4
|
require 'models/reader'
|
5
|
+
require 'models/comment'
|
5
6
|
|
6
7
|
class HasManyThroughAssociationsTest < ActiveRecord::TestCase
|
7
|
-
fixtures :posts, :readers, :people
|
8
|
+
fixtures :posts, :readers, :people, :comments, :authors
|
8
9
|
|
9
10
|
def test_associate_existing
|
10
11
|
assert_queries(2) { posts(:thinking);people(:david) }
|
11
|
-
|
12
|
+
|
13
|
+
posts(:thinking).people
|
14
|
+
|
12
15
|
assert_queries(1) do
|
13
|
-
|
16
|
+
posts(:thinking).people << people(:david)
|
14
17
|
end
|
15
18
|
|
16
19
|
assert_queries(1) do
|
@@ -197,4 +200,48 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
|
|
197
200
|
def test_count_with_include_should_alias_join_table
|
198
201
|
assert_equal 2, people(:michael).posts.count(:include => :readers)
|
199
202
|
end
|
203
|
+
|
204
|
+
def test_get_ids
|
205
|
+
assert_equal [posts(:welcome).id, posts(:authorless).id].sort, people(:michael).post_ids.sort
|
206
|
+
end
|
207
|
+
|
208
|
+
def test_get_ids_for_loaded_associations
|
209
|
+
person = people(:michael)
|
210
|
+
person.posts(true)
|
211
|
+
assert_queries(0) do
|
212
|
+
person.post_ids
|
213
|
+
person.post_ids
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def test_get_ids_for_unloaded_associations_does_not_load_them
|
218
|
+
person = people(:michael)
|
219
|
+
assert !person.posts.loaded?
|
220
|
+
assert_equal [posts(:welcome).id, posts(:authorless).id].sort, person.post_ids.sort
|
221
|
+
assert !person.posts.loaded?
|
222
|
+
end
|
223
|
+
|
224
|
+
uses_mocha 'mocking Tag.transaction' do
|
225
|
+
def test_association_proxy_transaction_method_starts_transaction_in_association_class
|
226
|
+
Tag.expects(:transaction)
|
227
|
+
Post.find(:first).tags.transaction do
|
228
|
+
# nothing
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def test_has_many_association_through_a_belongs_to_association_where_the_association_doesnt_exist
|
234
|
+
author = authors(:mary)
|
235
|
+
post = Post.create!(:title => "TITLE", :body => "BODY")
|
236
|
+
assert_equal [], post.author_favorites
|
237
|
+
end
|
238
|
+
|
239
|
+
def test_has_many_association_through_a_belongs_to_association
|
240
|
+
author = authors(:mary)
|
241
|
+
post = Post.create!(:author => author, :title => "TITLE", :body => "BODY")
|
242
|
+
author.author_favorites.create(:favorite_author_id => 1)
|
243
|
+
author.author_favorites.create(:favorite_author_id => 2)
|
244
|
+
author.author_favorites.create(:favorite_author_id => 3)
|
245
|
+
assert_equal post.author.author_favorites, post.author_favorites
|
246
|
+
end
|
200
247
|
end
|
@@ -29,6 +29,13 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
|
|
29
29
|
assert_equal Firm.find(1, :include => :account_with_select).account_with_select.attributes.size, 2
|
30
30
|
end
|
31
31
|
|
32
|
+
def test_finding_using_primary_key
|
33
|
+
firm = companies(:first_firm)
|
34
|
+
assert_equal Account.find_by_firm_id(firm.id), firm.account
|
35
|
+
firm.firm_id = companies(:rails_core).id
|
36
|
+
assert_equal accounts(:rails_core_account), firm.account_using_primary_key
|
37
|
+
end
|
38
|
+
|
32
39
|
def test_can_marshal_has_one_association_with_nil_target
|
33
40
|
firm = Firm.new
|
34
41
|
assert_nothing_raised do
|
@@ -342,4 +349,14 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
|
|
342
349
|
assert companies(:first_firm).readonly_account.readonly?
|
343
350
|
end
|
344
351
|
|
352
|
+
def test_has_one_proxy_should_not_respond_to_private_methods
|
353
|
+
assert_raises(NoMethodError) { accounts(:signals37).private_method }
|
354
|
+
assert_raises(NoMethodError) { companies(:first_firm).account.private_method }
|
355
|
+
end
|
356
|
+
|
357
|
+
def test_has_one_proxy_should_respond_to_private_methods_via_send
|
358
|
+
accounts(:signals37).send(:private_method)
|
359
|
+
companies(:first_firm).account.send(:private_method)
|
360
|
+
end
|
361
|
+
|
345
362
|
end
|
@@ -3,9 +3,11 @@ require 'models/club'
|
|
3
3
|
require 'models/member'
|
4
4
|
require 'models/membership'
|
5
5
|
require 'models/sponsor'
|
6
|
+
require 'models/organization'
|
7
|
+
require 'models/member_detail'
|
6
8
|
|
7
9
|
class HasOneThroughAssociationsTest < ActiveRecord::TestCase
|
8
|
-
fixtures :members, :clubs, :memberships, :sponsors
|
10
|
+
fixtures :members, :clubs, :memberships, :sponsors, :organizations
|
9
11
|
|
10
12
|
def setup
|
11
13
|
@member = members(:groucho)
|
@@ -110,4 +112,50 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase
|
|
110
112
|
new_member.club = new_club = Club.create(:name => "LRUG")
|
111
113
|
assert_equal new_club, new_member.club.target
|
112
114
|
end
|
115
|
+
|
116
|
+
def test_has_one_through_proxy_should_not_respond_to_private_methods
|
117
|
+
assert_raises(NoMethodError) { clubs(:moustache_club).private_method }
|
118
|
+
assert_raises(NoMethodError) { @member.club.private_method }
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_has_one_through_proxy_should_respond_to_private_methods_via_send
|
122
|
+
clubs(:moustache_club).send(:private_method)
|
123
|
+
@member.club.send(:private_method)
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_assigning_to_has_one_through_preserves_decorated_join_record
|
127
|
+
@organization = organizations(:nsa)
|
128
|
+
assert_difference 'MemberDetail.count', 1 do
|
129
|
+
@member_detail = MemberDetail.new(:extra_data => 'Extra')
|
130
|
+
@member.member_detail = @member_detail
|
131
|
+
@member.organization = @organization
|
132
|
+
end
|
133
|
+
assert_equal @organization, @member.organization
|
134
|
+
assert @organization.members.include?(@member)
|
135
|
+
assert_equal 'Extra', @member.member_detail.extra_data
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_reassigning_has_one_through
|
139
|
+
@organization = organizations(:nsa)
|
140
|
+
@new_organization = organizations(:discordians)
|
141
|
+
|
142
|
+
assert_difference 'MemberDetail.count', 1 do
|
143
|
+
@member_detail = MemberDetail.new(:extra_data => 'Extra')
|
144
|
+
@member.member_detail = @member_detail
|
145
|
+
@member.organization = @organization
|
146
|
+
end
|
147
|
+
assert_equal @organization, @member.organization
|
148
|
+
assert_equal 'Extra', @member.member_detail.extra_data
|
149
|
+
assert @organization.members.include?(@member)
|
150
|
+
assert !@new_organization.members.include?(@member)
|
151
|
+
|
152
|
+
assert_no_difference 'MemberDetail.count' do
|
153
|
+
@member.organization = @new_organization
|
154
|
+
end
|
155
|
+
assert_equal @new_organization, @member.organization
|
156
|
+
assert_equal 'Extra', @member.member_detail.extra_data
|
157
|
+
assert !@organization.members.include?(@member)
|
158
|
+
assert @new_organization.members.include?(@member)
|
159
|
+
end
|
160
|
+
|
113
161
|
end
|
File without changes
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require "cases/helper"
|
2
2
|
require 'models/topic'
|
3
|
+
require 'models/minimalistic'
|
3
4
|
|
4
5
|
class AttributeMethodsTest < ActiveRecord::TestCase
|
5
6
|
fixtures :topics
|
@@ -57,19 +58,19 @@ class AttributeMethodsTest < ActiveRecord::TestCase
|
|
57
58
|
|
58
59
|
def test_kernel_methods_not_implemented_in_activerecord
|
59
60
|
%w(test name display y).each do |method|
|
60
|
-
|
61
|
+
assert !ActiveRecord::Base.instance_method_already_implemented?(method), "##{method} is defined"
|
61
62
|
end
|
62
63
|
end
|
63
64
|
|
64
65
|
def test_primary_key_implemented
|
65
|
-
|
66
|
+
assert Class.new(ActiveRecord::Base).instance_method_already_implemented?('id')
|
66
67
|
end
|
67
68
|
|
68
69
|
def test_defined_kernel_methods_implemented_in_model
|
69
70
|
%w(test name display y).each do |method|
|
70
71
|
klass = Class.new ActiveRecord::Base
|
71
72
|
klass.class_eval "def #{method}() 'defined #{method}' end"
|
72
|
-
|
73
|
+
assert klass.instance_method_already_implemented?(method), "##{method} is not defined"
|
73
74
|
end
|
74
75
|
end
|
75
76
|
|
@@ -79,7 +80,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
|
|
79
80
|
abstract.class_eval "def #{method}() 'defined #{method}' end"
|
80
81
|
abstract.abstract_class = true
|
81
82
|
klass = Class.new abstract
|
82
|
-
|
83
|
+
assert klass.instance_method_already_implemented?(method), "##{method} is not defined"
|
83
84
|
end
|
84
85
|
end
|
85
86
|
|
@@ -219,6 +220,51 @@ class AttributeMethodsTest < ActiveRecord::TestCase
|
|
219
220
|
end
|
220
221
|
end
|
221
222
|
|
223
|
+
def test_setting_time_zone_conversion_for_attributes_should_write_value_on_class_variable
|
224
|
+
Topic.skip_time_zone_conversion_for_attributes = [:field_a]
|
225
|
+
Minimalistic.skip_time_zone_conversion_for_attributes = [:field_b]
|
226
|
+
|
227
|
+
assert_equal [:field_a], Topic.skip_time_zone_conversion_for_attributes
|
228
|
+
assert_equal [:field_b], Minimalistic.skip_time_zone_conversion_for_attributes
|
229
|
+
end
|
230
|
+
|
231
|
+
def test_read_attributes_respect_access_control
|
232
|
+
privatize("title")
|
233
|
+
|
234
|
+
topic = @target.new(:title => "The pros and cons of programming naked.")
|
235
|
+
assert !topic.respond_to?(:title)
|
236
|
+
exception = assert_raise(NoMethodError) { topic.title }
|
237
|
+
assert_equal "Attempt to call private method", exception.message
|
238
|
+
assert_equal "I'm private", topic.send(:title)
|
239
|
+
end
|
240
|
+
|
241
|
+
def test_write_attributes_respect_access_control
|
242
|
+
privatize("title=(value)")
|
243
|
+
|
244
|
+
topic = @target.new
|
245
|
+
assert !topic.respond_to?(:title=)
|
246
|
+
exception = assert_raise(NoMethodError) { topic.title = "Pants"}
|
247
|
+
assert_equal "Attempt to call private method", exception.message
|
248
|
+
topic.send(:title=, "Very large pants")
|
249
|
+
end
|
250
|
+
|
251
|
+
def test_question_attributes_respect_access_control
|
252
|
+
privatize("title?")
|
253
|
+
|
254
|
+
topic = @target.new(:title => "Isaac Newton's pants")
|
255
|
+
assert !topic.respond_to?(:title?)
|
256
|
+
exception = assert_raise(NoMethodError) { topic.title? }
|
257
|
+
assert_equal "Attempt to call private method", exception.message
|
258
|
+
assert topic.send(:title?)
|
259
|
+
end
|
260
|
+
|
261
|
+
def test_bulk_update_respects_access_control
|
262
|
+
privatize("title=(value)")
|
263
|
+
|
264
|
+
assert_raise(ActiveRecord::UnknownAttributeError) { topic = @target.new(:title => "Rants about pants") }
|
265
|
+
assert_raise(ActiveRecord::UnknownAttributeError) { @target.new.attributes = { :title => "Ants in pants" } }
|
266
|
+
end
|
267
|
+
|
222
268
|
private
|
223
269
|
def time_related_columns_on_topic
|
224
270
|
Topic.columns.select{|c| [:time, :date, :datetime, :timestamp].include?(c.type)}.map(&:name)
|
@@ -235,4 +281,13 @@ class AttributeMethodsTest < ActiveRecord::TestCase
|
|
235
281
|
Time.zone = old_zone
|
236
282
|
ActiveRecord::Base.time_zone_aware_attributes = old_tz
|
237
283
|
end
|
284
|
+
|
285
|
+
def privatize(method_signature)
|
286
|
+
@target.class_eval <<-private_method
|
287
|
+
private
|
288
|
+
def #{method_signature}
|
289
|
+
"I'm private"
|
290
|
+
end
|
291
|
+
private_method
|
292
|
+
end
|
238
293
|
end
|
data/test/cases/base_test.rb
CHANGED
@@ -76,7 +76,7 @@ class TopicWithProtectedContentAndAccessibleAuthorName < ActiveRecord::Base
|
|
76
76
|
end
|
77
77
|
|
78
78
|
class BasicsTest < ActiveRecord::TestCase
|
79
|
-
fixtures :topics, :companies, :developers, :projects, :computers, :accounts, :minimalistics, 'warehouse-things', :authors, :categorizations, :categories
|
79
|
+
fixtures :topics, :companies, :developers, :projects, :computers, :accounts, :minimalistics, 'warehouse-things', :authors, :categorizations, :categories, :posts
|
80
80
|
|
81
81
|
def test_table_exists
|
82
82
|
assert !NonExistentTable.table_exists?
|
@@ -138,7 +138,7 @@ class BasicsTest < ActiveRecord::TestCase
|
|
138
138
|
if current_adapter?(:MysqlAdapter)
|
139
139
|
def test_read_attributes_before_type_cast_on_boolean
|
140
140
|
bool = Booleantest.create({ "value" => false })
|
141
|
-
assert_equal 0, bool.attributes_before_type_cast["value"]
|
141
|
+
assert_equal "0", bool.reload.attributes_before_type_cast["value"]
|
142
142
|
end
|
143
143
|
end
|
144
144
|
|
@@ -428,9 +428,6 @@ class BasicsTest < ActiveRecord::TestCase
|
|
428
428
|
end
|
429
429
|
|
430
430
|
def test_preserving_date_objects
|
431
|
-
# SQL Server doesn't have a separate column type just for dates, so all are returned as time
|
432
|
-
return true if current_adapter?(:SQLServerAdapter)
|
433
|
-
|
434
431
|
if current_adapter?(:SybaseAdapter, :OracleAdapter)
|
435
432
|
# Sybase ctlib does not (yet?) support the date type; use datetime instead.
|
436
433
|
# Oracle treats all dates/times as Time.
|
@@ -472,6 +469,18 @@ class BasicsTest < ActiveRecord::TestCase
|
|
472
469
|
assert topic.instance_variable_get("@custom_approved")
|
473
470
|
end
|
474
471
|
|
472
|
+
def test_delete
|
473
|
+
topic = Topic.find(1)
|
474
|
+
assert_equal topic, topic.delete, 'topic.delete did not return self'
|
475
|
+
assert topic.frozen?, 'topic not frozen after delete'
|
476
|
+
assert_raise(ActiveRecord::RecordNotFound) { Topic.find(topic.id) }
|
477
|
+
end
|
478
|
+
|
479
|
+
def test_delete_doesnt_run_callbacks
|
480
|
+
Topic.find(1).delete
|
481
|
+
assert_not_nil Topic.find(2)
|
482
|
+
end
|
483
|
+
|
475
484
|
def test_destroy
|
476
485
|
topic = Topic.find(1)
|
477
486
|
assert_equal topic, topic.destroy, 'topic.destroy did not return self'
|
@@ -664,10 +673,21 @@ class BasicsTest < ActiveRecord::TestCase
|
|
664
673
|
end
|
665
674
|
end
|
666
675
|
|
667
|
-
def
|
668
|
-
author =
|
676
|
+
def test_update_all_ignores_order_without_limit_from_association
|
677
|
+
author = authors(:david)
|
678
|
+
assert_nothing_raised do
|
679
|
+
assert_equal author.posts_with_comments_and_categories.length, author.posts_with_comments_and_categories.update_all([ "body = ?", "bulk update!" ])
|
680
|
+
end
|
681
|
+
end
|
682
|
+
|
683
|
+
def test_update_all_with_order_and_limit_updates_subset_only
|
684
|
+
author = authors(:david)
|
669
685
|
assert_nothing_raised do
|
670
|
-
assert_equal
|
686
|
+
assert_equal 1, author.posts_sorted_by_id_limited.size
|
687
|
+
assert_equal 2, author.posts_sorted_by_id_limited.find(:all, :limit => 2).size
|
688
|
+
assert_equal 1, author.posts_sorted_by_id_limited.update_all([ "body = ?", "bulk update!" ])
|
689
|
+
assert_equal "bulk update!", posts(:welcome).body
|
690
|
+
assert_not_equal "bulk update!", posts(:thinking).body
|
671
691
|
end
|
672
692
|
end
|
673
693
|
|
@@ -754,8 +774,8 @@ class BasicsTest < ActiveRecord::TestCase
|
|
754
774
|
end
|
755
775
|
end
|
756
776
|
|
757
|
-
# Oracle,
|
758
|
-
unless current_adapter?(:
|
777
|
+
# Oracle, and Sybase do not have a TIME datatype.
|
778
|
+
unless current_adapter?(:OracleAdapter, :SybaseAdapter)
|
759
779
|
def test_utc_as_time_zone
|
760
780
|
Topic.default_timezone = :utc
|
761
781
|
attributes = { "bonus_time" => "5:42:00AM" }
|
@@ -809,6 +829,20 @@ class BasicsTest < ActiveRecord::TestCase
|
|
809
829
|
assert_equal [ Topic.find(1) ], [ Topic.find(2).topic ] & [ Topic.find(1) ]
|
810
830
|
end
|
811
831
|
|
832
|
+
def test_delete_new_record
|
833
|
+
client = Client.new
|
834
|
+
client.delete
|
835
|
+
assert client.frozen?
|
836
|
+
end
|
837
|
+
|
838
|
+
def test_delete_record_with_associations
|
839
|
+
client = Client.find(3)
|
840
|
+
client.delete
|
841
|
+
assert client.frozen?
|
842
|
+
assert_kind_of Firm, client.firm
|
843
|
+
assert_raises(ActiveSupport::FrozenObjectError) { client.name = "something else" }
|
844
|
+
end
|
845
|
+
|
812
846
|
def test_destroy_new_record
|
813
847
|
client = Client.new
|
814
848
|
client.destroy
|
@@ -880,7 +914,7 @@ class BasicsTest < ActiveRecord::TestCase
|
|
880
914
|
|
881
915
|
def test_mass_assignment_protection_against_class_attribute_writers
|
882
916
|
[:logger, :configurations, :primary_key_prefix_type, :table_name_prefix, :table_name_suffix, :pluralize_table_names, :colorize_logging,
|
883
|
-
:default_timezone, :
|
917
|
+
:default_timezone, :schema_format, :lock_optimistically, :record_timestamps].each do |method|
|
884
918
|
assert Task.respond_to?(method)
|
885
919
|
assert Task.respond_to?("#{method}=")
|
886
920
|
assert Task.new.respond_to?(method)
|
@@ -904,6 +938,14 @@ class BasicsTest < ActiveRecord::TestCase
|
|
904
938
|
assert_nil keyboard.id
|
905
939
|
end
|
906
940
|
|
941
|
+
def test_mass_assigning_invalid_attribute
|
942
|
+
firm = Firm.new
|
943
|
+
|
944
|
+
assert_raises(ActiveRecord::UnknownAttributeError) do
|
945
|
+
firm.attributes = { "id" => 5, "type" => "Client", "i_dont_even_exist" => 20 }
|
946
|
+
end
|
947
|
+
end
|
948
|
+
|
907
949
|
def test_mass_assignment_protection_on_defaults
|
908
950
|
firm = Firm.new
|
909
951
|
firm.attributes = { "id" => 5, "type" => "Client" }
|
@@ -1112,8 +1154,8 @@ class BasicsTest < ActiveRecord::TestCase
|
|
1112
1154
|
end
|
1113
1155
|
|
1114
1156
|
def test_attributes_on_dummy_time
|
1115
|
-
# Oracle,
|
1116
|
-
return true if current_adapter?(:
|
1157
|
+
# Oracle, and Sybase do not have a TIME datatype.
|
1158
|
+
return true if current_adapter?(:OracleAdapter, :SybaseAdapter)
|
1117
1159
|
|
1118
1160
|
attributes = {
|
1119
1161
|
"bonus_time" => "5:42:00AM"
|
@@ -1124,11 +1166,15 @@ class BasicsTest < ActiveRecord::TestCase
|
|
1124
1166
|
end
|
1125
1167
|
|
1126
1168
|
def test_boolean
|
1169
|
+
b_nil = Booleantest.create({ "value" => nil })
|
1170
|
+
nil_id = b_nil.id
|
1127
1171
|
b_false = Booleantest.create({ "value" => false })
|
1128
1172
|
false_id = b_false.id
|
1129
1173
|
b_true = Booleantest.create({ "value" => true })
|
1130
1174
|
true_id = b_true.id
|
1131
1175
|
|
1176
|
+
b_nil = Booleantest.find(nil_id)
|
1177
|
+
assert_nil b_nil.value
|
1132
1178
|
b_false = Booleantest.find(false_id)
|
1133
1179
|
assert !b_false.value?
|
1134
1180
|
b_true = Booleantest.find(true_id)
|
@@ -1136,11 +1182,15 @@ class BasicsTest < ActiveRecord::TestCase
|
|
1136
1182
|
end
|
1137
1183
|
|
1138
1184
|
def test_boolean_cast_from_string
|
1185
|
+
b_blank = Booleantest.create({ "value" => "" })
|
1186
|
+
blank_id = b_blank.id
|
1139
1187
|
b_false = Booleantest.create({ "value" => "0" })
|
1140
1188
|
false_id = b_false.id
|
1141
1189
|
b_true = Booleantest.create({ "value" => "1" })
|
1142
1190
|
true_id = b_true.id
|
1143
1191
|
|
1192
|
+
b_blank = Booleantest.find(blank_id)
|
1193
|
+
assert_nil b_blank.value
|
1144
1194
|
b_false = Booleantest.find(false_id)
|
1145
1195
|
assert !b_false.value?
|
1146
1196
|
b_true = Booleantest.find(true_id)
|
@@ -1376,6 +1426,12 @@ class BasicsTest < ActiveRecord::TestCase
|
|
1376
1426
|
topic = Topic.create("content" => myobj).reload
|
1377
1427
|
assert_equal(myobj, topic.content)
|
1378
1428
|
end
|
1429
|
+
|
1430
|
+
def test_serialized_string_attribute
|
1431
|
+
myobj = "Yes"
|
1432
|
+
topic = Topic.create("content" => myobj).reload
|
1433
|
+
assert_equal(myobj, topic.content)
|
1434
|
+
end
|
1379
1435
|
|
1380
1436
|
def test_nil_serialized_attribute_with_class_constraint
|
1381
1437
|
myobj = MyObject.new('value1', 'value2')
|
@@ -1411,15 +1467,17 @@ class BasicsTest < ActiveRecord::TestCase
|
|
1411
1467
|
|
1412
1468
|
if RUBY_VERSION < '1.9'
|
1413
1469
|
def test_quote_chars
|
1414
|
-
|
1415
|
-
|
1416
|
-
|
1470
|
+
with_kcode('UTF8') do
|
1471
|
+
str = 'The Narrator'
|
1472
|
+
topic = Topic.create(:author_name => str)
|
1473
|
+
assert_equal str, topic.author_name
|
1417
1474
|
|
1418
|
-
|
1419
|
-
|
1475
|
+
assert_kind_of ActiveSupport::Multibyte.proxy_class, str.mb_chars
|
1476
|
+
topic = Topic.find_by_author_name(str.mb_chars)
|
1420
1477
|
|
1421
|
-
|
1422
|
-
|
1478
|
+
assert_kind_of Topic, topic
|
1479
|
+
assert_equal str, topic.author_name, "The right topic should have been found by name even with name passed as Chars"
|
1480
|
+
end
|
1423
1481
|
end
|
1424
1482
|
end
|
1425
1483
|
|
@@ -1813,7 +1871,7 @@ class BasicsTest < ActiveRecord::TestCase
|
|
1813
1871
|
assert_equal "integer", xml.elements["//parent-id"].attributes['type']
|
1814
1872
|
assert_equal "true", xml.elements["//parent-id"].attributes['nil']
|
1815
1873
|
|
1816
|
-
if current_adapter?(:SybaseAdapter, :
|
1874
|
+
if current_adapter?(:SybaseAdapter, :OracleAdapter)
|
1817
1875
|
assert_equal last_read_in_current_timezone, xml.elements["//last-read"].text
|
1818
1876
|
assert_equal "datetime" , xml.elements["//last-read"].attributes['type']
|
1819
1877
|
else
|
@@ -2012,4 +2070,18 @@ class BasicsTest < ActiveRecord::TestCase
|
|
2012
2070
|
ensure
|
2013
2071
|
ActiveRecord::Base.logger = original_logger
|
2014
2072
|
end
|
2073
|
+
|
2074
|
+
private
|
2075
|
+
def with_kcode(kcode)
|
2076
|
+
if RUBY_VERSION < '1.9'
|
2077
|
+
orig_kcode, $KCODE = $KCODE, kcode
|
2078
|
+
begin
|
2079
|
+
yield
|
2080
|
+
ensure
|
2081
|
+
$KCODE = orig_kcode
|
2082
|
+
end
|
2083
|
+
else
|
2084
|
+
yield
|
2085
|
+
end
|
2086
|
+
end
|
2015
2087
|
end
|