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     eo = Hash[eo]
341     eo[:loader] = false
342 
343     eager_load_results(opts, eo) do |assoc_record|
344       if pks = assoc_record.get_column_value(key)
345         pks.each do |pkv|
346           id_map[pkv].each do |object| 
347             object.associations[name].push(assoc_record)
348           end
349         end
350       end
351     end
352   end
353 
354   join_type = opts[:graph_join_type]
355   select = opts[:graph_select]
356   opts[:cartesian_product_number] ||= 1
357 
358   if opts.include?(:graph_only_conditions)
359     conditions = opts[:graph_only_conditions]
360     graph_block = opts[:graph_block]
361   else
362     conditions = opts[:graph_conditions]
363     conditions = nil if conditions.empty?
364     graph_block = proc do |j, lj, js|
365       Sequel.pg_array_op(Sequel.deep_qualify(j, key_column)).contains([Sequel.deep_qualify(lj, opts.primary_key)])
366     end
367 
368     if orig_graph_block = opts[:graph_block]
369       pg_array_graph_block = graph_block
370       graph_block = proc do |j, lj, js|
371         Sequel.&(orig_graph_block.call(j,lj,js), pg_array_graph_block.call(j, lj, js))
372       end
373     end
374   end
375 
376   opts[:eager_grapher] ||= proc do |eo|
377     ds = eo[:self]
378     ds = ds.graph(eager_graph_dataset(opts, eo), conditions, eo.merge(:select=>select, :join_type=>eo[:join_type]||join_type, :qualify=>:deep), &graph_block)
379     ds
380   end
381 
382   return if opts[:read_only]
383 
384   save_opts = {:validate=>opts[:validate]}
385   save_opts[:raise_on_failure] = opts[:raise_on_save_failure] != false
386 
387   unless opts.has_key?(:adder)
388     opts[:adder] = proc do |o|
389       if array = o.get_column_value(key)
390         array << get_column_value(pk)
391       else
392         o.set_column_value("#{key}=", Sequel.pg_array([get_column_value(pk)], opts.array_type))
393       end
394       o.save(save_opts)
395     end
396   end
397     
398   unless opts.has_key?(:remover)
399     opts[:remover] = proc do |o|
400       if (array = o.get_column_value(key)) && !array.empty?
401         array.delete(get_column_value(pk))
402         o.save(save_opts)
403       end
404     end
405   end
406 
407   unless opts.has_key?(:clearer)
408     opts[:clearer] = proc do
409       pk_value = get_column_value(pk)
410       db_type = opts.array_type
411       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)))
412     end
413   end
414 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
417 def def_pg_array_to_many(opts)
418   name = opts[:name]
419   opts[:key] = opts.default_key unless opts.has_key?(:key)
420   key = opts[:key]
421   key_column = opts[:key_column] ||= key
422   opts[:eager_loader_key] = nil
423   if opts[:uniq]
424     opts[:after_load] ||= []
425     opts[:after_load].unshift(:array_uniq!)
426   end
427   opts[:dataset] ||= lambda do
428     opts.associated_dataset.where(opts.predicate_key=>get_column_value(key).to_a)
429   end
430   opts[:eager_loader] ||= proc do |eo|
431     rows = eo[:rows]
432     id_map = {}
433     pkm = opts.primary_key_method
434 
435     Sequel.synchronize_with(eo[:mutex]) do
436       rows.each do |object|
437         if associated_pks = object.get_column_value(key)
438           associated_pks.each do |apk|
439             (id_map[apk] ||= []) << object
440           end
441         end
442       end
443     end
444 
445     eo = Hash[eo]
446     eo[:id_map] = id_map
447     eager_load_results(opts, eo) do |assoc_record|
448       if objects = id_map[assoc_record.get_column_value(pkm)]
449         objects.each do |object| 
450           object.associations[name].push(assoc_record)
451         end
452       end
453     end
454   end
455 
456   join_type = opts[:graph_join_type]
457   select = opts[:graph_select]
458   opts[:cartesian_product_number] ||= 1
459 
460   if opts.include?(:graph_only_conditions)
461     conditions = opts[:graph_only_conditions]
462     graph_block = opts[:graph_block]
463   else
464     conditions = opts[:graph_conditions]
465     conditions = nil if conditions.empty?
466     graph_block = proc do |j, lj, js|
467       Sequel.pg_array_op(Sequel.deep_qualify(lj, key_column)).contains([Sequel.deep_qualify(j, opts.primary_key)])
468     end
469 
470     if orig_graph_block = opts[:graph_block]
471       pg_array_graph_block = graph_block
472       graph_block = proc do |j, lj, js|
473         Sequel.&(orig_graph_block.call(j,lj,js), pg_array_graph_block.call(j, lj, js))
474       end
475     end
476   end
477 
478   opts[:eager_grapher] ||= proc do |eo|
479     ds = eo[:self]
480     ds = ds.graph(eager_graph_dataset(opts, eo), conditions, eo.merge(:select=>select, :join_type=>eo[:join_type]||join_type, :qualify=>:deep), &graph_block)
481     ds
482   end
483 
484   return if opts[:read_only]
485 
486   save_opts = {:validate=>opts[:validate]}
487   save_opts[:raise_on_failure] = opts[:raise_on_save_failure] != false
488 
489   if opts[:save_after_modify]
490     save_after_modify = proc do |obj|
491       obj.save(save_opts)
492     end
493   end
494 
495   unless opts.has_key?(:adder)
496     opts[:adder] = proc do |o|
497       opk = o.get_column_value(opts.primary_key) 
498       if array = get_column_value(key)
499         modified!(key)
500         array << opk
501       else
502         set_column_value("#{key}=", Sequel.pg_array([opk], opts.array_type))
503       end
504       save_after_modify.call(self) if save_after_modify
505     end
506   end
507     
508   unless opts.has_key?(:remover)
509     opts[:remover] = proc do |o|
510       if (array = get_column_value(key)) && !array.empty?
511         modified!(key)
512         array.delete(o.get_column_value(opts.primary_key))
513         save_after_modify.call(self) if save_after_modify
514       end
515     end
516   end
517 
518   unless opts.has_key?(:clearer)
519     opts[:clearer] = proc do
520       if (array = get_column_value(key)) && !array.empty?
521         modified!(key)
522         array.clear
523         save_after_modify.call(self) if save_after_modify
524       end
525     end
526   end
527 end