Module Sequel::Plugins::DatasetAssociations::DatasetMethods
In: lib/sequel/plugins/dataset_associations.rb

Methods

Public Instance methods

For the association given by name, return a dataset of associated objects such that it would return the union of calling the association method on all objects returned by the current dataset.

This supports most options that are supported when eager loading. However, it will only work for limited associations or *_one associations with orders if the database supports window functions.

[Source]

     # File lib/sequel/plugins/dataset_associations.rb, line 80
 80:         def associated(name)
 81:           raise Error, "unrecognized association name: #{name.inspect}" unless r = model.association_reflection(name)
 82:           ds = r.associated_class.dataset
 83:           sds = opts[:limit] ? self : unordered
 84:           ds = case r[:type]
 85:           when :many_to_one
 86:             ds.where(r.qualified_primary_key=>sds.select(*Array(r[:qualified_key])))
 87:           when :one_to_one, :one_to_many
 88:             r.send(:apply_filter_by_associations_limit_strategy, ds.where(r.qualified_key=>sds.select(*Array(r.qualified_primary_key))))
 89:           when :many_to_many, :one_through_one
 90:             mds = r.associated_class.dataset.
 91:               join(r[:join_table], r[:right_keys].zip(r.right_primary_keys)).
 92:               select(*Array(r.qualified_right_key)).
 93:               where(r.qualify(r.join_table_alias, r[:left_keys])=>sds.select(*r.qualify(model.table_name, r[:left_primary_key_columns])))
 94:             ds.where(r.qualified_right_primary_key=>r.send(:apply_filter_by_associations_limit_strategy, mds))
 95:           when :many_through_many, :one_through_many
 96:             if r.reverse_edges.empty?
 97:               mds = r.associated_dataset
 98:               fe = r.edges.first
 99:               selection = Array(r.qualify(fe[:table], r.final_edge[:left]))
100:               predicate_key = r.qualify(fe[:table], fe[:right])
101:             else
102:               mds = model.dataset
103:               iq = model.table_name
104:               edges = r.edges.map(&:dup)
105:               edges << r.final_edge.dup
106:               edges.each do |e|
107:                 alias_expr = e[:table]
108:                 aliaz = mds.unused_table_alias(e[:table])
109:                 unless aliaz == alias_expr
110:                   alias_expr = Sequel.as(e[:table], aliaz)
111:                 end
112:                 e[:alias] = aliaz
113:                 mds = mds.join(alias_expr, Array(e[:right]).zip(Array(e[:left])), :implicit_qualifier=>iq)
114:                 iq = nil
115:               end
116:               fe, f1e, f2e = edges.values_at(0, -1, -2)
117:               selection = Array(r.qualify(f2e[:alias], f1e[:left]))
118:               predicate_key = r.qualify(fe[:alias], fe[:right])
119:             end
120: 
121:             mds = mds.
122:               select(*selection).
123:               where(predicate_key=>sds.select(*r.qualify(model.table_name, r[:left_primary_key_columns])))
124:             ds.where(r.qualified_right_primary_key=>r.send(:apply_filter_by_associations_limit_strategy, mds))
125:           when :pg_array_to_many
126:             ds.where(Sequel[r.primary_key=>sds.select{Sequel.pg_array_op(r.qualify(r[:model].table_name, r[:key])).unnest}])
127:           when :many_to_pg_array
128:             ds.where(Sequel.function(:coalesce, Sequel.pg_array_op(r[:key]).overlaps(sds.select{array_agg(r.qualify(r[:model].table_name, r.primary_key))}), false))
129:           else
130:             raise Error, "unrecognized association type for association #{name.inspect}: #{r[:type].inspect}"
131:           end
132: 
133:           ds = r.apply_eager_dataset_changes(ds).unlimited
134: 
135:           if r[:dataset_associations_join]
136:             case r[:type]
137:             when :many_to_many, :one_through_one
138:               ds = ds.join(r[:join_table], r[:right_keys].zip(r.right_primary_keys))
139:             when :many_through_many, :one_through_many
140:               (r.reverse_edges + [r.final_reverse_edge]).each{|e| ds = ds.join(e[:table], e.fetch(:only_conditions, (Array(e[:left]).zip(Array(e[:right])) + Array(e[:conditions]))), :table_alias=>ds.unused_table_alias(e[:table]), :qualify=>:deep, &e[:block])}
141:             end
142:           end
143: 
144:           ds
145:         end

[Validate]