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