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 klass = r.associated_class 86 sds = opts[:limit] ? self : unordered 87 88 if r.send(:filter_by_associations_limit_strategy) == :lateral_subquery 89 ds = r.send(:associated_eager_dataset) 90 91 case r[:type] 92 when :one_to_one, :one_to_many 93 sds = sds.select(*Array(r.qualified_primary_key)) 94 else 95 sds = sds.select(*r[:left_primary_keys]) 96 ds = ds.select_all(klass.table_name) 97 update_select = true 98 end 99 100 ds = r.send(:apply_lateral_subquery_eager_limit_strategy, ds, sds, r.limit_and_offset) 101 ds = ds.clone(:select=>ds.opts[:select][0,1]) if update_select 102 return ds.clone(:eager=>nil, :eager_graph=>nil) 103 end 104 105 ds = klass.dataset 106 ds = case r[:type] 107 when :many_to_one 108 ds.where(r.qualified_primary_key=>sds.select(*Array(r[:qualified_key]))) 109 when :one_to_one, :one_to_many 110 r.send(:apply_filter_by_associations_limit_strategy, ds.where(r.qualified_key=>sds.select(*Array(r.qualified_primary_key)))) 111 when :many_to_many, :one_through_one 112 mds = r.associated_class.dataset. 113 join(r[:join_table], r[:right_keys].zip(r.right_primary_keys)). 114 select(*Array(r.qualified_right_key)). 115 where(r.qualify(r.join_table_alias, r[:left_keys])=>sds.select(*r.qualify(model.table_name, r[:left_primary_key_columns]))) 116 ds.where(r.qualified_right_primary_key=>r.send(:apply_filter_by_associations_limit_strategy, mds)) 117 when :many_through_many, :one_through_many 118 if r.reverse_edges.empty? 119 mds = r.associated_dataset 120 fe = r.edges.first 121 selection = Array(r.qualify(fe[:table], r.final_edge[:left])) 122 predicate_key = r.qualify(fe[:table], fe[:right]) 123 else 124 mds = model.dataset 125 iq = model.table_name 126 edges = r.edges.map(&:dup) 127 edges << r.final_edge.dup 128 edges.each do |e| 129 alias_expr = e[:table] 130 aliaz = mds.unused_table_alias(e[:table]) 131 unless aliaz == alias_expr 132 alias_expr = Sequel.as(e[:table], aliaz) 133 end 134 e[:alias] = aliaz 135 mds = mds.join(alias_expr, Array(e[:right]).zip(Array(e[:left])), :implicit_qualifier=>iq) 136 iq = nil 137 end 138 fe, f1e, f2e = edges.values_at(0, -1, -2) 139 selection = Array(r.qualify(f2e[:alias], f1e[:left])) 140 predicate_key = r.qualify(fe[:alias], fe[:right]) 141 end 142 143 mds = mds. 144 select(*selection). 145 where(predicate_key=>sds.select(*r.qualify(model.table_name, r[:left_primary_key_columns]))) 146 ds.where(r.qualified_right_primary_key=>r.send(:apply_filter_by_associations_limit_strategy, mds)) 147 when :pg_array_to_many 148 ds.where(Sequel[r.primary_key=>sds.select{Sequel.pg_array_op(r.qualify(r[:model].table_name, r[:key])).unnest}]) 149 when :many_to_pg_array 150 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)) 151 else 152 raise Error, "unrecognized association type for association #{name.inspect}: #{r[:type].inspect}" 153 end 154 155 ds = r.apply_eager_dataset_changes(ds).unlimited 156 157 if r[:dataset_associations_join] 158 case r[:type] 159 when :many_to_many, :one_through_one 160 ds = ds.join(r[:join_table], r[:right_keys].zip(r.right_primary_keys)) 161 when :many_through_many, :one_through_many 162 (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])} 163 end 164 end 165 166 ds 167 end