From 985f8cdeea0bf1e532fd77e9b40b6b255bbbcad4 Mon Sep 17 00:00:00 2001 From: misfo Date: Wed, 22 Apr 2009 00:45:48 -0500 Subject: [PATCH 1/2] made belongs_to creation methods respect their conditions hash --- activerecord/lib/active_record/associations.rb | 4 +++- .../associations/belongs_to_association.rb | 1 + .../associations/belongs_to_associations_test.rb | 13 +++++++++++++ activerecord/test/models/company.rb | 1 + 4 files changed, 18 insertions(+), 1 deletions(-) diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 2115878..6d8406d 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -948,7 +948,9 @@ module ActiveRecord # if the real class name is Person, you'll have to specify it with this option. # [:conditions] # Specify the conditions that the associated object must meet in order to be included as a +WHERE+ - # SQL fragment, such as authorized = 1. + # SQL fragment, such as price > 5 AND name LIKE 'B%'. Record creations from the association are scoped if a hash + # is used. belongs_to :mother, :class_name => "Person", :conditions => {:gender => "female"} will create a + # person with a gender of "female" with @person.create_mother or @person.build_mother. # [:select] # By default, this is * as in SELECT * FROM, but can be changed if, for example, you want to do a join # but not include the joined columns. Do not forget to include the primary and foreign keys, otherwise it will raise an error. diff --git a/activerecord/lib/active_record/associations/belongs_to_association.rb b/activerecord/lib/active_record/associations/belongs_to_association.rb index f05c6be..d29aed6 100644 --- a/activerecord/lib/active_record/associations/belongs_to_association.rb +++ b/activerecord/lib/active_record/associations/belongs_to_association.rb @@ -27,6 +27,7 @@ module ActiveRecord end @target = (AssociationProxy === record ? record.target : record) + @target.attributes = @reflection.options[:conditions] if @reflection.options[:conditions].is_a?(Hash) @owner[@reflection.primary_key_name] = record.id unless record.new_record? @updated = true end diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb index 13a78a1..982713e 100644 --- a/activerecord/test/cases/associations/belongs_to_associations_test.rb +++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb @@ -76,6 +76,19 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase assert_equal apple.id, citibank.firm_id end + def test_creation_respects_hash_conditions + client = Client.find(3) + apple = client.build_firm_with_firm_name("name" => "Apple") + + assert apple.new_record? + assert_equal "Stiff", apple.firm_name + + another_apple = client.create_firm_with_firm_name("name" => "Apple") + + assert !another_apple.new_record? + assert_equal "Stiff", another_apple.firm_name + end + def test_natural_assignment_to_nil client = Client.find(3) client.firm = nil diff --git a/activerecord/test/models/company.rb b/activerecord/test/models/company.rb index eb68153..b19b16e 100644 --- a/activerecord/test/models/company.rb +++ b/activerecord/test/models/company.rb @@ -84,6 +84,7 @@ class Client < Company belongs_to :firm_with_select, :class_name => "Firm", :foreign_key => "firm_id", :select => "id" belongs_to :firm_with_other_name, :class_name => "Firm", :foreign_key => "client_of" belongs_to :firm_with_condition, :class_name => "Firm", :foreign_key => "client_of", :conditions => ["1 = ?", 1] + belongs_to :firm_with_firm_name, :class_name => "Firm", :foreign_key => "client_of", :conditions => { :firm_name => "Stiff" } belongs_to :readonly_firm, :class_name => "Firm", :foreign_key => "firm_id", :readonly => true # Record destruction so we can test whether firm.clients.clear has -- 1.6.2.1 From 36bc5faf0fc803e38ceba420fc8e9d953707411f Mon Sep 17 00:00:00 2001 From: misfo Date: Wed, 22 Apr 2009 00:48:31 -0500 Subject: [PATCH 2/2] made has_one creation methods respect their conditions hash --- activerecord/lib/active_record/associations.rb | 4 +++- .../associations/has_one_association.rb | 2 +- .../associations/has_one_associations_test.rb | 14 ++++++++++++++ activerecord/test/cases/reflection_test.rb | 4 ++-- activerecord/test/models/company.rb | 2 ++ 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 6d8406d..15754db 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -846,7 +846,9 @@ module ActiveRecord # if the real class name is Person, you'll have to specify it with this option. # [:conditions] # Specify the conditions that the associated object must meet in order to be included as a +WHERE+ - # SQL fragment, such as rank = 5. + # SQL fragment, such as price > 5 AND name LIKE 'B%'. Record creations from the association are scoped if a hash + # is used. has_one :blue_shirt, :class_name => "Shirt", :conditions => {:color => "blue"} will create a shirt + # with a color of "blue" with @person.create_blue_shirt or @person.build_blue_shirt. # [:order] # Specify the order in which the associated objects are returned as an ORDER BY SQL fragment, # such as last_name, first_name DESC. diff --git a/activerecord/lib/active_record/associations/has_one_association.rb b/activerecord/lib/active_record/associations/has_one_association.rb index b92cbbd..42dd2f7 100644 --- a/activerecord/lib/active_record/associations/has_one_association.rb +++ b/activerecord/lib/active_record/associations/has_one_association.rb @@ -96,7 +96,7 @@ module ActiveRecord end def construct_scope - create_scoping = {} + create_scoping = @reflection.options[:conditions].is_a?(Hash) ? @reflection.options[:conditions] : {} set_belongs_to_association_for(create_scoping) { :create => create_scoping } end diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb index 1ddb3f4..39f0b2c 100644 --- a/activerecord/test/cases/associations/has_one_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_associations_test.rb @@ -229,6 +229,20 @@ class HasOneAssociationsTest < ActiveRecord::TestCase assert_equal account, firm.account end + def test_creation_respects_hash_conditions + firm = Firm.new("name" => "GlobalMegaCorp") + firm.save + account = firm.build_account_with_credit_limit + + assert account.new_record? + assert_equal 42, account.credit_limit + + another_account = firm.create_account_with_credit_limit + + assert !another_account.new_record? + assert_equal 42, another_account.credit_limit + end + def test_create_before_save firm = Firm.new("name" => "GlobalMegaCorp") firm.account = account = Account.create("credit_limit" => 1000) diff --git a/activerecord/test/cases/reflection_test.rb b/activerecord/test/cases/reflection_test.rb index db64bbb..41b1770 100644 --- a/activerecord/test/cases/reflection_test.rb +++ b/activerecord/test/cases/reflection_test.rb @@ -170,9 +170,9 @@ class ReflectionTest < ActiveRecord::TestCase def test_reflection_of_all_associations # FIXME these assertions bust a lot - assert_equal 28, Firm.reflect_on_all_associations.size + assert_equal 29, Firm.reflect_on_all_associations.size assert_equal 21, Firm.reflect_on_all_associations(:has_many).size - assert_equal 7, Firm.reflect_on_all_associations(:has_one).size + assert_equal 8, Firm.reflect_on_all_associations(:has_one).size assert_equal 0, Firm.reflect_on_all_associations(:belongs_to).size end diff --git a/activerecord/test/models/company.rb b/activerecord/test/models/company.rb index b19b16e..3dc3b65 100644 --- a/activerecord/test/models/company.rb +++ b/activerecord/test/models/company.rb @@ -66,6 +66,8 @@ class Firm < Company has_many :clients_grouped_by_name, :class_name => "Client", :group => "name", :select => "name" has_one :account, :foreign_key => "firm_id", :dependent => :destroy, :validate => true + has_one :account_with_credit_limit, :foreign_key => "firm_id", :class_name => "Account", + :conditions => { :credit_limit => 42 } has_one :unvalidated_account, :foreign_key => "firm_id", :class_name => 'Account', :validate => false has_one :account_with_select, :foreign_key => "firm_id", :select => "id, firm_id", :class_name=>'Account' has_one :readonly_account, :foreign_key => "firm_id", :class_name => "Account", :readonly => true -- 1.6.2.1