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