/usr/lib/ruby/vendor_ruby/sequel/plugins/association_pks.rb is in ruby-sequel 3.33.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | module Sequel
module Plugins
# The association_pks plugin adds the association_pks and association_pks=
# instance methods to the model class for each association added. These
# methods allow for easily returning the primary keys of the associated
# objects, and easily modifying the associated objects to set the primary
# keys to just the ones given:
#
# Artist.one_to_many :albums
# artist = Artist[1]
# artist.album_pks # [1, 2, 3]
# artist.album_pks = [2, 4]
# artist.album_pks # [2, 4]
#
# Note that it uses the singular form of the association name. Also note
# that the setter both associates to new primary keys not in the assocation
# and disassociates from primary keys not provided to the method.
#
# This plugin makes modifications directly to the underlying tables,
# it does not create or return any model objects, and therefore does
# not call any callbacks. If you have any association callbacks,
# you probably should not use the setter methods.
#
# This plugin only works with singular primary keys, it does not work
# with composite primary keys.
#
# Usage:
#
# # Make all model subclass *_to_many associations have association_pks
# # methods (called before loading subclasses)
# Sequel::Model.plugin :association_pks
#
# # Make the Album *_to_many associations have association_pks
# # methods (called before the association methods)
# Album.plugin :association_pks
module AssociationPks
module ClassMethods
private
# Define a association_pks method using the block for the association reflection
def def_association_pks_getter(opts, &block)
association_module_def(:"#{singularize(opts[:name])}_pks", opts, &block)
end
# Define a association_pks= method using the block for the association reflection,
# if the association is not read only.
def def_association_pks_setter(opts, &block)
association_module_def(:"#{singularize(opts[:name])}_pks=", opts, &block) unless opts[:read_only]
end
# Add a getter that checks the join table for matching records and
# a setter that deletes from or inserts into the join table.
def def_many_to_many(opts)
super
def_association_pks_getter(opts) do
_join_table_dataset(opts).filter(opts[:left_key]=>send(opts[:left_primary_key])).select_map(opts[:right_key])
end
def_association_pks_setter(opts) do |pks|
pks = convert_pk_array(opts, pks)
checked_transaction do
ds = _join_table_dataset(opts).filter(opts[:left_key]=>send(opts[:left_primary_key]))
ds.exclude(opts[:right_key]=>pks).delete
pks -= ds.select_map(opts[:right_key])
pks.each{|pk| ds.insert(opts[:left_key]=>send(opts[:left_primary_key]), opts[:right_key]=>pk)}
end
end
end
# Add a getter that checks the association dataset and a setter
# that updates the associated table.
def def_one_to_many(opts)
super
return if opts[:type] == :one_to_one
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|
pks = convert_pk_array(opts, pks)
checked_transaction do
ds = send(opts.dataset_method)
primary_key = opts.associated_class.primary_key
key = opts[:key]
ds.unfiltered.filter(primary_key=>pks).update(key=>pk)
ds.exclude(primary_key=>pks).update(key=>nil)
end
end
end
end
module InstanceMethods
private
# If the associated class's primary key column type is integer,
# typecast all provided values to integer before using them.
def convert_pk_array(opts, pks)
if klass = opts.associated_class and sch = klass.db_schema and col = sch[klass.primary_key] and col[:type] == :integer
pks.map{|pk| model.db.typecast_value(:integer, pk)}
else
pks
end
end
end
end
end
end
|