Permalink
Browse files

add discard_if option to has_many_with_association_options

git-svn-id: http://svn.jamesgolick.com/attribute_fu/trunk@64 80b79608-713f-0410-8737-d8c0d0c1b50c
  • Loading branch information...
1 parent e396b41 commit c6f0f3c744a8e5241271e36155fbe43d5bf358ca james committed Feb 16, 2008
Showing with 49 additions and 7 deletions.
  1. +11 −4 lib/attribute_fu/associations.rb
  2. +38 −3 test/test/unit/photo_test.rb
@@ -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
@@ -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
@@ -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)
@@ -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)
@@ -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." },
@@ -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
@@ -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.