module Sequel::Plugins::AssociationPks::ClassMethods

Private Instance Methods

def_association_pks_methods(opts) click to toggle source

Define a association_pks method using the block for the association reflection

   # File lib/sequel/plugins/association_pks.rb
75 def def_association_pks_methods(opts)
76   association_module_def(opts[:pks_dataset_method], &opts[:pks_dataset])
77 
78   opts[:pks_getter_method] = :"#{singularize(opts[:name])}_pks_getter"
79   association_module_def(opts[:pks_getter_method], &opts[:pks_getter])
80   association_module_def(:"#{singularize(opts[:name])}_pks", opts){|dynamic_opts=OPTS| _association_pks_getter(opts, dynamic_opts)}
81 
82   if opts[:pks_setter]
83     opts[:pks_setter_method] = :"#{singularize(opts[:name])}_pks_setter"
84     association_module_def(opts[:pks_setter_method], &opts[:pks_setter])
85     association_module_def(:"#{singularize(opts[:name])}_pks=", opts){|pks| _association_pks_setter(opts, pks)}
86   end
87 end
def_many_to_many(opts) click to toggle source

Add a getter that checks the join table for matching records and a setter that deletes from or inserts into the join table.

Calls superclass method
    # File lib/sequel/plugins/association_pks.rb
 91 def def_many_to_many(opts)
 92   super
 93 
 94   return if opts[:type] == :one_through_one
 95 
 96   # Grab values from the reflection so that the hash lookup only needs to be
 97   # done once instead of inside every method call.
 98   lk, lpk, rk = opts.values_at(:left_key, :left_primary_key, :right_key)
 99   clpk = lpk.is_a?(Array)
100   crk = rk.is_a?(Array)
101 
102   dataset_method = opts[:pks_dataset_method] = :"#{singularize(opts[:name])}_pks_dataset"
103 
104   opts[:pks_dataset] = if join_associated_table = opts[:association_pks_use_associated_table]
105     tname = opts[:join_table]
106     lambda do
107       cond = if clpk
108         lk.zip(lpk).map{|k, pk| [Sequel.qualify(tname, k), get_column_value(pk)]}
109       else
110         {Sequel.qualify(tname, lk) => get_column_value(lpk)}
111       end
112       rpk = opts.associated_class.primary_key
113       opts.associated_dataset.
114         naked.where(cond).
115         select(*Sequel.public_send(rpk.is_a?(Array) ? :deep_qualify : :qualify, opts.associated_class.table_name, rpk))
116     end
117   elsif clpk
118     lambda do
119       cond = lk.zip(lpk).map{|k, pk| [k, get_column_value(pk)]}
120       _join_table_dataset(opts).where(cond).select(*rk)
121     end
122   else
123     lambda do
124       _join_table_dataset(opts).where(lk=>get_column_value(lpk)).select(*rk)
125     end
126   end
127 
128   opts[:pks_getter] = if join_associated_table = opts[:association_pks_use_associated_table]
129     lambda do
130       public_send(dataset_method).map(opts.associated_class.primary_key)
131     end
132   else
133     lambda do
134       public_send(dataset_method).map(rk)
135     end
136   end
137 
138   if !opts[:read_only] && !join_associated_table
139     opts[:pks_setter] = lambda do |pks|
140       if pks.empty?
141         public_send(opts[:remove_all_method])
142       else
143         checked_transaction do
144           if clpk
145             lpkv = lpk.map{|k| get_column_value(k)}
146             cond = lk.zip(lpkv)
147           else
148             lpkv = get_column_value(lpk)
149             cond = {lk=>lpkv}
150           end
151           ds = _join_table_dataset(opts).where(cond)
152           ds.exclude(rk=>pks).delete
153           pks -= ds.select_map(rk)
154           lpkv = Array(lpkv)
155           key_array = crk ? pks.map{|pk| lpkv + pk} : pks.map{|pk| lpkv + [pk]}
156           key_columns = Array(lk) + Array(rk)
157           ds.import(key_columns, key_array)
158         end
159       end
160     end
161   end
162 
163   def_association_pks_methods(opts)
164 end
def_one_to_many(opts) click to toggle source

Add a getter that checks the association dataset and a setter that updates the associated table.

Calls superclass method
    # File lib/sequel/plugins/association_pks.rb
168 def def_one_to_many(opts)
169   super
170 
171   return if opts[:type] == :one_to_one
172 
173   key = opts[:key]
174 
175   dataset_method = opts[:pks_dataset_method] = :"#{singularize(opts[:name])}_pks_dataset"
176 
177   opts[:pks_dataset] = lambda do
178     public_send(opts[:dataset_method]).select(*opts.associated_class.primary_key)
179   end
180 
181   opts[:pks_getter] = lambda do
182     public_send(dataset_method).map(opts.associated_class.primary_key)
183   end
184 
185   unless opts[:read_only]
186     opts[:pks_setter] = lambda do |pks|
187       if pks.empty?
188         public_send(opts[:remove_all_method])
189       else
190         primary_key = opts.associated_class.primary_key
191         pkh = {primary_key=>pks}
192 
193         if key.is_a?(Array)
194           h = {}
195           nh = {}
196           key.zip(pk).each do|k, v|
197             h[k] = v
198             nh[k] = nil
199           end
200         else
201           h = {key=>pk}
202           nh = {key=>nil}
203         end
204 
205         checked_transaction do
206           ds = public_send(opts.dataset_method)
207           ds.unfiltered.where(pkh).update(h)
208           ds.exclude(pkh).update(nh)
209         end
210       end
211     end
212   end
213 
214   def_association_pks_methods(opts)
215 end