Permalink
Browse files

Make add_ association method not add the associated object to the cac…

…hed array if it's already there

This makes the most sense for one_to_many associations, since those cannot
be associated more than once.  For many_to_many associations, I think it
is a better default, as it's a rare case that you want duplicate items
in the association.  If you do want duplicate items for a many_to_many
association and you want it to work well with caching, please bring it
up on the Sequel mailing list and we'll work it out.

Note that this exact thing was done for reciprocal associations, so
Sequel is more consistent with this change.
  • Loading branch information...
1 parent bab0b9b commit 28480f9d03773b6ee8f49c69753ee4584b53598b @jeremyevans committed Oct 27, 2009
Showing with 31 additions and 1 deletion.
  1. +2 −0 CHANGELOG
  2. +3 −1 lib/sequel/model/associations.rb
  3. +26 −0 spec/model/associations_spec.rb
View
@@ -1,5 +1,7 @@
=== HEAD
+* Make add_ association method not add the associated object to the cached array if it's already there (jeremyevans)
+
* Add Model#modified! for explicitly marking an object as modified, so save_changes/update will run callbacks even if no columns have been modified (jeremyevans)
* Add support for a :fields option in the nested attributes plugin, and only allow updating of the fields specified (jeremyevans)
@@ -994,7 +994,9 @@ def add_associated_object(opts, o, *args)
end
return if run_association_callbacks(opts, :before_add, o) == false
send(opts._add_method, o, *args)
- associations[opts[:name]].push(o) if associations.include?(opts[:name])
+ if array = associations[opts[:name]] and !array.include?(o)
+ array.push(o)
+ end
add_reciprocal_object(opts, o)
run_association_callbacks(opts, :after_add, o)
o
@@ -745,6 +745,21 @@ def ds.fetch_rows(sql)
a.should == n.add_attribute(a)
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = 5 WHERE (id = 2345)']
end
+
+ it "should have add_ method not add the same object to the cached association array if the object is already in the array" do
+ @c2.one_to_many :attributes, :class => @c1
+
+ n = @c2.new(:id => 1234)
+ a = @c1.new(:id => 2345)
+ a.save
+ MODEL_DB.reset
+ n.associations[:attributes] = []
+ a.should == n.add_attribute(a)
+ a.should == n.add_attribute(a)
+ a.values.should == {:node_id => 1234, :id => 2345}
+ MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = 1234 WHERE (id = 2345)'] * 2
+ n.attributes.should == [a]
+ end
it "should have add_ method respect composite keys" do
@c2.one_to_many :attributes, :class => @c1, :key =>[:node_id, :y], :primary_key=>[:id, :x]
@@ -1666,6 +1681,17 @@ def ds.fetch_rows(sql)
].should(include(MODEL_DB.sqls.first))
end
+ it "should have add_ method not add the same object to the cached association array if the object is already in the array" do
+ @c2.many_to_many :attributes, :class => @c1
+
+ n = @c2.load(:id => 1234).set(:xxx=>5)
+ a = @c1.load(:id => 2345).set(:yyy=>8)
+ n.associations[:attributes] = []
+ a.should == n.add_attribute(a)
+ a.should == n.add_attribute(a)
+ n.attributes.should == [a]
+ end
+
it "should have the add_ method respect composite keys" do
@c2.many_to_many :attributes, :class => @c1, :left_key=>[:l1, :l2], :right_key=>[:r1, :r2], :left_primary_key=>[:id, :x], :right_primary_key=>[:id, :y]
n = @c2.load(:id => 1234, :x=>5)

0 comments on commit 28480f9

Please sign in to comment.