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     rows.each do |object|
430       if associated_pks = object.get_column_value(key)
431         associated_pks.each do |apk|
432           (id_map[apk] ||= []) << object
433         end
434       end
435     end
436 
437     eo = Hash[eo]
438     eo[:id_map] = id_map
439     eager_load_results(opts, eo) do |assoc_record|
440       if objects = id_map[assoc_record.get_column_value(pkm)]
441         objects.each do |object| 
442           object.associations[name].push(assoc_record)
443         end
444       end
445     end
446   end
447 
448   join_type = opts[:graph_join_type]
449   select = opts[:graph_select]
450   opts[:cartesian_product_number] ||= 1
451 
452   if opts.include?(:graph_only_conditions)
453     conditions = opts[:graph_only_conditions]
454     graph_block = opts[:graph_block]
455   else
456     conditions = opts[:graph_conditions]
457     conditions = nil if conditions.empty?
458     graph_block = proc do |j, lj, js|
459       Sequel.pg_array_op(Sequel.deep_qualify(lj, key_column)).contains([Sequel.deep_qualify(j, opts.primary_key)])
460     end
461 
462     if orig_graph_block = opts[:graph_block]
463       pg_array_graph_block = graph_block
464       graph_block = proc do |j, lj, js|
465         Sequel.&(orig_graph_block.call(j,lj,js), pg_array_graph_block.call(j, lj, js))
466       end
467     end
468   end
469 
470   opts[:eager_grapher] ||= proc do |eo|
471     ds = eo[:self]
472     ds = ds.graph(eager_graph_dataset(opts, eo), conditions, eo.merge(:select=>select, :join_type=>eo[:join_type]||join_type, :qualify=>:deep), &graph_block)
473     ds
474   end
475 
476   return if opts[:read_only]
477 
478   save_opts = {:validate=>opts[:validate]}
479   save_opts[:raise_on_failure] = opts[:raise_on_save_failure] != false
480 
481   if opts[:save_after_modify]
482     save_after_modify = proc do |obj|
483       obj.save(save_opts)
484     end
485   end
486 
487   opts[:adder] ||= proc do |o|
488     opk = o.get_column_value(opts.primary_key) 
489     if array = get_column_value(key)
490       modified!(key)
491       array << opk
492     else
493       set_column_value("#{key}=", Sequel.pg_array([opk], opts.array_type))
494     end
495     save_after_modify.call(self) if save_after_modify
496   end
497   
498   opts[:remover] ||= proc do |o|
499     if (array = get_column_value(key)) && !array.empty?
500       modified!(key)
501       array.delete(o.get_column_value(opts.primary_key))
502       save_after_modify.call(self) if save_after_modify
503     end
504   end
505 
506   opts[:clearer] ||= proc do
507     if (array = get_column_value(key)) && !array.empty?
508       modified!(key)
509       array.clear
510       save_after_modify.call(self) if save_after_modify
511     end
512   end
513 end