lib/sequel/plugins/many_through_many.rb in sequel-4.9.0 vs lib/sequel/plugins/many_through_many.rb in sequel-4.10.0
- old
+ new
@@ -99,17 +99,29 @@
cached_fetch(:#{meth}){calculate_edges[:#{meth}]}
end
END
end
+ # The alias for the first join table.
+ def join_table_alias
+ final_reverse_edge[:alias]
+ end
+
# Many through many associations don't have a reciprocal
def reciprocal
nil
end
private
+ def _associated_dataset
+ ds = associated_class
+ reverse_edges.each{|t| ds = ds.join(t[:table], Array(t[:left]).zip(Array(t[:right])), :table_alias=>t[:alias], :qualify=>:deep)}
+ ft = final_reverse_edge
+ ds.join(ft[:table], Array(ft[:left]).zip(Array(ft[:right])), :table_alias=>ft[:alias], :qualify=>:deep)
+ end
+
# Make sure to use unique table aliases when lazy loading or eager loading
def calculate_reverse_edge_aliases(reverse_edges)
aliases = [associated_class.table_name]
reverse_edges.each do |e|
table_alias = e[:table]
@@ -154,30 +166,14 @@
}
h.each{|k, v| cached_set(k, v)}
h
end
- def filter_by_associations_add_conditions_dataset_filter(ds)
- reverse_edges.each{|t| ds = ds.join(t[:table], Array(t[:left]).zip(Array(t[:right])), :table_alias=>t[:alias], :qualify=>:deep)}
- ft = final_reverse_edge
- k = qualify(ft[:alias], Array(self[:left_key]))
- ds.join(ft[:table], Array(ft[:left]).zip(Array(ft[:right])), :table_alias=>ft[:alias], :qualify=>:deep).
- where(Sequel.negate(k.zip([]))).
- select(*k)
- end
-
def filter_by_associations_limit_key
fe = edges.first
Array(qualify(fe[:table], fe[:right])) + Array(qualify(associated_class.table_name, associated_class.primary_key))
end
-
- def filter_by_associations_limit_subquery
- subquery = associated_eager_dataset.unlimited
- reverse_edges.each{|t| subquery = subquery.join(t[:table], Array(t[:left]).zip(Array(t[:right])), :table_alias=>t[:alias], :qualify=>:deep)}
- ft = final_reverse_edge
- subquery.join(ft[:table], Array(ft[:left]).zip(Array(ft[:right])), :table_alias=>ft[:alias], :qualify=>:deep)
- end
end
class OneThroughManyAssociationReflection < ManyThroughManyAssociationReflection
Sequel::Model::Associations::ASSOCIATION_TYPES[:one_through_many] = self
include Sequel::Model::Associations::SingularAssociationReflection
@@ -212,12 +208,10 @@
private
# Create the association methods and :eager_loader and :eager_grapher procs.
def def_many_through_many(opts)
one_through_many = opts[:type] == :one_through_many
- name = opts[:name]
- model = self
opts[:read_only] = true
opts[:after_load].unshift(:array_uniq!) if opts[:uniq]
opts[:cartesian_product_number] ||= one_through_many ? 0 : 2
opts[:through] = opts[:through].map do |e|
case e
@@ -231,61 +225,22 @@
raise(Error, "the through option/argument for many_through_many associations must be an enumerable of arrays or hashes")
end
end
left_key = opts[:left_key] = opts[:through].first[:left]
- uses_lcks = opts[:uses_left_composite_keys] = left_key.is_a?(Array)
- left_keys = Array(left_key)
+ opts[:left_keys] = Array(left_key)
+ opts[:uses_left_composite_keys] = left_key.is_a?(Array)
left_pk = (opts[:left_primary_key] ||= self.primary_key)
opts[:eager_loader_key] = left_pk unless opts.has_key?(:eager_loader_key)
- left_pks = opts[:left_primary_keys] = Array(left_pk)
+ opts[:left_primary_keys] = Array(left_pk)
lpkc = opts[:left_primary_key_column] ||= left_pk
lpkcs = opts[:left_primary_key_columns] ||= Array(lpkc)
- opts[:dataset] ||= lambda do
- ds = opts.associated_dataset
- opts.reverse_edges.each{|t| ds = ds.join(t[:table], Array(t[:left]).zip(Array(t[:right])), :table_alias=>t[:alias], :qualify=>:deep)}
- ft = opts.final_reverse_edge
- ds.join(ft[:table], Array(ft[:left]).zip(Array(ft[:right])) + opts.predicate_keys.zip(left_pks.map{|k| send(k)}), :table_alias=>ft[:alias], :qualify=>:deep)
- end
+ opts[:dataset] ||= opts.association_dataset_proc
- slice_range = opts.slice_range
- left_key_alias = opts[:left_key_alias] ||= opts.default_associated_key_alias
- opts[:eager_loader] ||= lambda do |eo|
- h = eo[:id_map]
- rows = eo[:rows]
- ds = opts.associated_class
- opts.reverse_edges.each{|t| ds = ds.join(t[:table], Array(t[:left]).zip(Array(t[:right])), :table_alias=>t[:alias], :qualify=>:deep)}
- ft = opts.final_reverse_edge
+ opts[:left_key_alias] ||= opts.default_associated_key_alias
+ opts[:eager_loader] ||= opts.method(:default_eager_loader)
- ds = ds.join(ft[:table], Array(ft[:left]).zip(Array(ft[:right])) + [[opts.predicate_key, h.keys]], :table_alias=>ft[:alias], :qualify=>:deep)
- ds = model.eager_loading_dataset(opts, ds, nil, eo[:associations], eo)
- ds = opts.apply_eager_limit_strategy(ds)
- opts.initialize_association_cache(rows)
-
- assign_singular = opts.assign_singular?
- delete_rn = opts.delete_row_number_column(ds)
- ds.all do |assoc_record|
- assoc_record.values.delete(delete_rn) if delete_rn
- hash_key = if uses_lcks
- left_key_alias.map{|k| assoc_record.values.delete(k)}
- else
- assoc_record.values.delete(left_key_alias)
- end
- next unless objects = h[hash_key]
- if assign_singular
- objects.each do |object|
- object.associations[name] ||= assoc_record
- end
- else
- objects.each do |object|
- object.associations[name].push(assoc_record)
- end
- end
- end
- opts.apply_ruby_eager_limit_strategy(rows)
- end
-
join_type = opts[:graph_join_type]
select = opts[:graph_select]
graph_block = opts[:graph_block]
only_conditions = opts[:graph_only_conditions]
use_only_conditions = opts.include?(:graph_only_conditions)
@@ -311,11 +266,9 @@
end
fe = opts.final_edge
ds.graph(opts.associated_class, use_only_conditions ? only_conditions : (Array(opts.right_primary_key).zip(Array(fe[:left])) + conditions), :select=>select, :table_alias=>eo[:table_alias], :qualify=>:deep, :join_type=>eo[:join_type]||join_type, &graph_block)
end
end
-
- def_association_dataset_methods(opts)
end
# Use def_many_through_many, since they share pretty much the same code.
def def_one_through_many(opts)
def_many_through_many(opts)