module Sequel::Plugins::AssociationPks::ClassMethods

Private Instance Methods

def_association_pks_methods(opts) click to toggle source

Define a association_pks method using the block for the association reflection

# File lib/sequel/plugins/association_pks.rb, line 58
def def_association_pks_methods(opts)
  association_module_def(:"#{singularize(opts[:name])}_pks", opts){_association_pks_getter(opts)}
  association_module_def(:"#{singularize(opts[:name])}_pks=", opts){|pks| _association_pks_setter(opts, pks)} unless opts[:read_only]
end
def_many_to_many(opts) click to toggle source

Add a getter that checks the join table for matching records and a setter that deletes from or inserts into the join table.

Calls superclass method
# File lib/sequel/plugins/association_pks.rb, line 65
def def_many_to_many(opts)
  super

  return if opts[:type] == :one_through_one

  # Grab values from the reflection so that the hash lookup only needs to be
  # done once instead of inside every method call.
  lk, lpk, rk = opts.values_at(:left_key, :left_primary_key, :right_key)
  clpk = lpk.is_a?(Array)
  crk = rk.is_a?(Array)

  opts[:pks_getter] = if clpk
    lambda do
      h = {}
      lk.zip(lpk).each{|k, pk| h[k] = get_column_value(pk)}
      _join_table_dataset(opts).where(h).select_map(rk)
    end
  else
    lambda do
      _join_table_dataset(opts).where(lk=>get_column_value(lpk)).select_map(rk)
    end
  end

  opts[:pks_setter] = lambda do |pks|
    if pks.empty?
      send(opts.remove_all_method)
    else
      checked_transaction do
        if clpk
          lpkv = lpk.map{|k| get_column_value(k)}
          cond = lk.zip(lpkv)
        else
          lpkv = get_column_value(lpk)
          cond = {lk=>lpkv}
        end
        ds = _join_table_dataset(opts).where(cond)
        ds.exclude(rk=>pks).delete
        pks -= ds.select_map(rk)
        lpkv = Array(lpkv)
        key_array = crk ? pks.map{|pk| lpkv + pk} : pks.map{|pk| lpkv + [pk]}
        key_columns = Array(lk) + Array(rk)
        ds.import(key_columns, key_array)
      end
    end
  end

  def_association_pks_methods(opts)
end
def_one_to_many(opts) click to toggle source

Add a getter that checks the association dataset and a setter that updates the associated table.

Calls superclass method
# File lib/sequel/plugins/association_pks.rb, line 116
def def_one_to_many(opts)
  super

  return if opts[:type] == :one_to_one

  key = opts[:key]

  opts[:pks_getter] = lambda do
    send(opts.dataset_method).select_map(opts.associated_class.primary_key)
  end

  opts[:pks_setter] = lambda do |pks|
    if pks.empty?
      send(opts.remove_all_method)
    else
      primary_key = opts.associated_class.primary_key
      pkh = {primary_key=>pks}

      if key.is_a?(Array)
        h = {}
        nh = {}
        key.zip(pk).each do|k, v|
          h[k] = v
          nh[k] = nil
        end
      else
        h = {key=>pk}
        nh = {key=>nil}
      end

      checked_transaction do
        ds = send(opts.dataset_method)
        ds.unfiltered.where(pkh).update(h)
        ds.exclude(pkh).update(nh)
      end
    end
  end

  def_association_pks_methods(opts)
end