Skip to content

Commit

Permalink
Make sure associated has_many/habtm objects get saved even when :vali…
Browse files Browse the repository at this point in the history
…date => false is used. [#486 state:resolved]

Signed-off-by: Pratik Naik <pratiknaik@gmail.com>
  • Loading branch information
DefV authored and lifo committed Jun 27, 2008
1 parent 5ca7d01 commit b2b7611
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 8 deletions.
19 changes: 12 additions & 7 deletions activerecord/lib/active_record/associations.rb
Expand Up @@ -711,7 +711,8 @@ def has_many(association_id, options = {}, &extension)

configure_dependency_for_has_many(reflection)

add_multiple_associated_save_callbacks(reflection.name) unless options[:validate] == false
add_multiple_associated_validation_callbacks(reflection.name) unless options[:validate] == false
add_multiple_associated_save_callbacks(reflection.name)
add_association_callbacks(reflection.name, reflection.options)

if options[:through]
Expand Down Expand Up @@ -801,7 +802,7 @@ def has_one(association_id, options = {})
end
after_save method_name

add_single_associated_save_callbacks(reflection.name) if options[:validate] == true
add_single_associated_validation_callbacks(reflection.name) if options[:validate] == true
association_accessor_methods(reflection, HasOneAssociation)
association_constructor_method(:build, reflection, HasOneAssociation)
association_constructor_method(:create, reflection, HasOneAssociation)
Expand Down Expand Up @@ -940,7 +941,7 @@ def belongs_to(association_id, options = {})
)
end

add_single_associated_save_callbacks(reflection.name) if options[:validate] == true
add_single_associated_validation_callbacks(reflection.name) if options[:validate] == true

configure_dependency_for_belongs_to(reflection)
end
Expand Down Expand Up @@ -1043,7 +1044,8 @@ def belongs_to(association_id, options = {})
def has_and_belongs_to_many(association_id, options = {}, &extension)
reflection = create_has_and_belongs_to_many_reflection(association_id, options, &extension)

add_multiple_associated_save_callbacks(reflection.name) unless options[:validate] == false
add_multiple_associated_validation_callbacks(reflection.name) unless options[:validate] == false
add_multiple_associated_save_callbacks(reflection.name)
collection_accessor_methods(reflection, HasAndBelongsToManyAssociation)

# Don't use a before_destroy callback since users' before_destroy
Expand Down Expand Up @@ -1163,7 +1165,7 @@ def collection_accessor_methods(reflection, association_proxy_class, writer = tr
end
end

def add_single_associated_save_callbacks(association_name)
def add_single_associated_validation_callbacks(association_name)
method_name = "validate_associated_records_for_#{association_name}".to_sym
define_method(method_name) do
association = instance_variable_get("@#{association_name}")
Expand All @@ -1175,7 +1177,7 @@ def add_single_associated_save_callbacks(association_name)
validate method_name
end

def add_multiple_associated_save_callbacks(association_name)
def add_multiple_associated_validation_callbacks(association_name)
method_name = "validate_associated_records_for_#{association_name}".to_sym
ivar = "@#{association_name}"

Expand All @@ -1196,6 +1198,10 @@ def add_multiple_associated_save_callbacks(association_name)
end

validate method_name
end

def add_multiple_associated_save_callbacks(association_name)
ivar = "@#{association_name}"

method_name = "before_save_associated_records_for_#{association_name}".to_sym
define_method(method_name) do
Expand All @@ -1217,7 +1223,6 @@ def add_multiple_associated_save_callbacks(association_name)
else
[]
end

records_to_save.each { |record| association.send(:insert_record, record) } unless records_to_save.blank?

# reconstruct the SQL queries now that we know the owner's id
Expand Down
Expand Up @@ -345,14 +345,31 @@ def test_invalid_adding_before_save
def test_invalid_adding_with_validate_false
firm = Firm.find(:first)
client = Client.new
firm.unvalidated_clients_of_firm << Client.new
firm.unvalidated_clients_of_firm << client

assert firm.valid?
assert !client.valid?
assert firm.save
assert client.new_record?
end

def test_valid_adding_with_validate_false
no_of_clients = Client.count

firm = Firm.find(:first)
client = Client.new("name" => "Apple")

assert firm.valid?
assert client.valid?
assert client.new_record?

firm.unvalidated_clients_of_firm << client

assert firm.save
assert !client.new_record?
assert_equal no_of_clients+1, Client.count
end

def test_build
company = companies(:first_firm)
new_client = assert_no_queries { company.clients_of_firm.build("name" => "Another Client") }
Expand Down

0 comments on commit b2b7611

Please sign in to comment.