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.

Files changed (120) hide show
  1. data/CHANGELOG +438 -396
  2. data/Rakefile +4 -2
  3. data/lib/active_record.rb +46 -43
  4. data/lib/active_record/association_preload.rb +34 -19
  5. data/lib/active_record/associations.rb +193 -251
  6. data/lib/active_record/associations/association_collection.rb +38 -21
  7. data/lib/active_record/associations/association_proxy.rb +11 -4
  8. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +2 -2
  9. data/lib/active_record/associations/has_many_association.rb +2 -2
  10. data/lib/active_record/associations/has_many_through_association.rb +8 -8
  11. data/lib/active_record/associations/has_one_association.rb +11 -2
  12. data/lib/active_record/attribute_methods.rb +1 -0
  13. data/lib/active_record/autosave_association.rb +349 -0
  14. data/lib/active_record/base.rb +292 -106
  15. data/lib/active_record/batches.rb +73 -0
  16. data/lib/active_record/calculations.rb +34 -16
  17. data/lib/active_record/callbacks.rb +37 -8
  18. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +16 -0
  19. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +3 -0
  20. data/lib/active_record/connection_adapters/abstract/database_statements.rb +103 -15
  21. data/lib/active_record/connection_adapters/abstract/query_cache.rb +6 -6
  22. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +28 -25
  23. data/lib/active_record/connection_adapters/abstract_adapter.rb +29 -5
  24. data/lib/active_record/connection_adapters/mysql_adapter.rb +50 -21
  25. data/lib/active_record/connection_adapters/postgresql_adapter.rb +26 -41
  26. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -1
  27. data/lib/active_record/connection_adapters/sqlite_adapter.rb +41 -21
  28. data/lib/active_record/dirty.rb +1 -1
  29. data/lib/active_record/dynamic_scope_match.rb +25 -0
  30. data/lib/active_record/fixtures.rb +193 -198
  31. data/lib/active_record/locale/en.yml +1 -1
  32. data/lib/active_record/locking/optimistic.rb +33 -0
  33. data/lib/active_record/migration.rb +8 -2
  34. data/lib/active_record/named_scope.rb +13 -6
  35. data/lib/active_record/nested_attributes.rb +329 -0
  36. data/lib/active_record/query_cache.rb +25 -13
  37. data/lib/active_record/reflection.rb +6 -1
  38. data/lib/active_record/schema_dumper.rb +2 -0
  39. data/lib/active_record/serialization.rb +3 -1
  40. data/lib/active_record/serializers/json_serializer.rb +19 -0
  41. data/lib/active_record/serializers/xml_serializer.rb +28 -13
  42. data/lib/active_record/session_store.rb +318 -0
  43. data/lib/active_record/test_case.rb +15 -9
  44. data/lib/active_record/timestamp.rb +2 -2
  45. data/lib/active_record/transactions.rb +58 -8
  46. data/lib/active_record/validations.rb +29 -24
  47. data/lib/active_record/version.rb +2 -2
  48. data/test/cases/ar_schema_test.rb +0 -1
  49. data/test/cases/associations/belongs_to_associations_test.rb +35 -131
  50. data/test/cases/associations/cascaded_eager_loading_test.rb +8 -0
  51. data/test/cases/associations/eager_load_nested_include_test.rb +29 -0
  52. data/test/cases/associations/eager_test.rb +137 -7
  53. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +45 -7
  54. data/test/cases/associations/has_many_associations_test.rb +110 -149
  55. data/test/cases/associations/has_many_through_associations_test.rb +39 -7
  56. data/test/cases/associations/has_one_associations_test.rb +39 -92
  57. data/test/cases/associations/has_one_through_associations_test.rb +34 -3
  58. data/test/cases/associations/inner_join_association_test.rb +0 -5
  59. data/test/cases/associations/join_model_test.rb +5 -7
  60. data/test/cases/attribute_methods_test.rb +13 -1
  61. data/test/cases/autosave_association_test.rb +901 -0
  62. data/test/cases/base_test.rb +41 -21
  63. data/test/cases/batches_test.rb +61 -0
  64. data/test/cases/calculations_test.rb +37 -17
  65. data/test/cases/callbacks_test.rb +43 -5
  66. data/test/cases/connection_pool_test.rb +25 -0
  67. data/test/cases/copy_table_test_sqlite.rb +11 -0
  68. data/test/cases/datatype_test_postgresql.rb +1 -0
  69. data/test/cases/defaults_test.rb +37 -26
  70. data/test/cases/dirty_test.rb +26 -2
  71. data/test/cases/finder_test.rb +79 -44
  72. data/test/cases/fixtures_test.rb +15 -19
  73. data/test/cases/helper.rb +26 -19
  74. data/test/cases/inheritance_test.rb +2 -2
  75. data/test/cases/json_serialization_test.rb +1 -1
  76. data/test/cases/locking_test.rb +23 -5
  77. data/test/cases/method_scoping_test.rb +126 -3
  78. data/test/cases/migration_test.rb +253 -237
  79. data/test/cases/named_scope_test.rb +73 -3
  80. data/test/cases/nested_attributes_test.rb +509 -0
  81. data/test/cases/query_cache_test.rb +0 -4
  82. data/test/cases/reflection_test.rb +13 -3
  83. data/test/cases/reload_models_test.rb +3 -1
  84. data/test/cases/repair_helper.rb +50 -0
  85. data/test/cases/schema_dumper_test.rb +0 -1
  86. data/test/cases/transactions_test.rb +177 -12
  87. data/test/cases/validations_i18n_test.rb +288 -294
  88. data/test/cases/validations_test.rb +230 -180
  89. data/test/cases/xml_serialization_test.rb +19 -1
  90. data/test/fixtures/fixture_database.sqlite3 +0 -0
  91. data/test/fixtures/fixture_database_2.sqlite3 +0 -0
  92. data/test/fixtures/member_types.yml +6 -0
  93. data/test/fixtures/members.yml +3 -1
  94. data/test/fixtures/people.yml +10 -1
  95. data/test/fixtures/toys.yml +4 -0
  96. data/test/models/author.rb +1 -2
  97. data/test/models/bird.rb +3 -0
  98. data/test/models/category.rb +1 -0
  99. data/test/models/company.rb +3 -0
  100. data/test/models/developer.rb +12 -0
  101. data/test/models/event.rb +3 -0
  102. data/test/models/member.rb +1 -0
  103. data/test/models/member_detail.rb +1 -0
  104. data/test/models/member_type.rb +3 -0
  105. data/test/models/owner.rb +2 -1
  106. data/test/models/parrot.rb +2 -0
  107. data/test/models/person.rb +6 -0
  108. data/test/models/pet.rb +2 -1
  109. data/test/models/pirate.rb +55 -1
  110. data/test/models/post.rb +6 -0
  111. data/test/models/project.rb +1 -0
  112. data/test/models/reply.rb +6 -0
  113. data/test/models/ship.rb +8 -1
  114. data/test/models/ship_part.rb +5 -0
  115. data/test/models/topic.rb +13 -1
  116. data/test/models/toy.rb +4 -0
  117. data/test/schema/schema.rb +35 -2
  118. metadata +70 -9
  119. data/test/fixtures/fixture_database.sqlite +0 -0
  120. 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(2) { 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 address
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 test_eager_with_has_many_and_limit_ond_high_offset
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 test_count_eager_with_has_many_and_limit_ond_high_offset
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
- assert_raises(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
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
- assert_raises(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
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
- assert_raises(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
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
- assert_raises(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys, :elephants") {
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
- assert_raises(ActiveRecord::ReadOnlyRecord) { david.save! }
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
- uses_mocha 'mocking Post.transaction' do
766
- def test_association_proxy_transaction_method_starts_transaction_in_association_class
767
- Post.expects(:transaction)
768
- Category.find(:first).posts.transaction do
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
- assert_raises(ActiveRecord::RecordNotFound) { firm.clients.find }
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
- assert_raises(ActiveRecord::RecordNotFound) { firm.clients.find(2, 99) }
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
- assert_raises(ActiveRecord::RecordNotFound) { companies(:first_firm).clients.find(6) }
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
- assert_raises(ActiveRecord::RecordNotSaved) do
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
- assert_raises(ActiveRecord::RecordNotSaved) do
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
- assert_raises(ActiveRecord::RecordInvalid) do
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
- assert_raises(ActiveRecord::RecordNotSaved) do
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
- assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << nil }
304
- assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << 1 }
305
- assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << Topic.find(1) }
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 [author_address.id], AuthorAddress.destroyed_author_address_ids[authors(:david).id]
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
- assert_raises ArgumentError do
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
- assert_raises(ActiveRecord::AssociationTypeMismatch) { david.projects.delete(1) }
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
- assert_raises(ActiveRecord::AssociationTypeMismatch) { david.projects.delete(Project.find(1).developers) }
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
- uses_mocha 'mocking Comment.transaction' do
1082
- def test_association_proxy_transaction_method_starts_transaction_in_association_class
1083
- Comment.expects(:transaction)
1084
- Post.find(:first).comments.transaction do
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