Skip to content

Commit

Permalink
Make has_one with :conditions hash scope build or creation of the ass…
Browse files Browse the repository at this point in the history
…ociated object with those conditions

Signed-off-by: Michael Koziarski <michael@koziarski.com>
[#3088 state:committed]
  • Loading branch information
Luciano G Panaro authored and NZKoz committed Sep 28, 2009
1 parent 8371d6f commit 14a6794
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 3 deletions.
4 changes: 3 additions & 1 deletion activerecord/lib/active_record/associations.rb
Expand Up @@ -875,7 +875,9 @@ def has_many(association_id, options = {}, &extension)
# 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 <tt>rank = 5</tt>.
# SQL fragment, such as <tt>rank = 5</tt>. Record creation from the association is scoped if a hash
# is used. <tt>has_one :account, :conditions => {:enabled => true}</tt> will create an enabled account with <tt>@company.create_account</tt>
# or <tt>@company.build_account</tt>.
# [:order]
# Specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment,
# such as <tt>last_name, first_name DESC</tt>.
Expand Down
Expand Up @@ -8,18 +8,21 @@ def initialize(owner, reflection)

def create(attrs = {}, replace_existing = true)
new_record(replace_existing) do |reflection|
attrs = merge_with_conditions(attrs)
reflection.create_association(attrs)
end
end

def create!(attrs = {}, replace_existing = true)
new_record(replace_existing) do |reflection|
attrs = merge_with_conditions(attrs)
reflection.create_association!(attrs)
end
end

def build(attrs = {}, replace_existing = true)
new_record(replace_existing) do |reflection|
attrs = merge_with_conditions(attrs)
reflection.build_association(attrs)
end
end
Expand Down Expand Up @@ -119,6 +122,12 @@ def new_record(replace_existing)

record
end

def merge_with_conditions(attrs={})
attrs ||= {}
attrs.update(@reflection.options[:conditions]) if @reflection.options[:conditions].is_a?(Hash)
attrs
end
end
end
end
18 changes: 18 additions & 0 deletions activerecord/test/cases/associations/has_one_associations_test.rb
Expand Up @@ -315,4 +315,22 @@ def test_save_of_record_with_loaded_has_one
Firm.find(@firm.id, :include => :account).save!
end
end

def test_build_respects_hash_condition
account = companies(:first_firm).build_account_limit_500_with_hash_conditions
assert account.save
assert_equal 500, account.credit_limit
end

def test_create_respects_hash_condition
account = companies(:first_firm).create_account_limit_500_with_hash_conditions
assert !account.new_record?
assert_equal 500, account.credit_limit
end

def test_create!_respects_hash_condition
account = companies(:first_firm).create_account_limit_500_with_hash_conditions!
assert !account.new_record?
assert_equal 500, account.credit_limit
end
end
4 changes: 2 additions & 2 deletions activerecord/test/cases/reflection_test.rb
Expand Up @@ -170,9 +170,9 @@ def test_association_reflection_in_modules

def test_reflection_of_all_associations
# FIXME these assertions bust a lot
assert_equal 34, Firm.reflect_on_all_associations.size
assert_equal 35, Firm.reflect_on_all_associations.size
assert_equal 25, Firm.reflect_on_all_associations(:has_many).size
assert_equal 9, Firm.reflect_on_all_associations(:has_one).size
assert_equal 10, Firm.reflect_on_all_associations(:has_one).size
assert_equal 0, Firm.reflect_on_all_associations(:belongs_to).size
end

Expand Down
2 changes: 2 additions & 0 deletions activerecord/test/models/company.rb
Expand Up @@ -75,6 +75,8 @@ class Firm < Company
has_one :account_using_foreign_and_primary_keys, :foreign_key => "firm_name", :primary_key => "name", :class_name => "Account"
has_one :deletable_account, :foreign_key => "firm_id", :class_name => "Account", :dependent => :delete

has_one :account_limit_500_with_hash_conditions, :foreign_key => "firm_id", :class_name => "Account", :conditions => { :credit_limit => 500 }

has_one :unautosaved_account, :foreign_key => "firm_id", :class_name => 'Account', :autosave => false
has_many :accounts
has_many :unautosaved_accounts, :foreign_key => "firm_id", :class_name => 'Account', :autosave => false
Expand Down

0 comments on commit 14a6794

Please sign in to comment.