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
data/test/cases/helper.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
$:.unshift(File.dirname(__FILE__) + '/../../lib')
|
2
|
+
$:.unshift(File.dirname(__FILE__) + '/../../../activesupport/lib')
|
2
3
|
|
3
4
|
require 'config'
|
4
5
|
require 'test/unit'
|
@@ -45,3 +46,17 @@ end
|
|
45
46
|
class << ActiveRecord::Base
|
46
47
|
public :with_scope, :with_exclusive_scope
|
47
48
|
end
|
49
|
+
|
50
|
+
unless ENV['FIXTURE_DEBUG']
|
51
|
+
module Test #:nodoc:
|
52
|
+
module Unit #:nodoc:
|
53
|
+
class << TestCase #:nodoc:
|
54
|
+
def try_to_load_dependency_with_silence(*args)
|
55
|
+
ActiveRecord::Base.logger.silence { try_to_load_dependency_without_silence(*args)}
|
56
|
+
end
|
57
|
+
|
58
|
+
alias_method_chain :try_to_load_dependency, :silence
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "cases/helper"
|
2
|
+
require 'models/topic'
|
3
|
+
require 'models/reply'
|
4
|
+
|
5
|
+
class ActiveRecordI18nTests < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
I18n.backend = I18n::Backend::Simple.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_translated_model_attributes
|
12
|
+
I18n.backend.store_translations 'en', :activerecord => {:attributes => {:topic => {:title => 'topic title attribute'} } }
|
13
|
+
assert_equal 'topic title attribute', Topic.human_attribute_name('title')
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_translated_model_attributes_with_sti
|
17
|
+
I18n.backend.store_translations 'en', :activerecord => {:attributes => {:reply => {:title => 'reply title attribute'} } }
|
18
|
+
assert_equal 'reply title attribute', Reply.human_attribute_name('title')
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_translated_model_attributes_with_sti_fallback
|
22
|
+
I18n.backend.store_translations 'en', :activerecord => {:attributes => {:topic => {:title => 'topic title attribute'} } }
|
23
|
+
assert_equal 'topic title attribute', Reply.human_attribute_name('title')
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_translated_model_names
|
27
|
+
I18n.backend.store_translations 'en', :activerecord => {:models => {:topic => 'topic model'} }
|
28
|
+
assert_equal 'topic model', Topic.human_name
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_translated_model_names_with_sti
|
32
|
+
I18n.backend.store_translations 'en', :activerecord => {:models => {:reply => 'reply model'} }
|
33
|
+
assert_equal 'reply model', Reply.human_name
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_translated_model_names_with_sti_fallback
|
37
|
+
I18n.backend.store_translations 'en', :activerecord => {:models => {:topic => 'topic model'} }
|
38
|
+
assert_equal 'topic model', Reply.human_name
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
@@ -59,13 +59,13 @@ class InheritanceTest < ActiveRecord::TestCase
|
|
59
59
|
|
60
60
|
def test_a_bad_type_column
|
61
61
|
#SQLServer need to turn Identity Insert On before manually inserting into the Identity column
|
62
|
-
if current_adapter?(:
|
62
|
+
if current_adapter?(:SybaseAdapter)
|
63
63
|
Company.connection.execute "SET IDENTITY_INSERT companies ON"
|
64
64
|
end
|
65
65
|
Company.connection.insert "INSERT INTO companies (id, #{QUOTED_TYPE}, name) VALUES(100, 'bad_class!', 'Not happening')"
|
66
66
|
|
67
67
|
#We then need to turn it back Off before continuing.
|
68
|
-
if current_adapter?(:
|
68
|
+
if current_adapter?(:SybaseAdapter)
|
69
69
|
Company.connection.execute "SET IDENTITY_INSERT companies OFF"
|
70
70
|
end
|
71
71
|
assert_raises(ActiveRecord::SubclassNotFound) { Company.find(100) }
|
File without changes
|
data/test/cases/locking_test.rb
CHANGED
@@ -200,9 +200,9 @@ end
|
|
200
200
|
# blocks, so separate script called by Kernel#system is needed.
|
201
201
|
# (See exec vs. async_exec in the PostgreSQL adapter.)
|
202
202
|
|
203
|
-
# TODO: The
|
203
|
+
# TODO: The Sybase, and OpenBase adapters currently have no support for pessimistic locking
|
204
204
|
|
205
|
-
unless current_adapter?(:
|
205
|
+
unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter)
|
206
206
|
class PessimisticLockingTest < ActiveRecord::TestCase
|
207
207
|
self.use_transactional_fixtures = false
|
208
208
|
fixtures :people, :readers
|
@@ -210,13 +210,6 @@ unless current_adapter?(:SQLServerAdapter, :SybaseAdapter, :OpenBaseAdapter)
|
|
210
210
|
def setup
|
211
211
|
# Avoid introspection queries during tests.
|
212
212
|
Person.columns; Reader.columns
|
213
|
-
|
214
|
-
@allow_concurrency = ActiveRecord::Base.allow_concurrency
|
215
|
-
ActiveRecord::Base.allow_concurrency = true
|
216
|
-
end
|
217
|
-
|
218
|
-
def teardown
|
219
|
-
ActiveRecord::Base.allow_concurrency = @allow_concurrency
|
220
213
|
end
|
221
214
|
|
222
215
|
# Test typical find.
|
@@ -264,6 +257,8 @@ unless current_adapter?(:SQLServerAdapter, :SybaseAdapter, :OpenBaseAdapter)
|
|
264
257
|
end
|
265
258
|
|
266
259
|
if current_adapter?(:PostgreSQLAdapter, :OracleAdapter)
|
260
|
+
use_concurrent_connections
|
261
|
+
|
267
262
|
def test_no_locks_no_wait
|
268
263
|
first, second = duel { Person.find 1 }
|
269
264
|
assert first.end > second.end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require "cases/helper"
|
2
|
+
require 'models/author'
|
2
3
|
require 'models/developer'
|
3
4
|
require 'models/project'
|
4
5
|
require 'models/comment'
|
@@ -6,7 +7,7 @@ require 'models/post'
|
|
6
7
|
require 'models/category'
|
7
8
|
|
8
9
|
class MethodScopingTest < ActiveRecord::TestCase
|
9
|
-
fixtures :developers, :projects, :comments, :posts, :developers_projects
|
10
|
+
fixtures :authors, :developers, :projects, :comments, :posts, :developers_projects
|
10
11
|
|
11
12
|
def test_set_conditions
|
12
13
|
Developer.with_scope(:find => { :conditions => 'just a test...' }) do
|
@@ -97,6 +98,76 @@ class MethodScopingTest < ActiveRecord::TestCase
|
|
97
98
|
assert_equal developers(:david).attributes, scoped_developers.first.attributes
|
98
99
|
end
|
99
100
|
|
101
|
+
def test_scoped_find_using_new_style_joins
|
102
|
+
scoped_developers = Developer.with_scope(:find => { :joins => :projects }) do
|
103
|
+
Developer.find(:all, :conditions => 'projects.id = 2')
|
104
|
+
end
|
105
|
+
assert scoped_developers.include?(developers(:david))
|
106
|
+
assert !scoped_developers.include?(developers(:jamis))
|
107
|
+
assert_equal 1, scoped_developers.size
|
108
|
+
assert_equal developers(:david).attributes, scoped_developers.first.attributes
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_scoped_find_merges_old_style_joins
|
112
|
+
scoped_authors = Author.with_scope(:find => { :joins => 'INNER JOIN posts ON authors.id = posts.author_id ' }) do
|
113
|
+
Author.find(:all, :select => 'DISTINCT authors.*', :joins => 'INNER JOIN comments ON posts.id = comments.post_id', :conditions => 'comments.id = 1')
|
114
|
+
end
|
115
|
+
assert scoped_authors.include?(authors(:david))
|
116
|
+
assert !scoped_authors.include?(authors(:mary))
|
117
|
+
assert_equal 1, scoped_authors.size
|
118
|
+
assert_equal authors(:david).attributes, scoped_authors.first.attributes
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_scoped_find_merges_new_style_joins
|
122
|
+
scoped_authors = Author.with_scope(:find => { :joins => :posts }) do
|
123
|
+
Author.find(:all, :select => 'DISTINCT authors.*', :joins => :comments, :conditions => 'comments.id = 1')
|
124
|
+
end
|
125
|
+
assert scoped_authors.include?(authors(:david))
|
126
|
+
assert !scoped_authors.include?(authors(:mary))
|
127
|
+
assert_equal 1, scoped_authors.size
|
128
|
+
assert_equal authors(:david).attributes, scoped_authors.first.attributes
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_scoped_find_merges_new_and_old_style_joins
|
132
|
+
scoped_authors = Author.with_scope(:find => { :joins => :posts }) do
|
133
|
+
Author.find(:all, :select => 'DISTINCT authors.*', :joins => 'JOIN comments ON posts.id = comments.post_id', :conditions => 'comments.id = 1')
|
134
|
+
end
|
135
|
+
assert scoped_authors.include?(authors(:david))
|
136
|
+
assert !scoped_authors.include?(authors(:mary))
|
137
|
+
assert_equal 1, scoped_authors.size
|
138
|
+
assert_equal authors(:david).attributes, scoped_authors.first.attributes
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_scoped_find_merges_string_array_style_and_string_style_joins
|
142
|
+
scoped_authors = Author.with_scope(:find => { :joins => ["INNER JOIN posts ON posts.author_id = authors.id"]}) do
|
143
|
+
Author.find(:all, :select => 'DISTINCT authors.*', :joins => 'INNER JOIN comments ON posts.id = comments.post_id', :conditions => 'comments.id = 1')
|
144
|
+
end
|
145
|
+
assert scoped_authors.include?(authors(:david))
|
146
|
+
assert !scoped_authors.include?(authors(:mary))
|
147
|
+
assert_equal 1, scoped_authors.size
|
148
|
+
assert_equal authors(:david).attributes, scoped_authors.first.attributes
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_scoped_find_merges_string_array_style_and_hash_style_joins
|
152
|
+
scoped_authors = Author.with_scope(:find => { :joins => :posts}) do
|
153
|
+
Author.find(:all, :select => 'DISTINCT authors.*', :joins => ['INNER JOIN comments ON posts.id = comments.post_id'], :conditions => 'comments.id = 1')
|
154
|
+
end
|
155
|
+
assert scoped_authors.include?(authors(:david))
|
156
|
+
assert !scoped_authors.include?(authors(:mary))
|
157
|
+
assert_equal 1, scoped_authors.size
|
158
|
+
assert_equal authors(:david).attributes, scoped_authors.first.attributes
|
159
|
+
end
|
160
|
+
|
161
|
+
def test_scoped_find_merges_joins_and_eliminates_duplicate_string_joins
|
162
|
+
scoped_authors = Author.with_scope(:find => { :joins => 'INNER JOIN posts ON posts.author_id = authors.id'}) do
|
163
|
+
Author.find(:all, :select => 'DISTINCT authors.*', :joins => ["INNER JOIN posts ON posts.author_id = authors.id", "INNER JOIN comments ON posts.id = comments.post_id"], :conditions => 'comments.id = 1')
|
164
|
+
end
|
165
|
+
assert scoped_authors.include?(authors(:david))
|
166
|
+
assert !scoped_authors.include?(authors(:mary))
|
167
|
+
assert_equal 1, scoped_authors.size
|
168
|
+
assert_equal authors(:david).attributes, scoped_authors.first.attributes
|
169
|
+
end
|
170
|
+
|
100
171
|
def test_scoped_count_include
|
101
172
|
# with the include, will retrieve only developers for the given project
|
102
173
|
Developer.with_scope(:find => { :include => :projects }) do
|
@@ -152,7 +223,7 @@ class MethodScopingTest < ActiveRecord::TestCase
|
|
152
223
|
end
|
153
224
|
|
154
225
|
class NestedScopingTest < ActiveRecord::TestCase
|
155
|
-
fixtures :developers, :projects, :comments, :posts
|
226
|
+
fixtures :authors, :developers, :projects, :comments, :posts
|
156
227
|
|
157
228
|
def test_merge_options
|
158
229
|
Developer.with_scope(:find => { :conditions => 'salary = 80000' }) do
|
@@ -357,6 +428,42 @@ class NestedScopingTest < ActiveRecord::TestCase
|
|
357
428
|
assert_equal scoped_methods, Developer.instance_eval('current_scoped_methods')
|
358
429
|
end
|
359
430
|
end
|
431
|
+
|
432
|
+
def test_nested_scoped_find_merges_old_style_joins
|
433
|
+
scoped_authors = Author.with_scope(:find => { :joins => 'INNER JOIN posts ON authors.id = posts.author_id' }) do
|
434
|
+
Author.with_scope(:find => { :joins => 'INNER JOIN comments ON posts.id = comments.post_id' }) do
|
435
|
+
Author.find(:all, :select => 'DISTINCT authors.*', :conditions => 'comments.id = 1')
|
436
|
+
end
|
437
|
+
end
|
438
|
+
assert scoped_authors.include?(authors(:david))
|
439
|
+
assert !scoped_authors.include?(authors(:mary))
|
440
|
+
assert_equal 1, scoped_authors.size
|
441
|
+
assert_equal authors(:david).attributes, scoped_authors.first.attributes
|
442
|
+
end
|
443
|
+
|
444
|
+
def test_nested_scoped_find_merges_new_style_joins
|
445
|
+
scoped_authors = Author.with_scope(:find => { :joins => :posts }) do
|
446
|
+
Author.with_scope(:find => { :joins => :comments }) do
|
447
|
+
Author.find(:all, :select => 'DISTINCT authors.*', :conditions => 'comments.id = 1')
|
448
|
+
end
|
449
|
+
end
|
450
|
+
assert scoped_authors.include?(authors(:david))
|
451
|
+
assert !scoped_authors.include?(authors(:mary))
|
452
|
+
assert_equal 1, scoped_authors.size
|
453
|
+
assert_equal authors(:david).attributes, scoped_authors.first.attributes
|
454
|
+
end
|
455
|
+
|
456
|
+
def test_nested_scoped_find_merges_new_and_old_style_joins
|
457
|
+
scoped_authors = Author.with_scope(:find => { :joins => :posts }) do
|
458
|
+
Author.with_scope(:find => { :joins => 'INNER JOIN comments ON posts.id = comments.post_id' }) do
|
459
|
+
Author.find(:all, :select => 'DISTINCT authors.*', :joins => '', :conditions => 'comments.id = 1')
|
460
|
+
end
|
461
|
+
end
|
462
|
+
assert scoped_authors.include?(authors(:david))
|
463
|
+
assert !scoped_authors.include?(authors(:mary))
|
464
|
+
assert_equal 1, scoped_authors.size
|
465
|
+
assert_equal authors(:david).attributes, scoped_authors.first.attributes
|
466
|
+
end
|
360
467
|
end
|
361
468
|
|
362
469
|
class HasManyScopingTest< ActiveRecord::TestCase
|
@@ -271,9 +271,9 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|
271
271
|
Person.connection.drop_table table_name rescue nil
|
272
272
|
end
|
273
273
|
|
274
|
-
#
|
274
|
+
# Sybase, and SQLite3 will not allow you to add a NOT NULL
|
275
275
|
# column to a table without a default value.
|
276
|
-
unless current_adapter?(:
|
276
|
+
unless current_adapter?(:SybaseAdapter, :SQLiteAdapter)
|
277
277
|
def test_add_column_not_null_without_default
|
278
278
|
Person.connection.create_table :testings do |t|
|
279
279
|
t.column :foo, :string
|
@@ -410,7 +410,7 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|
410
410
|
assert_equal Fixnum, bob.age.class
|
411
411
|
assert_equal Time, bob.birthday.class
|
412
412
|
|
413
|
-
if current_adapter?(:
|
413
|
+
if current_adapter?(:OracleAdapter, :SybaseAdapter)
|
414
414
|
# Sybase, and Oracle don't differentiate between date/time
|
415
415
|
assert_equal Time, bob.favorite_day.class
|
416
416
|
else
|
@@ -851,10 +851,6 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|
851
851
|
# - SQLite3 stores a float, in violation of SQL
|
852
852
|
assert_kind_of BigDecimal, b.value_of_e
|
853
853
|
assert_equal BigDecimal("2.71828182845905"), b.value_of_e
|
854
|
-
elsif current_adapter?(:SQLServer)
|
855
|
-
# - SQL Server rounds instead of truncating
|
856
|
-
assert_kind_of Fixnum, b.value_of_e
|
857
|
-
assert_equal 3, b.value_of_e
|
858
854
|
else
|
859
855
|
# - SQL standard is an integer
|
860
856
|
assert_kind_of Fixnum, b.value_of_e
|
@@ -934,6 +930,21 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|
934
930
|
assert_equal(0, ActiveRecord::Migrator.current_version)
|
935
931
|
end
|
936
932
|
|
933
|
+
if current_adapter?(:PostgreSQLAdapter)
|
934
|
+
def test_migrator_one_up_with_exception_and_rollback
|
935
|
+
assert !Person.column_methods_hash.include?(:last_name)
|
936
|
+
|
937
|
+
e = assert_raises(StandardError) do
|
938
|
+
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/broken", 100)
|
939
|
+
end
|
940
|
+
|
941
|
+
assert_equal "An error has occurred, this and all later migrations canceled:\n\nSomething broke", e.message
|
942
|
+
|
943
|
+
Person.reset_column_information
|
944
|
+
assert !Person.column_methods_hash.include?(:last_name)
|
945
|
+
end
|
946
|
+
end
|
947
|
+
|
937
948
|
def test_finds_migrations
|
938
949
|
migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/valid").migrations
|
939
950
|
[['1', 'people_have_last_names'],
|
@@ -952,6 +963,26 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|
952
963
|
migrations[0].name == 'innocent_jointable'
|
953
964
|
end
|
954
965
|
|
966
|
+
def test_only_loads_pending_migrations
|
967
|
+
# migrate up to 1
|
968
|
+
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)
|
969
|
+
|
970
|
+
# now unload the migrations that have been defined
|
971
|
+
PeopleHaveLastNames.unloadable
|
972
|
+
ActiveSupport::Dependencies.remove_unloadable_constants!
|
973
|
+
|
974
|
+
ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", nil)
|
975
|
+
|
976
|
+
assert !defined? PeopleHaveLastNames
|
977
|
+
|
978
|
+
%w(WeNeedReminders, InnocentJointable).each do |migration|
|
979
|
+
assert defined? migration
|
980
|
+
end
|
981
|
+
|
982
|
+
ensure
|
983
|
+
load(MIGRATIONS_ROOT + "/valid/1_people_have_last_names.rb")
|
984
|
+
end
|
985
|
+
|
955
986
|
def test_migrator_interleaved_migrations
|
956
987
|
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_1")
|
957
988
|
|
@@ -1098,7 +1129,11 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|
1098
1129
|
columns = Person.connection.columns(:binary_testings)
|
1099
1130
|
data_column = columns.detect { |c| c.name == "data" }
|
1100
1131
|
|
1101
|
-
|
1132
|
+
if current_adapter?(:MysqlAdapter)
|
1133
|
+
assert_equal '', data_column.default
|
1134
|
+
else
|
1135
|
+
assert_nil data_column.default
|
1136
|
+
end
|
1102
1137
|
|
1103
1138
|
Person.connection.drop_table :binary_testings rescue nil
|
1104
1139
|
end
|
@@ -57,4 +57,29 @@ class MultipleDbTest < ActiveRecord::TestCase
|
|
57
57
|
|
58
58
|
assert Course.connection
|
59
59
|
end
|
60
|
+
|
61
|
+
def test_transactions_across_databases
|
62
|
+
c1 = Course.find(1)
|
63
|
+
e1 = Entrant.find(1)
|
64
|
+
|
65
|
+
begin
|
66
|
+
Course.transaction do
|
67
|
+
Entrant.transaction do
|
68
|
+
c1.name = "Typo"
|
69
|
+
e1.name = "Typo"
|
70
|
+
c1.save
|
71
|
+
e1.save
|
72
|
+
raise "No I messed up."
|
73
|
+
end
|
74
|
+
end
|
75
|
+
rescue
|
76
|
+
# Yup caught it
|
77
|
+
end
|
78
|
+
|
79
|
+
assert_equal "Typo", c1.name
|
80
|
+
assert_equal "Typo", e1.name
|
81
|
+
|
82
|
+
assert_equal "Ruby Development", Course.find(1).name
|
83
|
+
assert_equal "Ruby Developer", Entrant.find(1).name
|
84
|
+
end
|
60
85
|
end
|
@@ -77,6 +77,10 @@ class NamedScopeTest < ActiveRecord::TestCase
|
|
77
77
|
assert_equal Topic.replied.approved, Topic.replied.approved_as_string
|
78
78
|
end
|
79
79
|
|
80
|
+
def test_scopes_can_be_specified_with_deep_hash_conditions
|
81
|
+
assert_equal Topic.replied.approved, Topic.replied.approved_as_hash_condition
|
82
|
+
end
|
83
|
+
|
80
84
|
def test_scopes_are_composable
|
81
85
|
assert_equal (approved = Topic.find(:all, :conditions => {:approved => true})), Topic.approved
|
82
86
|
assert_equal (replied = Topic.find(:all, :conditions => 'replies_count > 0')), Topic.replied
|
@@ -192,6 +196,55 @@ class NamedScopeTest < ActiveRecord::TestCase
|
|
192
196
|
end
|
193
197
|
end
|
194
198
|
|
199
|
+
def test_any_should_not_load_results
|
200
|
+
topics = Topic.base
|
201
|
+
assert_queries(2) do
|
202
|
+
topics.any? # use count query
|
203
|
+
topics.collect # force load
|
204
|
+
topics.any? # use loaded (no query)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def test_any_should_call_proxy_found_if_using_a_block
|
209
|
+
topics = Topic.base
|
210
|
+
assert_queries(1) do
|
211
|
+
topics.expects(:empty?).never
|
212
|
+
topics.any? { true }
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def test_any_should_not_fire_query_if_named_scope_loaded
|
217
|
+
topics = Topic.base
|
218
|
+
topics.collect # force load
|
219
|
+
assert_no_queries { assert topics.any? }
|
220
|
+
end
|
221
|
+
|
222
|
+
def test_should_build_with_proxy_options
|
223
|
+
topic = Topic.approved.build({})
|
224
|
+
assert topic.approved
|
225
|
+
end
|
226
|
+
|
227
|
+
def test_should_build_new_with_proxy_options
|
228
|
+
topic = Topic.approved.new
|
229
|
+
assert topic.approved
|
230
|
+
end
|
231
|
+
|
232
|
+
def test_should_create_with_proxy_options
|
233
|
+
topic = Topic.approved.create({})
|
234
|
+
assert topic.approved
|
235
|
+
end
|
236
|
+
|
237
|
+
def test_should_create_with_bang_with_proxy_options
|
238
|
+
topic = Topic.approved.create!({})
|
239
|
+
assert topic.approved
|
240
|
+
end
|
241
|
+
|
242
|
+
def test_should_build_with_proxy_options_chained
|
243
|
+
topic = Topic.approved.by_lifo.build({})
|
244
|
+
assert topic.approved
|
245
|
+
assert_equal 'lifo', topic.author_name
|
246
|
+
end
|
247
|
+
|
195
248
|
def test_find_all_should_behave_like_select
|
196
249
|
assert_equal Topic.base.select(&:approved), Topic.base.find_all(&:approved)
|
197
250
|
end
|
@@ -203,4 +256,25 @@ class NamedScopeTest < ActiveRecord::TestCase
|
|
203
256
|
def test_should_use_where_in_query_for_named_scope
|
204
257
|
assert_equal Developer.find_all_by_name('Jamis'), Developer.find_all_by_id(Developer.jamises)
|
205
258
|
end
|
259
|
+
|
260
|
+
def test_size_should_use_count_when_results_are_not_loaded
|
261
|
+
topics = Topic.base
|
262
|
+
assert_queries(1) do
|
263
|
+
assert_sql(/COUNT/i) { topics.size }
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
def test_size_should_use_length_when_results_are_loaded
|
268
|
+
topics = Topic.base
|
269
|
+
topics.reload # force load
|
270
|
+
assert_no_queries do
|
271
|
+
topics.size # use loaded (no query)
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def test_chaining_with_duplicate_joins
|
276
|
+
join = "INNER JOIN comments ON comments.post_id = posts.id"
|
277
|
+
post = Post.find(1)
|
278
|
+
assert_equal post.comments.size, Post.scoped(:joins => join).scoped(:joins => join, :conditions => "posts.id = #{post.id}").size
|
279
|
+
end
|
206
280
|
end
|