module Sequel::Plugins::AssociationPks::ClassMethods

Private Instance Methods

def_association_pks_getter(opts, &block) click to toggle source

Define a association_pks method using the block for the association reflection

# File lib/sequel/plugins/association_pks.rb, line 38
def def_association_pks_getter(opts, &block)
  association_module_def(:"#{singularize(opts[:name])}_pks", opts, &block)
end
def_association_pks_setter(opts, &block) click to toggle source

Define a association_pks= method using the block for the association reflection, if the association is not read only.

# File lib/sequel/plugins/association_pks.rb, line 44
def def_association_pks_setter(opts, &block)
  association_module_def(:"#{singularize(opts[:name])}_pks=", opts, &block) 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 50
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 ever 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)

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

  def_association_pks_setter(opts) do |pks|
    pks = send(crk ? :convert_cpk_array : :convert_pk_array, opts, pks)
    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).filter(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_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 96
def def_one_to_many(opts)
  super
  return if opts[:type] == :one_to_one

  key = opts[:key]

  def_association_pks_getter(opts) do
    send(opts.dataset_method).select_map(opts.associated_class.primary_key)
  end

  def_association_pks_setter(opts) do |pks|
    primary_key = opts.associated_class.primary_key

    pks = if primary_key.is_a?(Array)
      convert_cpk_array(opts, pks)
    else
      convert_pk_array(opts, pks)
    end

    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.filter(pkh).update(h)
      ds.exclude(pkh).update(nh)
    end
  end
end