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)