module Sequel::Plugins::PgArrayAssociations::ClassMethods

Public Instance Methods

many_to_pg_array(name, opts=OPTS, &block) click to toggle source

Create a many_to_pg_array association, for the case where the associated table contains the array with foreign keys pointing to the current table. See associate for options.

    # File lib/sequel/plugins/pg_array_associations.rb
309 def many_to_pg_array(name, opts=OPTS, &block)
310   associate(:many_to_pg_array, name, opts, &block)
311 end
pg_array_to_many(name, opts=OPTS, &block) click to toggle source

Create a pg_array_to_many association, for the case where the current table contains the array with foreign keys pointing to the associated table. See associate for options.

    # File lib/sequel/plugins/pg_array_associations.rb
316 def pg_array_to_many(name, opts=OPTS, &block)
317   associate(:pg_array_to_many, name, opts, &block)
318 end

Private Instance Methods

def_many_to_pg_array(opts) click to toggle source

Setup the many_to_pg_array-specific datasets, eager loaders, and modification methods.

    # File lib/sequel/plugins/pg_array_associations.rb
323 def def_many_to_pg_array(opts)
324   name = opts[:name]
325   model = self
326   pk = opts[:eager_loader_key] = opts[:primary_key] ||= model.primary_key
327   raise(Error, "no primary key specified for #{inspect}") unless pk
328   opts[:key] = opts.default_key unless opts.has_key?(:key)
329   key = opts[:key]
330   key_column = opts[:key_column] ||= opts[:key]
331   if opts[:uniq]
332     opts[:after_load] ||= []
333     opts[:after_load].unshift(:array_uniq!)
334   end
335   opts[:dataset] ||= lambda do
336     opts.associated_dataset.where(Sequel.pg_array_op(opts.predicate_key).contains(Sequel.pg_array([get_column_value(pk)], opts.array_type)))
337   end
338   opts[:eager_loader] ||= proc do |eo|
339     id_map = eo[:id_map]
340 
341     eager_load_results(opts, Hash[eo].merge!(:loader=>false)) do |assoc_record|
342       if pks ||= assoc_record.get_column_value(key)
343         pks.each do |pkv|
344           next unless objects = id_map[pkv]
345           objects.each do |object| 
346             object.associations[name].push(assoc_record)
347           end
348         end
349       end
350     end
351   end
352 
353   join_type = opts[:graph_join_type]
354   select = opts[:graph_select]
355   opts[:cartesian_product_number] ||= 1
356 
357   if opts.include?(:graph_only_conditions)
358     conditions = opts[:graph_only_conditions]
359     graph_block = opts[:graph_block]
360   else
361     conditions = opts[:graph_conditions]
362     conditions = nil if conditions.empty?
363     graph_block = proc do |j, lj, js|
364       Sequel.pg_array_op(Sequel.deep_qualify(j, key_column)).contains([Sequel.deep_qualify(lj, opts.primary_key)])
365     end
366 
367     if orig_graph_block = opts[:graph_block]
368       pg_array_graph_block = graph_block
369       graph_block = proc do |j, lj, js|
370         Sequel.&(orig_graph_block.call(j,lj,js), pg_array_graph_block.call(j, lj, js))
371       end
372     end
373   end
374 
375   opts[:eager_grapher] ||= proc do |eo|
376     ds = eo[:self]
377     ds = ds.graph(eager_graph_dataset(opts, eo), conditions, Hash[eo].merge!(:select=>select, :join_type=>eo[:join_type]||join_type, :qualify=>:deep, :from_self_alias=>eo[:from_self_alias]), &graph_block)
378     ds
379   end
380 
381   return if opts[:read_only]
382 
383   save_opts = {:validate=>opts[:validate]}
384   save_opts[:raise_on_failure] = opts[:raise_on_save_failure] != false
385 
386   opts[:adder] ||= proc do |o|
387     if array = o.get_column_value(key)
388       array << get_column_value(pk)
389     else
390       o.set_column_value("#{key}=", Sequel.pg_array([get_column_value(pk)], opts.array_type))
391     end
392     o.save(save_opts)
393   end
394   
395   opts[:remover] ||= proc do |o|
396     if (array = o.get_column_value(key)) && !array.empty?
397       array.delete(get_column_value(pk))
398       o.save(save_opts)
399     end
400   end
401 
402   opts[:clearer] ||= proc do
403     pk_value = get_column_value(pk)
404     db_type = opts.array_type
405     opts.associated_dataset.where(Sequel.pg_array_op(key).contains(Sequel.pg_array([pk_value], db_type))).update(key=>Sequel.function(:array_remove, key, Sequel.cast(pk_value, db_type)))
406   end
407 end
def_pg_array_to_many(opts) click to toggle source

Setup the pg_array_to_many-specific datasets, eager loaders, and modification methods.

    # File lib/sequel/plugins/pg_array_associations.rb
410 def def_pg_array_to_many(opts)
411   name = opts[:name]
412   opts[:key] = opts.default_key unless opts.has_key?(:key)
413   key = opts[:key]
414   key_column = opts[:key_column] ||= key
415   opts[:eager_loader_key] = nil
416   if opts[:uniq]
417     opts[:after_load] ||= []
418     opts[:after_load].unshift(:array_uniq!)
419   end
420   opts[:dataset] ||= lambda do
421     opts.associated_dataset.where(opts.predicate_key=>get_column_value(key).to_a)
422   end
423   opts[:eager_loader] ||= proc do |eo|
424     rows = eo[:rows]
425     id_map = {}
426     pkm = opts.primary_key_method
427 
428     rows.each do |object|
429       if associated_pks = object.get_column_value(key)
430         associated_pks.each do |apk|
431           (id_map[apk] ||= []) << object
432         end
433       end
434     end
435 
436     eager_load_results(opts, Hash[eo].merge!(:id_map=>id_map)) do |assoc_record|
437       if objects = id_map[assoc_record.get_column_value(pkm)]
438         objects.each do |object| 
439           object.associations[name].push(assoc_record)
440         end
441       end
442     end
443   end
444 
445   join_type = opts[:graph_join_type]
446   select = opts[:graph_select]
447   opts[:cartesian_product_number] ||= 1
448 
449   if opts.include?(:graph_only_conditions)
450     conditions = opts[:graph_only_conditions]
451     graph_block = opts[:graph_block]
452   else
453     conditions = opts[:graph_conditions]
454     conditions = nil if conditions.empty?
455     graph_block = proc do |j, lj, js|
456       Sequel.pg_array_op(Sequel.deep_qualify(lj, key_column)).contains([Sequel.deep_qualify(j, opts.primary_key)])
457     end
458 
459     if orig_graph_block = opts[:graph_block]
460       pg_array_graph_block = graph_block
461       graph_block = proc do |j, lj, js|
462         Sequel.&(orig_graph_block.call(j,lj,js), pg_array_graph_block.call(j, lj, js))
463       end
464     end
465   end
466 
467   opts[:eager_grapher] ||= proc do |eo|
468     ds = eo[:self]
469     ds = ds.graph(eager_graph_dataset(opts, eo), conditions, Hash[eo].merge!(:select=>select, :join_type=>eo[:join_type]||join_type, :qualify=>:deep, :from_self_alias=>eo[:from_self_alias]), &graph_block)
470     ds
471   end
472 
473   return if opts[:read_only]
474 
475   save_opts = {:validate=>opts[:validate]}
476   save_opts[:raise_on_failure] = opts[:raise_on_save_failure] != false
477 
478   if opts[:save_after_modify]
479     save_after_modify = proc do |obj|
480       obj.save(save_opts)
481     end
482   end
483 
484   opts[:adder] ||= proc do |o|
485     opk = o.get_column_value(opts.primary_key) 
486     if array = get_column_value(key)
487       modified!(key)
488       array << opk
489     else
490       set_column_value("#{key}=", Sequel.pg_array([opk], opts.array_type))
491     end
492     save_after_modify.call(self) if save_after_modify
493   end
494   
495   opts[:remover] ||= proc do |o|
496     if (array = get_column_value(key)) && !array.empty?
497       modified!(key)
498       array.delete(o.get_column_value(opts.primary_key))
499       save_after_modify.call(self) if save_after_modify
500     end
501   end
502 
503   opts[:clearer] ||= proc do
504     if (array = get_column_value(key)) && !array.empty?
505       modified!(key)
506       array.clear
507       save_after_modify.call(self) if save_after_modify
508     end
509   end
510 end