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   opts[:adder] ||= proc do |o|
388     if array = o.get_column_value(key)
389       array << get_column_value(pk)
390     else
391       o.set_column_value("#{key}=", Sequel.pg_array([get_column_value(pk)], opts.array_type))
392     end
393     o.save(save_opts)
394   end
395   
396   opts[:remover] ||= proc do |o|
397     if (array = o.get_column_value(key)) && !array.empty?
398       array.delete(get_column_value(pk))
399       o.save(save_opts)
400     end
401   end
402 
403   opts[:clearer] ||= proc do
404     pk_value = get_column_value(pk)
405     db_type = opts.array_type
406     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)))
407   end
408 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
411 def def_pg_array_to_many(opts)
412   name = opts[:name]
413   opts[:key] = opts.default_key unless opts.has_key?(:key)
414   key = opts[:key]
415   key_column = opts[:key_column] ||= key
416   opts[:eager_loader_key] = nil
417   if opts[:uniq]
418     opts[:after_load] ||= []
419     opts[:after_load].unshift(:array_uniq!)
420   end
421   opts[:dataset] ||= lambda do
422     opts.associated_dataset.where(opts.predicate_key=>get_column_value(key).to_a)
423   end
424   opts[:eager_loader] ||= proc do |eo|
425     rows = eo[:rows]
426     id_map = {}
427     pkm = opts.primary_key_method
428 
429     Sequel.synchronize_with(eo[:mutex]) do
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     end
438 
439     eo = Hash[eo]
440     eo[:id_map] = id_map
441     eager_load_results(opts, eo) do |assoc_record|
442       if objects = id_map[assoc_record.get_column_value(pkm)]
443         objects.each do |object| 
444           object.associations[name].push(assoc_record)
445         end
446       end
447     end
448   end
449 
450   join_type = opts[:graph_join_type]
451   select = opts[:graph_select]
452   opts[:cartesian_product_number] ||= 1
453 
454   if opts.include?(:graph_only_conditions)
455     conditions = opts[:graph_only_conditions]
456     graph_block = opts[:graph_block]
457   else
458     conditions = opts[:graph_conditions]
459     conditions = nil if conditions.empty?
460     graph_block = proc do |j, lj, js|
461       Sequel.pg_array_op(Sequel.deep_qualify(lj, key_column)).contains([Sequel.deep_qualify(j, opts.primary_key)])
462     end
463 
464     if orig_graph_block = opts[:graph_block]
465       pg_array_graph_block = graph_block
466       graph_block = proc do |j, lj, js|
467         Sequel.&(orig_graph_block.call(j,lj,js), pg_array_graph_block.call(j, lj, js))
468       end
469     end
470   end
471 
472   opts[:eager_grapher] ||= proc do |eo|
473     ds = eo[:self]
474     ds = ds.graph(eager_graph_dataset(opts, eo), conditions, eo.merge(:select=>select, :join_type=>eo[:join_type]||join_type, :qualify=>:deep), &graph_block)
475     ds
476   end
477 
478   return if opts[:read_only]
479 
480   save_opts = {:validate=>opts[:validate]}
481   save_opts[:raise_on_failure] = opts[:raise_on_save_failure] != false
482 
483   if opts[:save_after_modify]
484     save_after_modify = proc do |obj|
485       obj.save(save_opts)
486     end
487   end
488 
489   opts[:adder] ||= proc do |o|
490     opk = o.get_column_value(opts.primary_key) 
491     if array = get_column_value(key)
492       modified!(key)
493       array << opk
494     else
495       set_column_value("#{key}=", Sequel.pg_array([opk], opts.array_type))
496     end
497     save_after_modify.call(self) if save_after_modify
498   end
499   
500   opts[:remover] ||= proc do |o|
501     if (array = get_column_value(key)) && !array.empty?
502       modified!(key)
503       array.delete(o.get_column_value(opts.primary_key))
504       save_after_modify.call(self) if save_after_modify
505     end
506   end
507 
508   opts[:clearer] ||= proc do
509     if (array = get_column_value(key)) && !array.empty?
510       modified!(key)
511       array.clear
512       save_after_modify.call(self) if save_after_modify
513     end
514   end
515 end