From e41b711316fee1488f1a3644616d13aa410c7fd8 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Thu, 16 Jul 2020 15:24:15 -0700 Subject: [PATCH] Always skip association placeholder loader if :dataset option given The placeholder loader does not consider the :dataset option, so it should never be used even if the association is marked as not instance specific. In general, a :dataset option that isn't instance specific is unlikely, as otherwise you would get the same associated values for every instance of the model. --- lib/sequel/model/associations.rb | 3 ++- spec/model/associations_spec.rb | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/sequel/model/associations.rb b/lib/sequel/model/associations.rb index c7ffd59b6a..d3467fe4e5 100644 --- a/lib/sequel/model/associations.rb +++ b/lib/sequel/model/associations.rb @@ -801,7 +801,7 @@ def union_eager_loader # Whether the placeholder loader can be used to load the association. def use_placeholder_loader? - !self[:instance_specific] && !self[:eager_graph] + self[:use_placeholder_loader] end end @@ -1810,6 +1810,7 @@ def associate(type, name, opts = OPTS, &block) raise(Error, "cannot clone an association to an association of different type (association #{name} with type #{type} cloning #{opts[:clone]} with type #{cloned_assoc[:type]})") end + opts[:use_placeholder_loader] = !opts[:instance_specific] && !opts[:eager_graph] && !orig_opts[:dataset] opts[:eager_block] = opts[:block] unless opts.include?(:eager_block) opts[:graph_join_type] ||= :left_outer opts[:order_eager_graph] = true unless opts.include?(:order_eager_graph) diff --git a/spec/model/associations_spec.rb b/spec/model/associations_spec.rb index f1f99736c2..0e90031873 100644 --- a/spec/model/associations_spec.rb +++ b/spec/model/associations_spec.rb @@ -1099,6 +1099,32 @@ class Parent < Sequel::Model; end DB.sqls.must_equal ["SELECT * FROM nodes WHERE ((nodes.id = 100) AND (x = 100)) LIMIT 1"] end + it "should handle associations with :dataset option that are marked as instance specific" do + @c2.one_to_one :child_20, :class => @c2, :key=>:id, :instance_specific=>true, :dataset=>proc{|r| r.associated_dataset.where(:x=>100)} + @c2.load(:id => 100).child_20 + DB.sqls.must_equal ["SELECT * FROM nodes WHERE (x = 100) LIMIT 1"] + end + + it "should handle associations with :dataset option that are marked as not-instance specific" do + @c2.one_to_one :child_20, :class => @c2, :key=>:id, :instance_specific=>false, :dataset=>proc{|r| r.associated_dataset.where(:x=>100)} + @c2.load(:id => 100).child_20 + DB.sqls.must_equal ["SELECT * FROM nodes WHERE (x = 100) LIMIT 1"] + end + + it "should handle associations with :dataset option that are marked as instance specific when finalizing associations" do + @c2.one_to_one :child_20, :class => @c2, :key=>:id, :instance_specific=>true, :dataset=>proc{|r| r.associated_dataset.where(:x=>100)} + @c2.finalize_associations + @c2.load(:id => 100).child_20 + DB.sqls.must_equal ["SELECT * FROM nodes WHERE (x = 100) LIMIT 1"] + end + + it "should handle associations with :dataset option that are marked as not-instance specific when finalizing associations" do + @c2.one_to_one :child_20, :class => @c2, :key=>:id, :instance_specific=>false, :dataset=>proc{|r| r.associated_dataset.where(:x=>100)} + @c2.finalize_associations + @c2.load(:id => 100).child_20 + DB.sqls.must_equal ["SELECT * FROM nodes WHERE (x = 100) LIMIT 1"] + end + it "should handle associations with blocks that are marked as not-instance specific and use Sequel.delay" do x = 100 @c2.one_to_one :child_20, :class => @c2, :key=>:id, :instance_specific=>false do |ds| ds.where(:x=>Sequel.delay{x}) end