activerecord 2.2.3 → 2.3.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 +438 -396
- data/Rakefile +4 -2
- data/lib/active_record.rb +46 -43
- data/lib/active_record/association_preload.rb +34 -19
- data/lib/active_record/associations.rb +193 -251
- data/lib/active_record/associations/association_collection.rb +38 -21
- data/lib/active_record/associations/association_proxy.rb +11 -4
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +2 -2
- data/lib/active_record/associations/has_many_association.rb +2 -2
- data/lib/active_record/associations/has_many_through_association.rb +8 -8
- data/lib/active_record/associations/has_one_association.rb +11 -2
- data/lib/active_record/attribute_methods.rb +1 -0
- data/lib/active_record/autosave_association.rb +349 -0
- data/lib/active_record/base.rb +292 -106
- data/lib/active_record/batches.rb +73 -0
- data/lib/active_record/calculations.rb +34 -16
- data/lib/active_record/callbacks.rb +37 -8
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +16 -0
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +3 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +103 -15
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +6 -6
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +28 -25
- data/lib/active_record/connection_adapters/abstract_adapter.rb +29 -5
- data/lib/active_record/connection_adapters/mysql_adapter.rb +50 -21
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +26 -41
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +41 -21
- data/lib/active_record/dirty.rb +1 -1
- data/lib/active_record/dynamic_scope_match.rb +25 -0
- data/lib/active_record/fixtures.rb +193 -198
- data/lib/active_record/locale/en.yml +1 -1
- data/lib/active_record/locking/optimistic.rb +33 -0
- data/lib/active_record/migration.rb +8 -2
- data/lib/active_record/named_scope.rb +13 -6
- data/lib/active_record/nested_attributes.rb +329 -0
- data/lib/active_record/query_cache.rb +25 -13
- data/lib/active_record/reflection.rb +6 -1
- data/lib/active_record/schema_dumper.rb +2 -0
- data/lib/active_record/serialization.rb +3 -1
- data/lib/active_record/serializers/json_serializer.rb +19 -0
- data/lib/active_record/serializers/xml_serializer.rb +28 -13
- data/lib/active_record/session_store.rb +318 -0
- data/lib/active_record/test_case.rb +15 -9
- data/lib/active_record/timestamp.rb +2 -2
- data/lib/active_record/transactions.rb +58 -8
- data/lib/active_record/validations.rb +29 -24
- data/lib/active_record/version.rb +2 -2
- data/test/cases/ar_schema_test.rb +0 -1
- data/test/cases/associations/belongs_to_associations_test.rb +35 -131
- data/test/cases/associations/cascaded_eager_loading_test.rb +8 -0
- data/test/cases/associations/eager_load_nested_include_test.rb +29 -0
- data/test/cases/associations/eager_test.rb +137 -7
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +45 -7
- data/test/cases/associations/has_many_associations_test.rb +110 -149
- data/test/cases/associations/has_many_through_associations_test.rb +39 -7
- data/test/cases/associations/has_one_associations_test.rb +39 -92
- data/test/cases/associations/has_one_through_associations_test.rb +34 -3
- data/test/cases/associations/inner_join_association_test.rb +0 -5
- data/test/cases/associations/join_model_test.rb +5 -7
- data/test/cases/attribute_methods_test.rb +13 -1
- data/test/cases/autosave_association_test.rb +901 -0
- data/test/cases/base_test.rb +41 -21
- data/test/cases/batches_test.rb +61 -0
- data/test/cases/calculations_test.rb +37 -17
- data/test/cases/callbacks_test.rb +43 -5
- data/test/cases/connection_pool_test.rb +25 -0
- data/test/cases/copy_table_test_sqlite.rb +11 -0
- data/test/cases/datatype_test_postgresql.rb +1 -0
- data/test/cases/defaults_test.rb +37 -26
- data/test/cases/dirty_test.rb +26 -2
- data/test/cases/finder_test.rb +79 -44
- data/test/cases/fixtures_test.rb +15 -19
- data/test/cases/helper.rb +26 -19
- data/test/cases/inheritance_test.rb +2 -2
- data/test/cases/json_serialization_test.rb +1 -1
- data/test/cases/locking_test.rb +23 -5
- data/test/cases/method_scoping_test.rb +126 -3
- data/test/cases/migration_test.rb +253 -237
- data/test/cases/named_scope_test.rb +73 -3
- data/test/cases/nested_attributes_test.rb +509 -0
- data/test/cases/query_cache_test.rb +0 -4
- data/test/cases/reflection_test.rb +13 -3
- data/test/cases/reload_models_test.rb +3 -1
- data/test/cases/repair_helper.rb +50 -0
- data/test/cases/schema_dumper_test.rb +0 -1
- data/test/cases/transactions_test.rb +177 -12
- data/test/cases/validations_i18n_test.rb +288 -294
- data/test/cases/validations_test.rb +230 -180
- data/test/cases/xml_serialization_test.rb +19 -1
- data/test/fixtures/fixture_database.sqlite3 +0 -0
- data/test/fixtures/fixture_database_2.sqlite3 +0 -0
- data/test/fixtures/member_types.yml +6 -0
- data/test/fixtures/members.yml +3 -1
- data/test/fixtures/people.yml +10 -1
- data/test/fixtures/toys.yml +4 -0
- data/test/models/author.rb +1 -2
- data/test/models/bird.rb +3 -0
- data/test/models/category.rb +1 -0
- data/test/models/company.rb +3 -0
- data/test/models/developer.rb +12 -0
- data/test/models/event.rb +3 -0
- data/test/models/member.rb +1 -0
- data/test/models/member_detail.rb +1 -0
- data/test/models/member_type.rb +3 -0
- data/test/models/owner.rb +2 -1
- data/test/models/parrot.rb +2 -0
- data/test/models/person.rb +6 -0
- data/test/models/pet.rb +2 -1
- data/test/models/pirate.rb +55 -1
- data/test/models/post.rb +6 -0
- data/test/models/project.rb +1 -0
- data/test/models/reply.rb +6 -0
- data/test/models/ship.rb +8 -1
- data/test/models/ship_part.rb +5 -0
- data/test/models/topic.rb +13 -1
- data/test/models/toy.rb +4 -0
- data/test/schema/schema.rb +35 -2
- metadata +70 -9
- data/test/fixtures/fixture_database.sqlite +0 -0
- data/test/fixtures/fixture_database_2.sqlite +0 -0
@@ -104,6 +104,14 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase
|
|
104
104
|
authors.first.posts.first.special_comments.first.post.very_special_comment
|
105
105
|
end
|
106
106
|
end
|
107
|
+
|
108
|
+
def test_eager_association_loading_where_first_level_returns_nil
|
109
|
+
authors = Author.find(:all, :include => {:post_about_thinking => :comments}, :order => 'authors.id DESC')
|
110
|
+
assert_equal [authors(:mary), authors(:david)], authors
|
111
|
+
assert_no_queries do
|
112
|
+
authors[1].post_about_thinking.comments.first
|
113
|
+
end
|
114
|
+
end
|
107
115
|
end
|
108
116
|
|
109
117
|
require 'models/vertex'
|
@@ -1,4 +1,9 @@
|
|
1
1
|
require 'cases/helper'
|
2
|
+
require 'models/author'
|
3
|
+
require 'models/post'
|
4
|
+
require 'models/comment'
|
5
|
+
require 'models/category'
|
6
|
+
require 'models/categorization'
|
2
7
|
|
3
8
|
module Remembered
|
4
9
|
def self.included(base)
|
@@ -99,3 +104,27 @@ class EagerLoadPolyAssocsTest < ActiveRecord::TestCase
|
|
99
104
|
end
|
100
105
|
end
|
101
106
|
end
|
107
|
+
|
108
|
+
class EagerLoadNestedIncludeWithMissingDataTest < ActiveRecord::TestCase
|
109
|
+
def setup
|
110
|
+
@davey_mcdave = Author.create(:name => 'Davey McDave')
|
111
|
+
@first_post = @davey_mcdave.posts.create(:title => 'Davey Speaks', :body => 'Expressive wordage')
|
112
|
+
@first_comment = @first_post.comments.create(:body => 'Inflamatory doublespeak')
|
113
|
+
@first_categorization = @davey_mcdave.categorizations.create(:category => Category.first, :post => @first_post)
|
114
|
+
end
|
115
|
+
|
116
|
+
def teardown
|
117
|
+
@davey_mcdave.destroy
|
118
|
+
@first_post.destroy
|
119
|
+
@first_comment.destroy
|
120
|
+
@first_categorization.destroy
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_missing_data_in_a_nested_include_should_not_cause_errors_when_constructing_objects
|
124
|
+
assert_nothing_raised do
|
125
|
+
# @davey_mcdave doesn't have any author_favorites
|
126
|
+
includes = {:posts => :comments, :categorizations => :category, :author_favorites => :favorite_author }
|
127
|
+
Author.all :include => includes, :conditions => {:authors => {:name => @davey_mcdave.name}}, :order => 'categories.name'
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require "cases/helper"
|
2
2
|
require 'models/post'
|
3
3
|
require 'models/tagging'
|
4
|
+
require 'models/tag'
|
4
5
|
require 'models/comment'
|
5
6
|
require 'models/author'
|
6
7
|
require 'models/category'
|
@@ -145,7 +146,7 @@ class EagerAssociationTest < ActiveRecord::TestCase
|
|
145
146
|
def test_finding_with_includes_on_null_belongs_to_association_with_same_include_includes_only_once
|
146
147
|
post = posts(:welcome)
|
147
148
|
post.update_attributes!(:author => nil)
|
148
|
-
post = assert_queries(
|
149
|
+
post = assert_queries(1) { Post.find(post.id, :include => {:author_with_address => :author_address}) } # find the post, then find the author which is null so no query for the author or address
|
149
150
|
assert_no_queries do
|
150
151
|
assert_equal nil, post.author_with_address
|
151
152
|
end
|
@@ -385,12 +386,28 @@ class EagerAssociationTest < ActiveRecord::TestCase
|
|
385
386
|
assert_equal count, posts.size
|
386
387
|
end
|
387
388
|
|
388
|
-
def
|
389
|
+
def test_eager_with_has_many_and_limit_and_high_offset
|
389
390
|
posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :offset => 10, :conditions => [ "authors.name = ?", 'David' ])
|
390
391
|
assert_equal 0, posts.size
|
391
392
|
end
|
392
393
|
|
393
|
-
def
|
394
|
+
def test_eager_with_has_many_and_limit_and_high_offset_and_multiple_array_conditions
|
395
|
+
assert_queries(1) do
|
396
|
+
posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :offset => 10,
|
397
|
+
:conditions => [ "authors.name = ? and comments.body = ?", 'David', 'go crazy' ])
|
398
|
+
assert_equal 0, posts.size
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
def test_eager_with_has_many_and_limit_and_high_offset_and_multiple_hash_conditions
|
403
|
+
assert_queries(1) do
|
404
|
+
posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :offset => 10,
|
405
|
+
:conditions => { 'authors.name' => 'David', 'comments.body' => 'go crazy' })
|
406
|
+
assert_equal 0, posts.size
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
def test_count_eager_with_has_many_and_limit_and_high_offset
|
394
411
|
posts = Post.count(:all, :include => [ :author, :comments ], :limit => 2, :offset => 10, :conditions => [ "authors.name = ?", 'David' ])
|
395
412
|
assert_equal 0, posts
|
396
413
|
end
|
@@ -532,16 +549,16 @@ class EagerAssociationTest < ActiveRecord::TestCase
|
|
532
549
|
end
|
533
550
|
|
534
551
|
def test_eager_with_invalid_association_reference
|
535
|
-
|
552
|
+
assert_raise(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
|
536
553
|
post = Post.find(6, :include=> :monkeys )
|
537
554
|
}
|
538
|
-
|
555
|
+
assert_raise(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
|
539
556
|
post = Post.find(6, :include=>[ :monkeys ])
|
540
557
|
}
|
541
|
-
|
558
|
+
assert_raise(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
|
542
559
|
post = Post.find(6, :include=>[ 'monkeys' ])
|
543
560
|
}
|
544
|
-
|
561
|
+
assert_raise(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys, :elephants") {
|
545
562
|
post = Post.find(6, :include=>[ :monkeys, :elephants ])
|
546
563
|
}
|
547
564
|
end
|
@@ -689,4 +706,117 @@ class EagerAssociationTest < ActiveRecord::TestCase
|
|
689
706
|
def test_order_on_join_table_with_include_and_limit
|
690
707
|
assert_equal 5, Developer.find(:all, :include => 'projects', :order => 'developers_projects.joined_on DESC', :limit => 5).size
|
691
708
|
end
|
709
|
+
|
710
|
+
def test_eager_loading_with_order_on_joined_table_preloads
|
711
|
+
posts = assert_queries(2) do
|
712
|
+
Post.find(:all, :joins => :comments, :include => :author, :order => 'comments.id DESC')
|
713
|
+
end
|
714
|
+
assert_equal posts(:eager_other), posts[0]
|
715
|
+
assert_equal authors(:mary), assert_no_queries { posts[0].author}
|
716
|
+
end
|
717
|
+
|
718
|
+
def test_eager_loading_with_conditions_on_joined_table_preloads
|
719
|
+
posts = assert_queries(2) do
|
720
|
+
Post.find(:all, :select => 'distinct posts.*', :include => :author, :joins => [:comments], :conditions => "comments.body like 'Thank you%'", :order => 'posts.id')
|
721
|
+
end
|
722
|
+
assert_equal [posts(:welcome)], posts
|
723
|
+
assert_equal authors(:david), assert_no_queries { posts[0].author}
|
724
|
+
|
725
|
+
posts = assert_queries(2) do
|
726
|
+
Post.find(:all, :select => 'distinct posts.*', :include => :author, :joins => [:comments], :conditions => "comments.body like 'Thank you%'", :order => 'posts.id')
|
727
|
+
end
|
728
|
+
assert_equal [posts(:welcome)], posts
|
729
|
+
assert_equal authors(:david), assert_no_queries { posts[0].author}
|
730
|
+
|
731
|
+
posts = assert_queries(2) do
|
732
|
+
Post.find(:all, :include => :author, :joins => {:taggings => :tag}, :conditions => "tags.name = 'General'", :order => 'posts.id')
|
733
|
+
end
|
734
|
+
assert_equal posts(:welcome, :thinking), posts
|
735
|
+
|
736
|
+
posts = assert_queries(2) do
|
737
|
+
Post.find(:all, :include => :author, :joins => {:taggings => {:tag => :taggings}}, :conditions => "taggings_tags.super_tag_id=2", :order => 'posts.id')
|
738
|
+
end
|
739
|
+
assert_equal posts(:welcome, :thinking), posts
|
740
|
+
|
741
|
+
end
|
742
|
+
|
743
|
+
def test_eager_loading_with_conditions_on_string_joined_table_preloads
|
744
|
+
posts = assert_queries(2) do
|
745
|
+
Post.find(:all, :select => 'distinct posts.*', :include => :author, :joins => "INNER JOIN comments on comments.post_id = posts.id", :conditions => "comments.body like 'Thank you%'", :order => 'posts.id')
|
746
|
+
end
|
747
|
+
assert_equal [posts(:welcome)], posts
|
748
|
+
assert_equal authors(:david), assert_no_queries { posts[0].author}
|
749
|
+
|
750
|
+
posts = assert_queries(2) do
|
751
|
+
Post.find(:all, :select => 'distinct posts.*', :include => :author, :joins => ["INNER JOIN comments on comments.post_id = posts.id"], :conditions => "comments.body like 'Thank you%'", :order => 'posts.id')
|
752
|
+
end
|
753
|
+
assert_equal [posts(:welcome)], posts
|
754
|
+
assert_equal authors(:david), assert_no_queries { posts[0].author}
|
755
|
+
|
756
|
+
end
|
757
|
+
|
758
|
+
def test_eager_loading_with_select_on_joined_table_preloads
|
759
|
+
posts = assert_queries(2) do
|
760
|
+
Post.find(:all, :select => 'posts.*, authors.name as author_name', :include => :comments, :joins => :author, :order => 'posts.id')
|
761
|
+
end
|
762
|
+
assert_equal 'David', posts[0].author_name
|
763
|
+
assert_equal posts(:welcome).comments, assert_no_queries { posts[0].comments}
|
764
|
+
end
|
765
|
+
|
766
|
+
def test_eager_loading_with_conditions_on_join_model_preloads
|
767
|
+
authors = assert_queries(2) do
|
768
|
+
Author.find(:all, :include => :author_address, :joins => :comments, :conditions => "posts.title like 'Welcome%'")
|
769
|
+
end
|
770
|
+
assert_equal authors(:david), authors[0]
|
771
|
+
assert_equal author_addresses(:david_address), authors[0].author_address
|
772
|
+
end
|
773
|
+
|
774
|
+
def test_preload_belongs_to_uses_exclusive_scope
|
775
|
+
people = Person.males.find(:all, :include => :primary_contact)
|
776
|
+
assert_not_equal people.length, 0
|
777
|
+
people.each do |person|
|
778
|
+
assert_no_queries {assert_not_nil person.primary_contact}
|
779
|
+
assert_equal Person.find(person.id).primary_contact, person.primary_contact
|
780
|
+
end
|
781
|
+
end
|
782
|
+
|
783
|
+
def test_preload_has_many_uses_exclusive_scope
|
784
|
+
people = Person.males.find :all, :include => :agents
|
785
|
+
people.each do |person|
|
786
|
+
assert_equal Person.find(person.id).agents, person.agents
|
787
|
+
end
|
788
|
+
end
|
789
|
+
|
790
|
+
def test_preload_has_many_using_primary_key
|
791
|
+
expected = Firm.find(:first).clients_using_primary_key.to_a
|
792
|
+
firm = Firm.find :first, :include => :clients_using_primary_key
|
793
|
+
assert_no_queries do
|
794
|
+
assert_equal expected, firm.clients_using_primary_key
|
795
|
+
end
|
796
|
+
end
|
797
|
+
|
798
|
+
def test_include_has_many_using_primary_key
|
799
|
+
expected = Firm.find(1).clients_using_primary_key.sort_by &:name
|
800
|
+
firm = Firm.find 1, :include => :clients_using_primary_key, :order => 'clients_using_primary_keys_companies.name'
|
801
|
+
assert_no_queries do
|
802
|
+
assert_equal expected, firm.clients_using_primary_key
|
803
|
+
end
|
804
|
+
end
|
805
|
+
|
806
|
+
def test_preload_has_one_using_primary_key
|
807
|
+
expected = Firm.find(:first).account_using_primary_key
|
808
|
+
firm = Firm.find :first, :include => :account_using_primary_key
|
809
|
+
assert_no_queries do
|
810
|
+
assert_equal expected, firm.account_using_primary_key
|
811
|
+
end
|
812
|
+
end
|
813
|
+
|
814
|
+
def test_include_has_one_using_primary_key
|
815
|
+
expected = Firm.find(1).account_using_primary_key
|
816
|
+
firm = Firm.find(:all, :include => :account_using_primary_key, :order => 'accounts.id').detect {|f| f.id == 1}
|
817
|
+
assert_no_queries do
|
818
|
+
assert_equal expected, firm.account_using_primary_key
|
819
|
+
end
|
820
|
+
end
|
821
|
+
|
692
822
|
end
|
@@ -381,6 +381,33 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
|
|
381
381
|
assert_date_from_db Date.new(2004, 10, 10), Developer.find(1).projects.first.joined_on.to_date
|
382
382
|
end
|
383
383
|
|
384
|
+
def test_destroying
|
385
|
+
david = Developer.find(1)
|
386
|
+
active_record = Project.find(1)
|
387
|
+
david.projects.reload
|
388
|
+
assert_equal 2, david.projects.size
|
389
|
+
assert_equal 3, active_record.developers.size
|
390
|
+
|
391
|
+
assert_difference "Project.count", -1 do
|
392
|
+
david.projects.destroy(active_record)
|
393
|
+
end
|
394
|
+
|
395
|
+
assert_equal 1, david.reload.projects.size
|
396
|
+
assert_equal 1, david.projects(true).size
|
397
|
+
end
|
398
|
+
|
399
|
+
def test_destroying_array
|
400
|
+
david = Developer.find(1)
|
401
|
+
david.projects.reload
|
402
|
+
|
403
|
+
assert_difference "Project.count", -Project.count do
|
404
|
+
david.projects.destroy(Project.find(:all))
|
405
|
+
end
|
406
|
+
|
407
|
+
assert_equal 0, david.reload.projects.size
|
408
|
+
assert_equal 0, david.projects(true).size
|
409
|
+
end
|
410
|
+
|
384
411
|
def test_destroy_all
|
385
412
|
david = Developer.find(1)
|
386
413
|
david.projects.reload
|
@@ -616,7 +643,7 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
|
|
616
643
|
def test_updating_attributes_on_rich_associations
|
617
644
|
david = projects(:action_controller).developers.first
|
618
645
|
david.name = "DHH"
|
619
|
-
|
646
|
+
assert_raise(ActiveRecord::ReadOnlyRecord) { david.save! }
|
620
647
|
end
|
621
648
|
|
622
649
|
def test_updating_attributes_on_rich_associations_with_limited_find_from_reflection
|
@@ -658,6 +685,11 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
|
|
658
685
|
assert_equal 1, categories(:technology).posts_gruoped_by_title.size
|
659
686
|
end
|
660
687
|
|
688
|
+
def test_find_scoped_grouped_having
|
689
|
+
assert_equal 2, projects(:active_record).well_payed_salary_groups.size
|
690
|
+
assert projects(:active_record).well_payed_salary_groups.all? { |g| g.salary > 10000 }
|
691
|
+
end
|
692
|
+
|
661
693
|
def test_get_ids
|
662
694
|
assert_equal projects(:active_record, :action_controller).map(&:id).sort, developers(:david).project_ids.sort
|
663
695
|
assert_equal [projects(:active_record).id], developers(:jamis).project_ids
|
@@ -735,6 +767,14 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
|
|
735
767
|
assert_equal developer, project.developers.find(:first)
|
736
768
|
assert_equal project, developer.projects.find(:first)
|
737
769
|
end
|
770
|
+
|
771
|
+
def test_self_referential_habtm_without_foreign_key_set_should_raise_exception
|
772
|
+
assert_raise(ActiveRecord::HasAndBelongsToManyAssociationForeignKeyNeeded) {
|
773
|
+
Member.class_eval do
|
774
|
+
has_and_belongs_to_many :friends, :class_name => "Member", :join_table => "member_friends"
|
775
|
+
end
|
776
|
+
}
|
777
|
+
end
|
738
778
|
|
739
779
|
def test_dynamic_find_should_respect_association_include
|
740
780
|
# SQL error in sort clause if :include is not included
|
@@ -762,12 +802,10 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
|
|
762
802
|
assert_equal 1, developer.projects.count
|
763
803
|
end
|
764
804
|
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
# nothing
|
770
|
-
end
|
805
|
+
def test_association_proxy_transaction_method_starts_transaction_in_association_class
|
806
|
+
Post.expects(:transaction)
|
807
|
+
Category.find(:first).posts.transaction do
|
808
|
+
# nothing
|
771
809
|
end
|
772
810
|
end
|
773
811
|
|
@@ -70,6 +70,10 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
|
|
70
70
|
assert_equal 2, companies(:first_firm).limited_clients.find(:all, :limit => nil).size
|
71
71
|
end
|
72
72
|
|
73
|
+
def test_dynamic_find_last_without_specified_order
|
74
|
+
assert_equal companies(:second_client), companies(:first_firm).unsorted_clients.find_last_by_type('Client')
|
75
|
+
end
|
76
|
+
|
73
77
|
def test_dynamic_find_should_respect_association_order
|
74
78
|
assert_equal companies(:second_client), companies(:first_firm).clients_sorted_desc.find(:first, :conditions => "type = 'Client'")
|
75
79
|
assert_equal companies(:second_client), companies(:first_firm).clients_sorted_desc.find_by_type('Client')
|
@@ -176,7 +180,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
|
|
176
180
|
def test_find_ids
|
177
181
|
firm = Firm.find(:first)
|
178
182
|
|
179
|
-
|
183
|
+
assert_raise(ActiveRecord::RecordNotFound) { firm.clients.find }
|
180
184
|
|
181
185
|
client = firm.clients.find(2)
|
182
186
|
assert_kind_of Client, client
|
@@ -190,7 +194,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
|
|
190
194
|
assert_equal 2, client_ary.size
|
191
195
|
assert_equal client, client_ary.first
|
192
196
|
|
193
|
-
|
197
|
+
assert_raise(ActiveRecord::RecordNotFound) { firm.clients.find(2, 99) }
|
194
198
|
end
|
195
199
|
|
196
200
|
def test_find_string_ids_when_using_finder_sql
|
@@ -215,6 +219,45 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
|
|
215
219
|
assert_equal 1, firm.clients.find(:all, :conditions => "name = 'Summit'").length
|
216
220
|
end
|
217
221
|
|
222
|
+
def test_find_each
|
223
|
+
firm = companies(:first_firm)
|
224
|
+
|
225
|
+
assert ! firm.clients.loaded?
|
226
|
+
|
227
|
+
assert_queries(3) do
|
228
|
+
firm.clients.find_each(:batch_size => 1) {|c| assert_equal firm.id, c.firm_id }
|
229
|
+
end
|
230
|
+
|
231
|
+
assert ! firm.clients.loaded?
|
232
|
+
end
|
233
|
+
|
234
|
+
def test_find_each_with_conditions
|
235
|
+
firm = companies(:first_firm)
|
236
|
+
|
237
|
+
assert_queries(2) do
|
238
|
+
firm.clients.find_each(:batch_size => 1, :conditions => {:name => "Microsoft"}) do |c|
|
239
|
+
assert_equal firm.id, c.firm_id
|
240
|
+
assert_equal "Microsoft", c.name
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
assert ! firm.clients.loaded?
|
245
|
+
end
|
246
|
+
|
247
|
+
def test_find_in_batches
|
248
|
+
firm = companies(:first_firm)
|
249
|
+
|
250
|
+
assert ! firm.clients.loaded?
|
251
|
+
|
252
|
+
assert_queries(2) do
|
253
|
+
firm.clients.find_in_batches(:batch_size => 2) do |clients|
|
254
|
+
clients.each {|c| assert_equal firm.id, c.firm_id }
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
assert ! firm.clients.loaded?
|
259
|
+
end
|
260
|
+
|
218
261
|
def test_find_all_sanitized
|
219
262
|
firm = Firm.find(:first)
|
220
263
|
summit = firm.clients.find(:all, :conditions => "name = 'Summit'")
|
@@ -238,7 +281,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
|
|
238
281
|
|
239
282
|
def test_find_in_collection
|
240
283
|
assert_equal Client.find(2).name, companies(:first_firm).clients.find(2).name
|
241
|
-
|
284
|
+
assert_raise(ActiveRecord::RecordNotFound) { companies(:first_firm).clients.find(6) }
|
242
285
|
end
|
243
286
|
|
244
287
|
def test_find_grouped
|
@@ -255,6 +298,11 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
|
|
255
298
|
assert_equal 2, companies(:first_firm).clients_grouped_by_name.length
|
256
299
|
end
|
257
300
|
|
301
|
+
def test_find_scoped_grouped_having
|
302
|
+
assert_equal 1, authors(:david).popular_grouped_posts.length
|
303
|
+
assert_equal 0, authors(:mary).popular_grouped_posts.length
|
304
|
+
end
|
305
|
+
|
258
306
|
def test_adding
|
259
307
|
force_signal37_to_load_all_clients_of_firm
|
260
308
|
natural = Client.new("name" => "Natural Company")
|
@@ -273,36 +321,36 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
|
|
273
321
|
end
|
274
322
|
|
275
323
|
def test_create_with_bang_on_has_many_when_parent_is_new_raises
|
276
|
-
|
324
|
+
assert_raise(ActiveRecord::RecordNotSaved) do
|
277
325
|
firm = Firm.new
|
278
326
|
firm.plain_clients.create! :name=>"Whoever"
|
279
327
|
end
|
280
328
|
end
|
281
329
|
|
282
330
|
def test_regular_create_on_has_many_when_parent_is_new_raises
|
283
|
-
|
331
|
+
assert_raise(ActiveRecord::RecordNotSaved) do
|
284
332
|
firm = Firm.new
|
285
333
|
firm.plain_clients.create :name=>"Whoever"
|
286
334
|
end
|
287
335
|
end
|
288
336
|
|
289
337
|
def test_create_with_bang_on_has_many_raises_when_record_not_saved
|
290
|
-
|
338
|
+
assert_raise(ActiveRecord::RecordInvalid) do
|
291
339
|
firm = Firm.find(:first)
|
292
340
|
firm.plain_clients.create!
|
293
341
|
end
|
294
342
|
end
|
295
343
|
|
296
344
|
def test_create_with_bang_on_habtm_when_parent_is_new_raises
|
297
|
-
|
345
|
+
assert_raise(ActiveRecord::RecordNotSaved) do
|
298
346
|
Developer.new("name" => "Aredridel").projects.create!
|
299
347
|
end
|
300
348
|
end
|
301
349
|
|
302
350
|
def test_adding_a_mismatch_class
|
303
|
-
|
304
|
-
|
305
|
-
|
351
|
+
assert_raise(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << nil }
|
352
|
+
assert_raise(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << 1 }
|
353
|
+
assert_raise(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << Topic.find(1) }
|
306
354
|
end
|
307
355
|
|
308
356
|
def test_adding_a_collection
|
@@ -312,81 +360,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
|
|
312
360
|
assert_equal 3, companies(:first_firm).clients_of_firm(true).size
|
313
361
|
end
|
314
362
|
|
315
|
-
def test_adding_before_save
|
316
|
-
no_of_firms = Firm.count
|
317
|
-
no_of_clients = Client.count
|
318
|
-
|
319
|
-
new_firm = Firm.new("name" => "A New Firm, Inc")
|
320
|
-
c = Client.new("name" => "Apple")
|
321
|
-
|
322
|
-
new_firm.clients_of_firm.push Client.new("name" => "Natural Company")
|
323
|
-
assert_equal 1, new_firm.clients_of_firm.size
|
324
|
-
new_firm.clients_of_firm << c
|
325
|
-
assert_equal 2, new_firm.clients_of_firm.size
|
326
|
-
|
327
|
-
assert_equal no_of_firms, Firm.count # Firm was not saved to database.
|
328
|
-
assert_equal no_of_clients, Client.count # Clients were not saved to database.
|
329
|
-
assert new_firm.save
|
330
|
-
assert !new_firm.new_record?
|
331
|
-
assert !c.new_record?
|
332
|
-
assert_equal new_firm, c.firm
|
333
|
-
assert_equal no_of_firms+1, Firm.count # Firm was saved to database.
|
334
|
-
assert_equal no_of_clients+2, Client.count # Clients were saved to database.
|
335
|
-
|
336
|
-
assert_equal 2, new_firm.clients_of_firm.size
|
337
|
-
assert_equal 2, new_firm.clients_of_firm(true).size
|
338
|
-
end
|
339
|
-
|
340
|
-
def test_invalid_adding
|
341
|
-
firm = Firm.find(1)
|
342
|
-
assert !(firm.clients_of_firm << c = Client.new)
|
343
|
-
assert c.new_record?
|
344
|
-
assert !firm.valid?
|
345
|
-
assert !firm.save
|
346
|
-
assert c.new_record?
|
347
|
-
end
|
348
|
-
|
349
|
-
def test_invalid_adding_before_save
|
350
|
-
no_of_firms = Firm.count
|
351
|
-
no_of_clients = Client.count
|
352
|
-
new_firm = Firm.new("name" => "A New Firm, Inc")
|
353
|
-
new_firm.clients_of_firm.concat([c = Client.new, Client.new("name" => "Apple")])
|
354
|
-
assert c.new_record?
|
355
|
-
assert !c.valid?
|
356
|
-
assert !new_firm.valid?
|
357
|
-
assert !new_firm.save
|
358
|
-
assert c.new_record?
|
359
|
-
assert new_firm.new_record?
|
360
|
-
end
|
361
|
-
|
362
|
-
def test_invalid_adding_with_validate_false
|
363
|
-
firm = Firm.find(:first)
|
364
|
-
client = Client.new
|
365
|
-
firm.unvalidated_clients_of_firm << client
|
366
|
-
|
367
|
-
assert firm.valid?
|
368
|
-
assert !client.valid?
|
369
|
-
assert firm.save
|
370
|
-
assert client.new_record?
|
371
|
-
end
|
372
|
-
|
373
|
-
def test_valid_adding_with_validate_false
|
374
|
-
no_of_clients = Client.count
|
375
|
-
|
376
|
-
firm = Firm.find(:first)
|
377
|
-
client = Client.new("name" => "Apple")
|
378
|
-
|
379
|
-
assert firm.valid?
|
380
|
-
assert client.valid?
|
381
|
-
assert client.new_record?
|
382
|
-
|
383
|
-
firm.unvalidated_clients_of_firm << client
|
384
|
-
|
385
|
-
assert firm.save
|
386
|
-
assert !client.new_record?
|
387
|
-
assert_equal no_of_clients+1, Client.count
|
388
|
-
end
|
389
|
-
|
390
363
|
def test_build
|
391
364
|
company = companies(:first_firm)
|
392
365
|
new_client = assert_no_queries { company.clients_of_firm.build("name" => "Another Client") }
|
@@ -395,10 +368,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
|
|
395
368
|
assert_equal "Another Client", new_client.name
|
396
369
|
assert new_client.new_record?
|
397
370
|
assert_equal new_client, company.clients_of_firm.last
|
398
|
-
company.name += '-changed'
|
399
|
-
assert_queries(2) { assert company.save }
|
400
|
-
assert !new_client.new_record?
|
401
|
-
assert_equal 2, company.clients_of_firm(true).size
|
402
371
|
end
|
403
372
|
|
404
373
|
def test_collection_size_after_building
|
@@ -423,11 +392,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
|
|
423
392
|
def test_build_many
|
424
393
|
company = companies(:first_firm)
|
425
394
|
new_clients = assert_no_queries { company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) }
|
426
|
-
|
427
395
|
assert_equal 2, new_clients.size
|
428
|
-
company.name += '-changed'
|
429
|
-
assert_queries(3) { assert company.save }
|
430
|
-
assert_equal 3, company.clients_of_firm(true).size
|
431
396
|
end
|
432
397
|
|
433
398
|
def test_build_followed_by_save_does_not_load_target
|
@@ -458,10 +423,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
|
|
458
423
|
assert_equal "Another Client", new_client.name
|
459
424
|
assert new_client.new_record?
|
460
425
|
assert_equal new_client, company.clients_of_firm.last
|
461
|
-
company.name += '-changed'
|
462
|
-
assert_queries(2) { assert company.save }
|
463
|
-
assert !new_client.new_record?
|
464
|
-
assert_equal 2, company.clients_of_firm(true).size
|
465
426
|
end
|
466
427
|
|
467
428
|
def test_build_many_via_block
|
@@ -475,10 +436,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
|
|
475
436
|
assert_equal 2, new_clients.size
|
476
437
|
assert_equal "changed", new_clients.first.name
|
477
438
|
assert_equal "changed", new_clients.last.name
|
478
|
-
|
479
|
-
company.name += '-changed'
|
480
|
-
assert_queries(3) { assert company.save }
|
481
|
-
assert_equal 3, company.clients_of_firm(true).size
|
482
439
|
end
|
483
440
|
|
484
441
|
def test_create_without_loading_association
|
@@ -496,16 +453,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
|
|
496
453
|
assert_equal 2, first_firm.clients_of_firm.size
|
497
454
|
end
|
498
455
|
|
499
|
-
def test_invalid_build
|
500
|
-
new_client = companies(:first_firm).clients_of_firm.build
|
501
|
-
assert new_client.new_record?
|
502
|
-
assert !new_client.valid?
|
503
|
-
assert_equal new_client, companies(:first_firm).clients_of_firm.last
|
504
|
-
assert !companies(:first_firm).save
|
505
|
-
assert new_client.new_record?
|
506
|
-
assert_equal 1, companies(:first_firm).clients_of_firm(true).size
|
507
|
-
end
|
508
|
-
|
509
456
|
def test_create
|
510
457
|
force_signal37_to_load_all_clients_of_firm
|
511
458
|
new_client = companies(:first_firm).clients_of_firm.create("name" => "Another Client")
|
@@ -660,6 +607,19 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
|
|
660
607
|
assert_equal 1, Client.find_all_by_client_of(firm.id).size
|
661
608
|
end
|
662
609
|
|
610
|
+
def test_dependent_association_respects_optional_hash_conditions_on_delete
|
611
|
+
firm = companies(:odegy)
|
612
|
+
Client.create(:client_of => firm.id, :name => "BigShot Inc.")
|
613
|
+
Client.create(:client_of => firm.id, :name => "SmallTime Inc.")
|
614
|
+
# only one of two clients is included in the association due to the :conditions key
|
615
|
+
assert_equal 2, Client.find_all_by_client_of(firm.id).size
|
616
|
+
assert_equal 1, firm.dependent_sanitized_conditional_clients_of_firm.size
|
617
|
+
firm.destroy
|
618
|
+
# only the correctly associated client should have been deleted
|
619
|
+
assert_equal 1, Client.find_all_by_client_of(firm.id).size
|
620
|
+
end
|
621
|
+
|
622
|
+
|
663
623
|
def test_creation_respects_hash_condition
|
664
624
|
ms_client = companies(:first_firm).clients_like_ms_with_hash_conditions.build
|
665
625
|
|
@@ -680,11 +640,12 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
|
|
680
640
|
authors(:david).destroy
|
681
641
|
end
|
682
642
|
|
683
|
-
assert_equal
|
643
|
+
assert_equal nil, AuthorAddress.find_by_id(authors(:david).author_address_id)
|
644
|
+
assert_equal nil, AuthorAddress.find_by_id(authors(:david).author_address_extra_id)
|
684
645
|
end
|
685
646
|
|
686
647
|
def test_invalid_belongs_to_dependent_option_raises_exception
|
687
|
-
|
648
|
+
assert_raise ArgumentError do
|
688
649
|
Author.belongs_to :special_author_address, :dependent => :nullify
|
689
650
|
end
|
690
651
|
end
|
@@ -710,13 +671,37 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
|
|
710
671
|
def test_deleting_type_mismatch
|
711
672
|
david = Developer.find(1)
|
712
673
|
david.projects.reload
|
713
|
-
|
674
|
+
assert_raise(ActiveRecord::AssociationTypeMismatch) { david.projects.delete(1) }
|
714
675
|
end
|
715
676
|
|
716
677
|
def test_deleting_self_type_mismatch
|
717
678
|
david = Developer.find(1)
|
718
679
|
david.projects.reload
|
719
|
-
|
680
|
+
assert_raise(ActiveRecord::AssociationTypeMismatch) { david.projects.delete(Project.find(1).developers) }
|
681
|
+
end
|
682
|
+
|
683
|
+
def test_destroying
|
684
|
+
force_signal37_to_load_all_clients_of_firm
|
685
|
+
|
686
|
+
assert_difference "Client.count", -1 do
|
687
|
+
companies(:first_firm).clients_of_firm.destroy(companies(:first_firm).clients_of_firm.first)
|
688
|
+
end
|
689
|
+
|
690
|
+
assert_equal 0, companies(:first_firm).reload.clients_of_firm.size
|
691
|
+
assert_equal 0, companies(:first_firm).clients_of_firm(true).size
|
692
|
+
end
|
693
|
+
|
694
|
+
def test_destroying_a_collection
|
695
|
+
force_signal37_to_load_all_clients_of_firm
|
696
|
+
companies(:first_firm).clients_of_firm.create("name" => "Another Client")
|
697
|
+
assert_equal 2, companies(:first_firm).clients_of_firm.size
|
698
|
+
|
699
|
+
assert_difference "Client.count", -2 do
|
700
|
+
companies(:first_firm).clients_of_firm.destroy([companies(:first_firm).clients_of_firm[0], companies(:first_firm).clients_of_firm[1]])
|
701
|
+
end
|
702
|
+
|
703
|
+
assert_equal 0, companies(:first_firm).reload.clients_of_firm.size
|
704
|
+
assert_equal 0, companies(:first_firm).clients_of_firm(true).size
|
720
705
|
end
|
721
706
|
|
722
707
|
def test_destroy_all
|
@@ -824,15 +809,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
|
|
824
809
|
assert !firm.clients.include?(:first_client)
|
825
810
|
end
|
826
811
|
|
827
|
-
def test_replace_on_new_object
|
828
|
-
firm = Firm.new("name" => "New Firm")
|
829
|
-
firm.clients = [companies(:second_client), Client.new("name" => "New Client")]
|
830
|
-
assert firm.save
|
831
|
-
firm.reload
|
832
|
-
assert_equal 2, firm.clients.length
|
833
|
-
assert firm.clients.include?(Client.find_by_name("New Client"))
|
834
|
-
end
|
835
|
-
|
836
812
|
def test_get_ids
|
837
813
|
assert_equal [companies(:first_client).id, companies(:second_client).id], companies(:first_firm).client_ids
|
838
814
|
end
|
@@ -860,15 +836,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
|
|
860
836
|
assert company.clients_using_sql.loaded?
|
861
837
|
end
|
862
838
|
|
863
|
-
def test_assign_ids
|
864
|
-
firm = Firm.new("name" => "Apple")
|
865
|
-
firm.client_ids = [companies(:first_client).id, companies(:second_client).id]
|
866
|
-
firm.save
|
867
|
-
firm.reload
|
868
|
-
assert_equal 2, firm.clients.length
|
869
|
-
assert firm.clients.include?(companies(:second_client))
|
870
|
-
end
|
871
|
-
|
872
839
|
def test_assign_ids_ignoring_blanks
|
873
840
|
firm = Firm.create!(:name => 'Apple')
|
874
841
|
firm.client_ids = [companies(:first_client).id, nil, companies(:second_client).id, '']
|
@@ -891,16 +858,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
|
|
891
858
|
].each {|block| assert_raise(ActiveRecord::HasManyThroughCantAssociateThroughHasManyReflection, &block) }
|
892
859
|
end
|
893
860
|
|
894
|
-
|
895
|
-
def test_assign_ids_for_through_a_belongs_to
|
896
|
-
post = Post.new(:title => "Assigning IDs works!", :body => "You heared it here first, folks!")
|
897
|
-
post.person_ids = [people(:david).id, people(:michael).id]
|
898
|
-
post.save
|
899
|
-
post.reload
|
900
|
-
assert_equal 2, post.people.length
|
901
|
-
assert post.people.include?(people(:david))
|
902
|
-
end
|
903
|
-
|
904
861
|
def test_dynamic_find_should_respect_association_order_for_through
|
905
862
|
assert_equal Comment.find(10), authors(:david).comments_desc.find(:first, :conditions => "comments.type = 'SpecialComment'")
|
906
863
|
assert_equal Comment.find(10), authors(:david).comments_desc.find_by_type('SpecialComment')
|
@@ -1078,12 +1035,10 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
|
|
1078
1035
|
ActiveRecord::Base.store_full_sti_class = old
|
1079
1036
|
end
|
1080
1037
|
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
# nothing
|
1086
|
-
end
|
1038
|
+
def test_association_proxy_transaction_method_starts_transaction_in_association_class
|
1039
|
+
Comment.expects(:transaction)
|
1040
|
+
Post.find(:first).comments.transaction do
|
1041
|
+
# nothing
|
1087
1042
|
end
|
1088
1043
|
end
|
1089
1044
|
|
@@ -1097,5 +1052,11 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
|
|
1097
1052
|
assert !client_association.respond_to?(:private_method)
|
1098
1053
|
assert client_association.respond_to?(:private_method, true)
|
1099
1054
|
end
|
1055
|
+
|
1056
|
+
def test_creating_using_primary_key
|
1057
|
+
firm = Firm.find(:first)
|
1058
|
+
client = firm.clients_using_primary_key.create!(:name => 'test')
|
1059
|
+
assert_equal firm.name, client.firm_name
|
1060
|
+
end
|
1100
1061
|
end
|
1101
1062
|
|