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/binary_test.rb
CHANGED
@@ -1,13 +1,9 @@
|
|
1
1
|
require "cases/helper"
|
2
2
|
|
3
|
-
# Without using prepared statements, it makes no sense to test
|
4
|
-
# BLOB data with SQL Server, because the length of a statement is
|
5
|
-
# limited to 8KB.
|
6
|
-
#
|
7
3
|
# Without using prepared statements, it makes no sense to test
|
8
4
|
# BLOB data with DB2 or Firebird, because the length of a statement
|
9
5
|
# is limited to 32KB.
|
10
|
-
unless current_adapter?(:
|
6
|
+
unless current_adapter?(:SybaseAdapter, :DB2Adapter, :FirebirdAdapter)
|
11
7
|
require 'models/binary'
|
12
8
|
|
13
9
|
class BinaryTest < ActiveRecord::TestCase
|
@@ -25,6 +25,11 @@ class CalculationsTest < ActiveRecord::TestCase
|
|
25
25
|
def test_should_return_nil_as_average
|
26
26
|
assert_nil NumericData.average(:bank_balance)
|
27
27
|
end
|
28
|
+
|
29
|
+
def test_type_cast_calculated_value_should_convert_db_averages_of_fixnum_class_to_decimal
|
30
|
+
assert_equal 0, NumericData.send(:type_cast_calculated_value, 0, nil, 'avg')
|
31
|
+
assert_equal 53.0, NumericData.send(:type_cast_calculated_value, 53, nil, 'avg')
|
32
|
+
end
|
28
33
|
|
29
34
|
def test_should_get_maximum_of_field
|
30
35
|
assert_equal 60, Account.maximum(:credit_limit)
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "cases/helper"
|
2
|
+
|
3
|
+
class Comment < ActiveRecord::Base
|
4
|
+
attr_accessor :callers
|
5
|
+
|
6
|
+
before_validation :record_callers
|
7
|
+
|
8
|
+
def after_validation
|
9
|
+
record_callers
|
10
|
+
end
|
11
|
+
|
12
|
+
def record_callers
|
13
|
+
callers << self.class if callers
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class CommentObserver < ActiveRecord::Observer
|
18
|
+
attr_accessor :callers
|
19
|
+
|
20
|
+
def after_validation(model)
|
21
|
+
callers << self.class if callers
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class CallbacksObserversTest < ActiveRecord::TestCase
|
26
|
+
def test_model_callbacks_fire_before_observers_are_notified
|
27
|
+
callers = []
|
28
|
+
|
29
|
+
comment = Comment.new
|
30
|
+
comment.callers = callers
|
31
|
+
|
32
|
+
CommentObserver.instance.callers = callers
|
33
|
+
|
34
|
+
comment.valid?
|
35
|
+
|
36
|
+
assert_equal [Comment, Comment, CommentObserver], callers, "model callbacks did not fire before observers were notified"
|
37
|
+
end
|
38
|
+
end
|
data/test/cases/defaults_test.rb
CHANGED
@@ -19,6 +19,37 @@ class DefaultTest < ActiveRecord::TestCase
|
|
19
19
|
end
|
20
20
|
|
21
21
|
if current_adapter?(:MysqlAdapter)
|
22
|
+
|
23
|
+
#MySQL 5 and higher is quirky with not null text/blob columns.
|
24
|
+
#With MySQL Text/blob columns cannot have defaults. If the column is not null MySQL will report that the column has a null default
|
25
|
+
#but it behaves as though the column had a default of ''
|
26
|
+
def test_mysql_text_not_null_defaults
|
27
|
+
klass = Class.new(ActiveRecord::Base)
|
28
|
+
klass.table_name = 'test_mysql_text_not_null_defaults'
|
29
|
+
klass.connection.create_table klass.table_name do |t|
|
30
|
+
t.column :non_null_text, :text, :null => false
|
31
|
+
t.column :non_null_blob, :blob, :null => false
|
32
|
+
t.column :null_text, :text, :null => true
|
33
|
+
t.column :null_blob, :blob, :null => true
|
34
|
+
end
|
35
|
+
assert_equal '', klass.columns_hash['non_null_blob'].default
|
36
|
+
assert_equal '', klass.columns_hash['non_null_text'].default
|
37
|
+
|
38
|
+
assert_equal nil, klass.columns_hash['null_blob'].default
|
39
|
+
assert_equal nil, klass.columns_hash['null_text'].default
|
40
|
+
|
41
|
+
assert_nothing_raised do
|
42
|
+
instance = klass.create!
|
43
|
+
assert_equal '', instance.non_null_text
|
44
|
+
assert_equal '', instance.non_null_blob
|
45
|
+
assert_nil instance.null_text
|
46
|
+
assert_nil instance.null_blob
|
47
|
+
end
|
48
|
+
ensure
|
49
|
+
klass.connection.drop_table(klass.table_name) rescue nil
|
50
|
+
end
|
51
|
+
|
52
|
+
|
22
53
|
# MySQL uses an implicit default 0 rather than NULL unless in strict mode.
|
23
54
|
# We use an implicit NULL so schema.rb is compatible with other databases.
|
24
55
|
def test_mysql_integer_not_null_defaults
|
@@ -47,7 +78,7 @@ class DefaultTest < ActiveRecord::TestCase
|
|
47
78
|
end
|
48
79
|
end
|
49
80
|
|
50
|
-
if current_adapter?(:PostgreSQLAdapter, :
|
81
|
+
if current_adapter?(:PostgreSQLAdapter, :FirebirdAdapter, :OpenBaseAdapter, :OracleAdapter)
|
51
82
|
def test_default_integers
|
52
83
|
default = Default.new
|
53
84
|
assert_instance_of Fixnum, default.positive_integer
|
File without changes
|
data/test/cases/dirty_test.rb
CHANGED
@@ -45,6 +45,19 @@ class DirtyTest < ActiveRecord::TestCase
|
|
45
45
|
assert_nil pirate.catchphrase_change
|
46
46
|
end
|
47
47
|
|
48
|
+
def test_aliased_attribute_changes
|
49
|
+
# the actual attribute here is name, title is an
|
50
|
+
# alias setup via alias_attribute
|
51
|
+
parrot = Parrot.new
|
52
|
+
assert !parrot.title_changed?
|
53
|
+
assert_nil parrot.title_change
|
54
|
+
|
55
|
+
parrot.name = 'Sam'
|
56
|
+
assert parrot.title_changed?
|
57
|
+
assert_nil parrot.title_was
|
58
|
+
assert_equal parrot.name_change, parrot.title_change
|
59
|
+
end
|
60
|
+
|
48
61
|
def test_nullable_integer_not_marked_as_changed_if_new_value_is_blank
|
49
62
|
pirate = Pirate.new
|
50
63
|
|
data/test/cases/finder_test.rb
CHANGED
@@ -12,6 +12,57 @@ require 'models/customer'
|
|
12
12
|
require 'models/job'
|
13
13
|
require 'models/categorization'
|
14
14
|
|
15
|
+
class DynamicFinderMatchTest < ActiveRecord::TestCase
|
16
|
+
def test_find_no_match
|
17
|
+
assert_nil ActiveRecord::DynamicFinderMatch.match("not_a_finder")
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_find_by
|
21
|
+
match = ActiveRecord::DynamicFinderMatch.match("find_by_age_and_sex_and_location")
|
22
|
+
assert_not_nil match
|
23
|
+
assert match.finder?
|
24
|
+
assert_equal :first, match.finder
|
25
|
+
assert_equal %w(age sex location), match.attribute_names
|
26
|
+
end
|
27
|
+
|
28
|
+
def find_by_bang
|
29
|
+
match = ActiveRecord::DynamicFinderMatch.match("find_by_age_and_sex_and_location!")
|
30
|
+
assert_not_nil match
|
31
|
+
assert match.finder?
|
32
|
+
assert match.bang?
|
33
|
+
assert_equal :first, match.finder
|
34
|
+
assert_equal %w(age sex location), match.attribute_names
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_find_all_by
|
38
|
+
match = ActiveRecord::DynamicFinderMatch.match("find_all_by_age_and_sex_and_location")
|
39
|
+
assert_not_nil match
|
40
|
+
assert match.finder?
|
41
|
+
assert_equal :all, match.finder
|
42
|
+
assert_equal %w(age sex location), match.attribute_names
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_find_or_initialize_by
|
46
|
+
match = ActiveRecord::DynamicFinderMatch.match("find_or_initialize_by_age_and_sex_and_location")
|
47
|
+
assert_not_nil match
|
48
|
+
assert !match.finder?
|
49
|
+
assert match.instantiator?
|
50
|
+
assert_equal :first, match.finder
|
51
|
+
assert_equal :new, match.instantiator
|
52
|
+
assert_equal %w(age sex location), match.attribute_names
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_find_or_create_by
|
56
|
+
match = ActiveRecord::DynamicFinderMatch.match("find_or_create_by_age_and_sex_and_location")
|
57
|
+
assert_not_nil match
|
58
|
+
assert !match.finder?
|
59
|
+
assert match.instantiator?
|
60
|
+
assert_equal :first, match.finder
|
61
|
+
assert_equal :create, match.instantiator
|
62
|
+
assert_equal %w(age sex location), match.attribute_names
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
15
66
|
class FinderTest < ActiveRecord::TestCase
|
16
67
|
fixtures :companies, :topics, :entrants, :developers, :developers_projects, :posts, :comments, :accounts, :authors, :customers
|
17
68
|
|
@@ -118,6 +169,12 @@ class FinderTest < ActiveRecord::TestCase
|
|
118
169
|
assert_equal("fixture_3", developers.first.name)
|
119
170
|
end
|
120
171
|
|
172
|
+
def test_find_with_group
|
173
|
+
developers = Developer.find(:all, :group => "salary", :select => "salary")
|
174
|
+
assert_equal 4, developers.size
|
175
|
+
assert_equal 4, developers.map(&:salary).uniq.size
|
176
|
+
end
|
177
|
+
|
121
178
|
def test_find_with_entire_select_statement
|
122
179
|
topics = Topic.find_by_sql "SELECT * FROM topics WHERE author_name = 'Mary'"
|
123
180
|
|
@@ -146,11 +203,11 @@ class FinderTest < ActiveRecord::TestCase
|
|
146
203
|
first = Topic.find(:first, :conditions => "title = 'The First Topic!'")
|
147
204
|
assert_nil(first)
|
148
205
|
end
|
149
|
-
|
206
|
+
|
150
207
|
def test_first
|
151
208
|
assert_equal topics(:second).title, Topic.first(:conditions => "title = 'The Second Topic of the day'").title
|
152
209
|
end
|
153
|
-
|
210
|
+
|
154
211
|
def test_first_failing
|
155
212
|
assert_nil Topic.first(:conditions => "title = 'The Second Topic of the day!'")
|
156
213
|
end
|
@@ -200,6 +257,23 @@ class FinderTest < ActiveRecord::TestCase
|
|
200
257
|
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { 'topics.approved' => true }) }
|
201
258
|
end
|
202
259
|
|
260
|
+
def test_find_on_hash_conditions_with_hashed_table_name
|
261
|
+
assert Topic.find(1, :conditions => {:topics => { :approved => false }})
|
262
|
+
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => {:topics => { :approved => true }}) }
|
263
|
+
end
|
264
|
+
|
265
|
+
def test_find_with_hash_conditions_on_joined_table
|
266
|
+
firms = Firm.all :joins => :account, :conditions => {:accounts => { :credit_limit => 50 }}
|
267
|
+
assert_equal 1, firms.size
|
268
|
+
assert_equal companies(:first_firm), firms.first
|
269
|
+
end
|
270
|
+
|
271
|
+
def test_find_with_hash_conditions_on_joined_table_and_with_range
|
272
|
+
firms = DependentFirm.all :joins => :account, :conditions => {:name => 'RailsCore', :accounts => { :credit_limit => 55..60 }}
|
273
|
+
assert_equal 1, firms.size
|
274
|
+
assert_equal companies(:rails_core), firms.first
|
275
|
+
end
|
276
|
+
|
203
277
|
def test_find_on_hash_conditions_with_explicit_table_name_and_aggregate
|
204
278
|
david = customers(:david)
|
205
279
|
assert Customer.find(david.id, :conditions => { 'customers.name' => david.name, :address => david.address })
|
@@ -229,7 +303,6 @@ class FinderTest < ActiveRecord::TestCase
|
|
229
303
|
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { :author_name => "David", :title => "The First Topic", :replies_count => 1, :approved => true }) }
|
230
304
|
end
|
231
305
|
|
232
|
-
|
233
306
|
def test_condition_interpolation
|
234
307
|
assert_kind_of Firm, Company.find(:first, :conditions => ["name = '%s'", "37signals"])
|
235
308
|
assert_nil Company.find(:first, :conditions => ["name = '%s'", "37signals!"])
|
@@ -324,7 +397,7 @@ class FinderTest < ActiveRecord::TestCase
|
|
324
397
|
Company.find(:first, :conditions => ["id=? AND name = ?", 2])
|
325
398
|
}
|
326
399
|
assert_raises(ActiveRecord::PreparedStatementInvalid) {
|
327
|
-
|
400
|
+
Company.find(:first, :conditions => ["id=?", 2, 3, 4])
|
328
401
|
}
|
329
402
|
end
|
330
403
|
|
@@ -350,7 +423,7 @@ class FinderTest < ActiveRecord::TestCase
|
|
350
423
|
def test_named_bind_variables
|
351
424
|
assert_equal '1', bind(':a', :a => 1) # ' ruby-mode
|
352
425
|
assert_equal '1 1', bind(':a :a', :a => 1) # ' ruby-mode
|
353
|
-
|
426
|
+
|
354
427
|
assert_nothing_raised { bind("'+00:00'", :foo => "bar") }
|
355
428
|
|
356
429
|
assert_kind_of Firm, Company.find(:first, :conditions => ["name = :name", { :name => "37signals" }])
|
@@ -387,12 +460,13 @@ class FinderTest < ActiveRecord::TestCase
|
|
387
460
|
assert_equal ActiveRecord::Base.connection.quote(''), bind('?', '')
|
388
461
|
end
|
389
462
|
|
390
|
-
def
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
assert_equal
|
463
|
+
def test_bind_chars
|
464
|
+
quoted_bambi = ActiveRecord::Base.connection.quote("Bambi")
|
465
|
+
quoted_bambi_and_thumper = ActiveRecord::Base.connection.quote("Bambi\nand\nThumper")
|
466
|
+
assert_equal "name=#{quoted_bambi}", bind('name=?', "Bambi")
|
467
|
+
assert_equal "name=#{quoted_bambi_and_thumper}", bind('name=?', "Bambi\nand\nThumper")
|
468
|
+
assert_equal "name=#{quoted_bambi}", bind('name=?', "Bambi".mb_chars)
|
469
|
+
assert_equal "name=#{quoted_bambi_and_thumper}", bind('name=?', "Bambi\nand\nThumper".mb_chars)
|
396
470
|
end
|
397
471
|
|
398
472
|
def test_bind_record
|
@@ -426,11 +500,33 @@ class FinderTest < ActiveRecord::TestCase
|
|
426
500
|
assert_equal(2, Entrant.count_by_sql(["SELECT COUNT(*) FROM entrants WHERE id > ?", 1]))
|
427
501
|
end
|
428
502
|
|
503
|
+
uses_mocha('test_dynamic_finder_should_go_through_the_find_class_method') do
|
504
|
+
def test_dynamic_finders_should_go_through_the_find_class_method
|
505
|
+
Topic.expects(:find).with(:first, :conditions => { :title => 'The First Topic!' })
|
506
|
+
Topic.find_by_title("The First Topic!")
|
507
|
+
|
508
|
+
Topic.expects(:find).with(:last, :conditions => { :title => 'The Last Topic!' })
|
509
|
+
Topic.find_last_by_title("The Last Topic!")
|
510
|
+
|
511
|
+
Topic.expects(:find).with(:all, :conditions => { :title => 'A Topic.' })
|
512
|
+
Topic.find_all_by_title("A Topic.")
|
513
|
+
|
514
|
+
Topic.expects(:find).with(:first, :conditions => { :title => 'Does not exist yet for sure!' }).times(2)
|
515
|
+
Topic.find_or_initialize_by_title('Does not exist yet for sure!')
|
516
|
+
Topic.find_or_create_by_title('Does not exist yet for sure!')
|
517
|
+
end
|
518
|
+
end
|
519
|
+
|
429
520
|
def test_find_by_one_attribute
|
430
521
|
assert_equal topics(:first), Topic.find_by_title("The First Topic")
|
431
522
|
assert_nil Topic.find_by_title("The First Topic!")
|
432
523
|
end
|
433
524
|
|
525
|
+
def test_find_by_one_attribute_bang
|
526
|
+
assert_equal topics(:first), Topic.find_by_title!("The First Topic")
|
527
|
+
assert_raises(ActiveRecord::RecordNotFound) { Topic.find_by_title!("The First Topic!") }
|
528
|
+
end
|
529
|
+
|
434
530
|
def test_find_by_one_attribute_caches_dynamic_finder
|
435
531
|
# ensure this test can run independently of order
|
436
532
|
class << Topic; self; end.send(:remove_method, :find_by_title) if Topic.public_methods.any? { |m| m.to_s == 'find_by_title' }
|
@@ -524,6 +620,38 @@ class FinderTest < ActiveRecord::TestCase
|
|
524
620
|
assert_nil Topic.find_by_title_and_author_name("The First Topic", "Mary")
|
525
621
|
end
|
526
622
|
|
623
|
+
def test_find_last_by_one_attribute
|
624
|
+
assert_equal Topic.last, Topic.find_last_by_title(Topic.last.title)
|
625
|
+
assert_nil Topic.find_last_by_title("A title with no matches")
|
626
|
+
end
|
627
|
+
|
628
|
+
def test_find_last_by_one_attribute_caches_dynamic_finder
|
629
|
+
# ensure this test can run independently of order
|
630
|
+
class << Topic; self; end.send(:remove_method, :find_last_by_title) if Topic.public_methods.any? { |m| m.to_s == 'find_last_by_title' }
|
631
|
+
assert !Topic.public_methods.any? { |m| m.to_s == 'find_last_by_title' }
|
632
|
+
t = Topic.find_last_by_title(Topic.last.title)
|
633
|
+
assert Topic.public_methods.any? { |m| m.to_s == 'find_last_by_title' }
|
634
|
+
end
|
635
|
+
|
636
|
+
def test_find_last_by_invalid_method_syntax
|
637
|
+
assert_raises(NoMethodError) { Topic.fail_to_find_last_by_title("The First Topic") }
|
638
|
+
assert_raises(NoMethodError) { Topic.find_last_by_title?("The First Topic") }
|
639
|
+
end
|
640
|
+
|
641
|
+
def test_find_last_by_one_attribute_with_several_options
|
642
|
+
assert_equal accounts(:signals37), Account.find_last_by_credit_limit(50, :order => 'id DESC', :conditions => ['id != ?', 3])
|
643
|
+
end
|
644
|
+
|
645
|
+
def test_find_last_by_one_missing_attribute
|
646
|
+
assert_raises(NoMethodError) { Topic.find_last_by_undertitle("The Last Topic!") }
|
647
|
+
end
|
648
|
+
|
649
|
+
def test_find_last_by_two_attributes
|
650
|
+
topic = Topic.last
|
651
|
+
assert_equal topic, Topic.find_last_by_title_and_author_name(topic.title, topic.author_name)
|
652
|
+
assert_nil Topic.find_last_by_title_and_author_name(topic.title, "Anonymous")
|
653
|
+
end
|
654
|
+
|
527
655
|
def test_find_all_by_one_attribute
|
528
656
|
topics = Topic.find_all_by_content("Have a nice day")
|
529
657
|
assert_equal 2, topics.size
|
@@ -717,7 +845,18 @@ class FinderTest < ActiveRecord::TestCase
|
|
717
845
|
assert c.valid?
|
718
846
|
assert !c.new_record?
|
719
847
|
end
|
720
|
-
|
848
|
+
|
849
|
+
def test_find_or_create_should_work_with_block_on_first_call
|
850
|
+
class << Company
|
851
|
+
undef_method(:find_or_create_by_name) if method_defined?(:find_or_create_by_name)
|
852
|
+
end
|
853
|
+
c = Company.find_or_create_by_name(:name => "Fortune 1000") { |f| f.rating = 1000 }
|
854
|
+
assert_equal "Fortune 1000", c.name
|
855
|
+
assert_equal 1000.to_f, c.rating.to_f
|
856
|
+
assert c.valid?
|
857
|
+
assert !c.new_record?
|
858
|
+
end
|
859
|
+
|
721
860
|
def test_dynamic_find_or_initialize_from_one_attribute_caches_method
|
722
861
|
class << Company; self; end.send(:remove_method, :find_or_initialize_by_name) if Company.public_methods.any? { |m| m.to_s == 'find_or_initialize_by_name' }
|
723
862
|
assert !Company.public_methods.any? { |m| m.to_s == 'find_or_initialize_by_name' }
|
@@ -824,6 +963,17 @@ class FinderTest < ActiveRecord::TestCase
|
|
824
963
|
assert_equal 1, first.id
|
825
964
|
end
|
826
965
|
|
966
|
+
def test_joins_with_string_array
|
967
|
+
person_with_reader_and_post = Post.find(
|
968
|
+
:all,
|
969
|
+
:joins => [
|
970
|
+
"INNER JOIN categorizations ON categorizations.post_id = posts.id",
|
971
|
+
"INNER JOIN categories ON categories.id = categorizations.category_id AND categories.type = 'SpecialCategory'"
|
972
|
+
]
|
973
|
+
)
|
974
|
+
assert_equal 1, person_with_reader_and_post.size
|
975
|
+
end
|
976
|
+
|
827
977
|
def test_find_by_id_with_conditions_with_or
|
828
978
|
assert_nothing_raised do
|
829
979
|
Post.find([1,2,3],
|
data/test/cases/fixtures_test.rb
CHANGED
@@ -15,6 +15,7 @@ require 'models/pirate'
|
|
15
15
|
require 'models/treasure'
|
16
16
|
require 'models/matey'
|
17
17
|
require 'models/ship'
|
18
|
+
require 'models/book'
|
18
19
|
|
19
20
|
class FixturesTest < ActiveRecord::TestCase
|
20
21
|
self.use_instantiated_fixtures = true
|
@@ -373,6 +374,34 @@ class CheckSetTableNameFixturesTest < ActiveRecord::TestCase
|
|
373
374
|
end
|
374
375
|
end
|
375
376
|
|
377
|
+
class FixtureNameIsNotTableNameFixturesTest < ActiveRecord::TestCase
|
378
|
+
set_fixture_class :items => Book
|
379
|
+
fixtures :items
|
380
|
+
# Set to false to blow away fixtures cache and ensure our fixtures are loaded
|
381
|
+
# and thus takes into account our set_fixture_class
|
382
|
+
self.use_transactional_fixtures = false
|
383
|
+
|
384
|
+
def test_named_accessor
|
385
|
+
assert_kind_of Book, items(:dvd)
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
class FixtureNameIsNotTableNameMultipleFixturesTest < ActiveRecord::TestCase
|
390
|
+
set_fixture_class :items => Book, :funny_jokes => Joke
|
391
|
+
fixtures :items, :funny_jokes
|
392
|
+
# Set to false to blow away fixtures cache and ensure our fixtures are loaded
|
393
|
+
# and thus takes into account our set_fixture_class
|
394
|
+
self.use_transactional_fixtures = false
|
395
|
+
|
396
|
+
def test_named_accessor_of_differently_named_fixture
|
397
|
+
assert_kind_of Book, items(:dvd)
|
398
|
+
end
|
399
|
+
|
400
|
+
def test_named_accessor_of_same_named_fixture
|
401
|
+
assert_kind_of Joke, funny_jokes(:a_joke)
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
376
405
|
class CustomConnectionFixturesTest < ActiveRecord::TestCase
|
377
406
|
set_fixture_class :courses => Course
|
378
407
|
fixtures :courses
|
@@ -432,11 +461,11 @@ class FixturesBrokenRollbackTest < ActiveRecord::TestCase
|
|
432
461
|
alias_method :teardown, :blank_teardown
|
433
462
|
|
434
463
|
def test_no_rollback_in_teardown_unless_transaction_active
|
435
|
-
assert_equal 0,
|
464
|
+
assert_equal 0, ActiveRecord::Base.connection.open_transactions
|
436
465
|
assert_raise(RuntimeError) { ar_setup_fixtures }
|
437
|
-
assert_equal 0,
|
466
|
+
assert_equal 0, ActiveRecord::Base.connection.open_transactions
|
438
467
|
assert_nothing_raised { ar_teardown_fixtures }
|
439
|
-
assert_equal 0,
|
468
|
+
assert_equal 0, ActiveRecord::Base.connection.open_transactions
|
440
469
|
end
|
441
470
|
|
442
471
|
private
|