Skip to content

Commit

Permalink
add discard_if option to has_many_with_association_options
Browse files Browse the repository at this point in the history
git-svn-id: http://svn.jamesgolick.com/attribute_fu/trunk@64 80b79608-713f-0410-8737-d8c0d0c1b50c
  • Loading branch information
james committed Feb 16, 2008
1 parent e396b41 commit c6f0f3c
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 7 deletions.
15 changes: 11 additions & 4 deletions lib/attribute_fu/associations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def self.included(base) #:nodoc:
class << self; alias_method_chain :has_many, :association_option; end

class_inheritable_accessor :managed_association_attributes
write_inheritable_attribute :managed_association_attributes, []
write_inheritable_attribute :managed_association_attributes, {}

after_update :save_managed_associations
end
Expand All @@ -16,7 +16,7 @@ class << self; alias_method_chain :has_many, :association_option; end
def method_missing(method_name, *args) #:nodoc:
if method_name.to_s =~ /.+?\_attributes=/
association_name = method_name.to_s.gsub '_attributes=', ''
association = managed_association_attributes.detect { |element| element == association_name.to_sym } || managed_association_attributes.detect { |element| element == association_name.pluralize.to_sym }
association = managed_association_attributes.keys.detect { |element| element == association_name.to_sym } || managed_association_attributes.keys.detect { |element| element == association_name.pluralize.to_sym }

unless association.nil?
has_many_attributes association, args.first
Expand Down Expand Up @@ -51,10 +51,16 @@ def has_many_attributes(association_id, attributes) #:nodoc:
object = association.detect { |associated| associated.id.to_s == id }
object.attributes = object_attrs unless object.nil?
end

# discard blank attributes if discard_if proc exists
unless (discard = managed_association_attributes[association_id][:discard_if]).nil?
association.reject! { |object| object.new_record? && discard.call(object) }
association.delete(*association.select { |object| discard.call(object) })
end
end

def save_managed_associations #:nodoc:
managed_association_attributes.each do |association_id|
managed_association_attributes.keys.each do |association_id|
association = send(association_id)
association.each(&:save)

Expand Down Expand Up @@ -89,7 +95,8 @@ module ClassMethods
#
def has_many_with_association_option(association_id, options = {}, &extension)
unless (config = options.delete(:attributes)).nil?
self.managed_association_attributes << association_id
managed_association_attributes[association_id] = {}
managed_association_attributes[association_id][:discard_if] = options.delete(:discard_if) if options.has_key?(:discard_if)
end

has_many_without_association_option(association_id, options, &extension)
Expand Down
41 changes: 38 additions & 3 deletions test/test/unit/photo_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ class PhotoTest < ActiveSupport::TestCase
context "comment_attributes" do
context "with valid children" do
setup do
@photo = Photo.create
@gob = @photo.comments.create :author => "Gob Bluth", :body => "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed..."
@bob = @photo.comments.create :author => "Bob Loblaw", :body => "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed..."
create_photo_and_children

@photo.comment_attributes = { @gob.id.to_s => { :author => "Buster Bluth", :body => "I said it was _our_ nausia..." },
:new => { "0" => { :author => "George-Michael", :body => "I was going to smoke the marijuana like a ciggarette." },
Expand Down Expand Up @@ -70,6 +68,36 @@ class PhotoTest < ActiveSupport::TestCase
assert @photo.comments.empty?, "one or more comments not removed: #{@photo.comments.inspect}"
end
end

context "with discard_if => proc { }" do
setup do
Photo.class_eval do
has_many :comments, :attributes => true, :discard_if => proc { |comment| comment.author.blank? && comment.body.blank? }
end

create_photo_and_children


@photo.comment_attributes = { @gob.id.to_s => { :author => "Buster Bluth", :body => "I said it was _our_ nausia..." },
@bob.id.to_s => { :author => '', :body => '' },
:new => { "0" => { :author => "", :body => "" }}}
@photo.save
end

teardown do
Photo.class_eval do
managed_association_attributes[:comments].delete(:discard_if)
end
end

should "discard any child objects for which discard_if evaluates to true" do
assert !@photo.comments.any? { |comment| comment.author.blank? && comment.body.blank? }, @photo.comments.inspect
end

should "not discard other objects" do
assert_equal 1, @photo.comments.length
end
end
end

context "updating with invalid children" do
Expand All @@ -87,4 +115,11 @@ class PhotoTest < ActiveSupport::TestCase
end
end
end

private
def create_photo_and_children
@photo = Photo.create
@gob = @photo.comments.create :author => "Gob Bluth", :body => "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed..."
@bob = @photo.comments.create :author => "Bob Loblaw", :body => "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed..."
end
end

0 comments on commit c6f0f3c

Please sign in to comment.