aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases/associations/has_many_associations_test.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/test/cases/associations/has_many_associations_test.rb')
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb253
1 files changed, 182 insertions, 71 deletions
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index 4b7a2db096..04714f42e9 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -20,6 +20,49 @@ require 'models/car'
require 'models/bulb'
require 'models/engine'
+class HasManyAssociationsTestForCountWithFinderSql < ActiveRecord::TestCase
+ class Invoice < ActiveRecord::Base
+ ActiveSupport::Deprecation.silence do
+ has_many :custom_line_items, :class_name => 'LineItem', :finder_sql => "SELECT line_items.* from line_items"
+ end
+ end
+ def test_should_fail
+ assert_raise(ArgumentError) do
+ Invoice.create.custom_line_items.count(:conditions => {:amount => 0})
+ end
+ end
+end
+
+class HasManyAssociationsTestForCountWithCountSql < ActiveRecord::TestCase
+ class Invoice < ActiveRecord::Base
+ ActiveSupport::Deprecation.silence do
+ has_many :custom_line_items, :class_name => 'LineItem', :counter_sql => "SELECT COUNT(*) line_items.* from line_items"
+ end
+ end
+ def test_should_fail
+ assert_raise(ArgumentError) do
+ Invoice.create.custom_line_items.count(:conditions => {:amount => 0})
+ end
+ end
+end
+
+class HasManyAssociationsTestForCountDistinctWithFinderSql < ActiveRecord::TestCase
+ class Invoice < ActiveRecord::Base
+ ActiveSupport::Deprecation.silence do
+ has_many :custom_line_items, :class_name => 'LineItem', :finder_sql => "SELECT DISTINCT line_items.amount from line_items"
+ end
+ end
+
+ def test_should_count_distinct_results
+ invoice = Invoice.new
+ invoice.custom_line_items << LineItem.new(:amount => 0)
+ invoice.custom_line_items << LineItem.new(:amount => 0)
+ invoice.save!
+
+ assert_equal 1, invoice.custom_line_items.count
+ end
+end
+
class HasManyAssociationsTestForReorderWithJoinDependency < ActiveRecord::TestCase
fixtures :authors, :posts, :comments
@@ -141,7 +184,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
# would be convenient), because this would cause that scope to be applied to any callbacks etc.
def test_build_and_create_should_not_happen_within_scope
car = cars(:honda)
- scoped_count = car.foo_bulbs.scoped.where_values.count
+ scoped_count = car.foo_bulbs.where_values.count
bulb = car.foo_bulbs.build
assert_not_equal scoped_count, bulb.scope_after_initialize.where_values.count
@@ -190,19 +233,19 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
# sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first
def test_counting_with_counter_sql
- assert_equal 2, Firm.scoped(:order => "id").first.clients.count
+ assert_equal 2, Firm.all.merge!(:order => "id").first.clients.count
end
def test_counting
- assert_equal 2, Firm.scoped(:order => "id").first.plain_clients.count
+ assert_equal 2, Firm.all.merge!(:order => "id").first.plain_clients.count
end
def test_counting_with_single_hash
- assert_equal 1, Firm.scoped(:order => "id").first.plain_clients.where(:name => "Microsoft").count
+ assert_equal 1, Firm.all.merge!(:order => "id").first.plain_clients.where(:name => "Microsoft").count
end
def test_counting_with_column_name_and_hash
- assert_equal 2, Firm.scoped(:order => "id").first.plain_clients.count(:name)
+ assert_equal 2, Firm.all.merge!(:order => "id").first.plain_clients.count(:name)
end
def test_counting_with_association_limit
@@ -212,7 +255,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
end
def test_finding
- assert_equal 2, Firm.scoped(:order => "id").first.clients.length
+ assert_equal 2, Firm.all.merge!(:order => "id").first.clients.length
end
def test_finding_array_compatibility
@@ -221,23 +264,23 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
def test_find_with_blank_conditions
[[], {}, nil, ""].each do |blank|
- assert_equal 2, Firm.scoped(:order => "id").first.clients.where(blank).all.size
+ assert_equal 2, Firm.all.merge!(:order => "id").first.clients.where(blank).to_a.size
end
end
def test_find_many_with_merged_options
assert_equal 1, companies(:first_firm).limited_clients.size
- assert_equal 1, companies(:first_firm).limited_clients.all.size
- assert_equal 2, companies(:first_firm).limited_clients.limit(nil).all.size
+ assert_equal 1, companies(:first_firm).limited_clients.to_a.size
+ assert_equal 2, companies(:first_firm).limited_clients.limit(nil).to_a.size
end
- def test_find_should_append_to_association_order
+ def test_find_should_prepend_to_association_order
ordered_clients = companies(:first_firm).clients_sorted_desc.order('companies.id')
- assert_equal ['id DESC', 'companies.id'], ordered_clients.order_values
+ assert_equal ['companies.id', 'id DESC'], ordered_clients.order_values
end
def test_dynamic_find_should_respect_association_order
- assert_equal companies(:second_client), companies(:first_firm).clients_sorted_desc.scoped(:where => "type = 'Client'").first
+ assert_equal companies(:second_client), companies(:first_firm).clients_sorted_desc.where("type = 'Client'").first
assert_equal companies(:second_client), companies(:first_firm).clients_sorted_desc.find_by_type('Client')
end
@@ -247,27 +290,58 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
end
def test_finding_default_orders
- assert_equal "Summit", Firm.scoped(:order => "id").first.clients.first.name
+ assert_equal "Summit", Firm.all.merge!(:order => "id").first.clients.first.name
end
def test_finding_with_different_class_name_and_order
- assert_equal "Microsoft", Firm.scoped(:order => "id").first.clients_sorted_desc.first.name
+ assert_equal "Microsoft", Firm.all.merge!(:order => "id").first.clients_sorted_desc.first.name
end
def test_finding_with_foreign_key
- assert_equal "Microsoft", Firm.scoped(:order => "id").first.clients_of_firm.first.name
+ assert_equal "Microsoft", Firm.all.merge!(:order => "id").first.clients_of_firm.first.name
end
def test_finding_with_condition
- assert_equal "Microsoft", Firm.scoped(:order => "id").first.clients_like_ms.first.name
+ assert_equal "Microsoft", Firm.all.merge!(:order => "id").first.clients_like_ms.first.name
end
def test_finding_with_condition_hash
- assert_equal "Microsoft", Firm.scoped(:order => "id").first.clients_like_ms_with_hash_conditions.first.name
+ assert_equal "Microsoft", Firm.all.merge!(:order => "id").first.clients_like_ms_with_hash_conditions.first.name
end
def test_finding_using_primary_key
- assert_equal "Summit", Firm.scoped(:order => "id").first.clients_using_primary_key.first.name
+ assert_equal "Summit", Firm.all.merge!(:order => "id").first.clients_using_primary_key.first.name
+ end
+
+ def test_finding_using_sql
+ firm = Firm.order("id").first
+ first_client = firm.clients_using_sql.first
+ assert_not_nil first_client
+ assert_equal "Microsoft", first_client.name
+ assert_equal 1, firm.clients_using_sql.size
+ assert_equal 1, Firm.order("id").first.clients_using_sql.size
+ end
+
+ def test_finding_using_sql_take_into_account_only_uniq_ids
+ firm = Firm.order("id").first
+ client = firm.clients_using_sql.first
+ assert_equal client, firm.clients_using_sql.find(client.id, client.id)
+ assert_equal client, firm.clients_using_sql.find(client.id, client.id.to_s)
+ end
+
+ def test_counting_using_sql
+ assert_equal 1, Firm.order("id").first.clients_using_counter_sql.size
+ assert Firm.order("id").first.clients_using_counter_sql.any?
+ assert_equal 0, Firm.order("id").first.clients_using_zero_counter_sql.size
+ assert !Firm.order("id").first.clients_using_zero_counter_sql.any?
+ end
+
+ def test_counting_non_existant_items_using_sql
+ assert_equal 0, Firm.order("id").first.no_clients_using_counter_sql.size
+ end
+
+ def test_counting_using_finder_sql
+ assert_equal 2, Firm.find(4).clients_using_sql.count
end
def test_belongs_to_sanity
@@ -278,7 +352,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
end
def test_find_ids
- firm = Firm.scoped(:order => "id").first
+ firm = Firm.all.merge!(:order => "id").first
assert_raise(ActiveRecord::RecordNotFound) { firm.clients.find }
@@ -297,10 +371,26 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_raise(ActiveRecord::RecordNotFound) { firm.clients.find(2, 99) }
end
+ def test_find_string_ids_when_using_finder_sql
+ firm = Firm.order("id").first
+
+ client = firm.clients_using_finder_sql.find("2")
+ assert_kind_of Client, client
+
+ client_ary = firm.clients_using_finder_sql.find(["2"])
+ assert_kind_of Array, client_ary
+ assert_equal client, client_ary.first
+
+ client_ary = firm.clients_using_finder_sql.find("2", "3")
+ assert_kind_of Array, client_ary
+ assert_equal 2, client_ary.size
+ assert client_ary.include?(client)
+ end
+
def test_find_all
- firm = Firm.scoped(:order => "id").first
- assert_equal 2, firm.clients.scoped(:where => "#{QUOTED_TYPE} = 'Client'").all.length
- assert_equal 1, firm.clients.scoped(:where => "name = 'Summit'").all.length
+ firm = Firm.all.merge!(:order => "id").first
+ assert_equal 2, firm.clients.where("#{QUOTED_TYPE} = 'Client'").to_a.length
+ assert_equal 1, firm.clients.where("name = 'Summit'").to_a.length
end
def test_find_each
@@ -344,29 +434,29 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
def test_find_all_sanitized
# sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first
- firm = Firm.scoped(:order => "id").first
- summit = firm.clients.scoped(:where => "name = 'Summit'").all
- assert_equal summit, firm.clients.scoped(:where => ["name = ?", "Summit"]).all
- assert_equal summit, firm.clients.scoped(:where => ["name = :name", { :name => "Summit" }]).all
+ firm = Firm.all.merge!(:order => "id").first
+ summit = firm.clients.where("name = 'Summit'").to_a
+ assert_equal summit, firm.clients.where("name = ?", "Summit").to_a
+ assert_equal summit, firm.clients.where("name = :name", { :name => "Summit" }).to_a
end
def test_find_first
- firm = Firm.scoped(:order => "id").first
+ firm = Firm.all.merge!(:order => "id").first
client2 = Client.find(2)
- assert_equal firm.clients.first, firm.clients.scoped(:order => "id").first
- assert_equal client2, firm.clients.scoped(:where => "#{QUOTED_TYPE} = 'Client'", :order => "id").first
+ assert_equal firm.clients.first, firm.clients.order("id").first
+ assert_equal client2, firm.clients.where("#{QUOTED_TYPE} = 'Client'").order("id").first
end
def test_find_first_sanitized
- firm = Firm.scoped(:order => "id").first
+ firm = Firm.all.merge!(:order => "id").first
client2 = Client.find(2)
- assert_equal client2, firm.clients.scoped(:where => ["#{QUOTED_TYPE} = ?", 'Client'], :order => "id").first
- assert_equal client2, firm.clients.scoped(:where => ["#{QUOTED_TYPE} = :type", { :type => 'Client' }], :order => "id").first
+ assert_equal client2, firm.clients.merge!(:where => ["#{QUOTED_TYPE} = ?", 'Client'], :order => "id").first
+ assert_equal client2, firm.clients.merge!(:where => ["#{QUOTED_TYPE} = :type", { :type => 'Client' }], :order => "id").first
end
def test_find_all_with_include_and_conditions
assert_nothing_raised do
- Developer.scoped(:joins => :audit_logs, :where => {'audit_logs.message' => nil, :name => 'Smith'}).all
+ Developer.all.merge!(:joins => :audit_logs, :where => {'audit_logs.message' => nil, :name => 'Smith'}).to_a
end
end
@@ -376,8 +466,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
end
def test_find_grouped
- all_clients_of_firm1 = Client.scoped(:where => "firm_id = 1").all
- grouped_clients_of_firm1 = Client.scoped(:where => "firm_id = 1", :group => "firm_id", :select => 'firm_id, count(id) as clients_count').all
+ all_clients_of_firm1 = Client.all.merge!(:where => "firm_id = 1").to_a
+ grouped_clients_of_firm1 = Client.all.merge!(:where => "firm_id = 1", :group => "firm_id", :select => 'firm_id, count(id) as clients_count').to_a
assert_equal 2, all_clients_of_firm1.size
assert_equal 1, grouped_clients_of_firm1.size
end
@@ -435,7 +525,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
def test_create_with_bang_on_has_many_raises_when_record_not_saved
assert_raise(ActiveRecord::RecordInvalid) do
- firm = Firm.scoped(:order => "id").first
+ firm = Firm.all.merge!(:order => "id").first
firm.plain_clients.create!
end
end
@@ -634,7 +724,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
def test_deleting_updates_counter_cache_with_dependent_delete_all
post = posts(:welcome)
- post.update_column(:taggings_with_delete_all_count, post.taggings_count)
+ post.update_columns(taggings_with_delete_all_count: post.taggings_count)
assert_difference "post.reload.taggings_with_delete_all_count", -1 do
post.taggings_with_delete_all.delete(post.taggings_with_delete_all.first)
@@ -643,7 +733,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
def test_deleting_updates_counter_cache_with_dependent_destroy
post = posts(:welcome)
- post.update_column(:taggings_with_destroy_count, post.taggings_count)
+ post.update_columns(taggings_with_destroy_count: post.taggings_count)
assert_difference "post.reload.taggings_with_destroy_count", -1 do
post.taggings_with_destroy.delete(post.taggings_with_destroy.first)
@@ -813,7 +903,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
firm = Firm.first
# break the vanilla firm_id foreign key
assert_equal 2, firm.clients.count
- firm.clients.first.update_column(:firm_id, nil)
+ firm.clients.first.update_columns(firm_id: nil)
assert_equal 1, firm.clients(true).count
assert_equal 1, firm.clients_using_primary_key_with_delete_all.count
old_record = firm.clients_using_primary_key_with_delete_all.first
@@ -939,7 +1029,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
firm = companies(:first_firm)
assert_equal 2, firm.clients.size
firm.destroy
- assert Client.scoped(:where => "firm_id=#{firm.id}").all.empty?
+ assert Client.all.merge!(:where => "firm_id=#{firm.id}").to_a.empty?
end
def test_dependence_for_associations_with_hash_condition
@@ -949,7 +1039,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
def test_destroy_dependent_when_deleted_from_association
# sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first
- firm = Firm.scoped(:order => "id").first
+ firm = Firm.all.merge!(:order => "id").first
assert_equal 2, firm.clients.size
client = firm.clients.first
@@ -977,7 +1067,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
firm.destroy rescue "do nothing"
- assert_equal 2, Client.scoped(:where => "firm_id=#{firm.id}").all.size
+ assert_equal 2, Client.all.merge!(:where => "firm_id=#{firm.id}").to_a.size
end
def test_dependence_on_account
@@ -1001,9 +1091,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
end
def test_restrict
- option_before = ActiveRecord::Base.dependent_restrict_raises
- ActiveRecord::Base.dependent_restrict_raises = true
-
firm = RestrictedFirm.create!(:name => 'restrict')
firm.companies.create(:name => 'child')
@@ -1011,15 +1098,25 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_raise(ActiveRecord::DeleteRestrictionError) { firm.destroy }
assert RestrictedFirm.exists?(:name => 'restrict')
assert firm.companies.exists?(:name => 'child')
- ensure
- ActiveRecord::Base.dependent_restrict_raises = option_before
end
- def test_restrict_when_dependent_restrict_raises_config_set_to_false
- option_before = ActiveRecord::Base.dependent_restrict_raises
- ActiveRecord::Base.dependent_restrict_raises = false
+ def test_restrict_is_deprecated
+ klass = Class.new(ActiveRecord::Base)
+ assert_deprecated { klass.has_many :posts, dependent: :restrict }
+ end
- firm = RestrictedFirm.create!(:name => 'restrict')
+ def test_restrict_with_exception
+ firm = RestrictedWithExceptionFirm.create!(:name => 'restrict')
+ firm.companies.create(:name => 'child')
+
+ assert !firm.companies.empty?
+ assert_raise(ActiveRecord::DeleteRestrictionError) { firm.destroy }
+ assert RestrictedWithExceptionFirm.exists?(:name => 'restrict')
+ assert firm.companies.exists?(:name => 'child')
+ end
+
+ def test_restrict_with_error
+ firm = RestrictedWithErrorFirm.create!(:name => 'restrict')
firm.companies.create(:name => 'child')
assert !firm.companies.empty?
@@ -1029,10 +1126,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert !firm.errors.empty?
assert_equal "Cannot delete record because dependent companies exist", firm.errors[:base].first
- assert RestrictedFirm.exists?(:name => 'restrict')
+ assert RestrictedWithErrorFirm.exists?(:name => 'restrict')
assert firm.companies.exists?(:name => 'child')
- ensure
- ActiveRecord::Base.dependent_restrict_raises = option_before
end
def test_included_in_collection
@@ -1044,7 +1139,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
end
def test_replace_with_less
- firm = Firm.scoped(:order => "id").first
+ firm = Firm.all.merge!(:order => "id").first
firm.clients = [companies(:first_client)]
assert firm.save, "Could not save firm"
firm.reload
@@ -1058,7 +1153,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
end
def test_replace_with_new
- firm = Firm.scoped(:order => "id").first
+ firm = Firm.all.merge!(:order => "id").first
firm.clients = [companies(:second_client), Client.new("name" => "New Client")]
firm.save
firm.reload
@@ -1124,6 +1219,13 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_equal [readers(:michael_welcome).id], posts(:welcome).readers_with_person_ids
end
+ def test_get_ids_for_unloaded_finder_sql_associations_loads_them
+ company = companies(:first_firm)
+ assert !company.clients_using_sql.loaded?
+ assert_equal [companies(:second_client).id], company.clients_using_sql_ids
+ assert company.clients_using_sql.loaded?
+ end
+
def test_get_ids_for_ordered_association
assert_equal [companies(:second_client).id, companies(:first_client).id], companies(:first_firm).clients_ordered_by_name_ids
end
@@ -1151,7 +1253,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
end
def test_dynamic_find_should_respect_association_order_for_through
- assert_equal Comment.find(10), authors(:david).comments_desc.scoped(:where => "comments.type = 'SpecialComment'").first
+ assert_equal Comment.find(10), authors(:david).comments_desc.where("comments.type = 'SpecialComment'").first
assert_equal Comment.find(10), authors(:david).comments_desc.find_by_type('SpecialComment')
end
@@ -1184,6 +1286,17 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert ! firm.clients.loaded?
end
+ def test_include_loads_collection_if_target_uses_finder_sql
+ firm = companies(:first_firm)
+ client = firm.clients_using_sql.first
+
+ firm.reload
+ assert ! firm.clients_using_sql.loaded?
+ assert firm.clients_using_sql.include?(client)
+ assert firm.clients_using_sql.loaded?
+ end
+
+
def test_include_returns_false_for_non_matching_record_to_verify_scoping
firm = companies(:first_firm)
client = Client.create!(:name => 'Not Associated')
@@ -1329,7 +1442,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
firm = Namespaced::Firm.create({ :name => 'Some Company' })
firm.clients.create({ :name => 'Some Client' })
- stats = Namespaced::Firm.scoped(
+ stats = Namespaced::Firm.all.merge!(
:select => "#{Namespaced::Firm.table_name}.id, COUNT(#{Namespaced::Client.table_name}.id) AS num_clients",
:joins => :clients,
:group => "#{Namespaced::Firm.table_name}.id"
@@ -1358,7 +1471,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
end
def test_creating_using_primary_key
- firm = Firm.scoped(:order => "id").first
+ firm = Firm.all.merge!(:order => "id").first
client = firm.clients_using_primary_key.create!(:name => 'test')
assert_equal firm.name, client.firm_name
end
@@ -1494,18 +1607,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_equal [bulb1, bulb3], result
end
- def test_building_has_many_association_with_restrict_dependency
- option_before = ActiveRecord::Base.dependent_restrict_raises
- ActiveRecord::Base.dependent_restrict_raises = true
-
- klass = Class.new(ActiveRecord::Base)
-
- assert_deprecated { klass.has_many :companies, :dependent => :restrict }
- assert_not_deprecated { klass.has_many :companies }
- ensure
- ActiveRecord::Base.dependent_restrict_raises = option_before
- end
-
def test_collection_association_with_private_kernel_method
firm = companies(:first_firm)
assert_equal [accounts(:signals37)], firm.accounts.open
@@ -1536,4 +1637,14 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
post.taggings_with_delete_all.delete_all
end
end
+
+ test ":finder_sql is deprecated" do
+ klass = Class.new(ActiveRecord::Base)
+ assert_deprecated { klass.has_many :foo, :finder_sql => 'lol' }
+ end
+
+ test ":counter_sql is deprecated" do
+ klass = Class.new(ActiveRecord::Base)
+ assert_deprecated { klass.has_many :foo, :counter_sql => 'lol' }
+ end
end