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
|
# frozen-string-literal: true
module Sequel
module Plugins
# The split_values plugin splits the values hash retreived from the
# database, and moves keys from the values hash that are not columns
# in the model's dataset to a separate hash. This makes it so the
# values hash only stores columns from the model's dataset.
#
# Among other things, this allows you to save model objects even if
# they were retrieved with additional columns, and have equality
# comparisons with other instances not care about non-column values.
#
# Example:
#
# class Album < Sequel::Model
# plugin :split_values
# end
# a1 = Album[1]
# a2 = Album.select_append(Sequel.as(true, :exists))[1]
# a1.name # => 'Album Name'
# a2.name # => 'Album Name'
# a1[:exists] # => nil
# a2[:exists] # => true
# a1 == a2 # => true
# a2.values # => {:id=>1, :name=>'Album Name'}
# a2.save # Works
#
# Usage:
#
# # Make all model subclass instances split values
# # (called before loading subclasses)
# Sequel::Model.plugin :split_values
#
# # Make the Album class split values
# Album.plugin :split_values
module SplitValues
module ClassMethods
# Split the noncolumn values when creating a new object retrieved from
# the database.
def call(_)
super.split_noncolumn_values
end
end
module InstanceMethods
# If there isn't an entry in the values hash, but there is a noncolumn_values
# hash, look in that hash for the value.
def [](k)
if (res = super).nil?
@noncolumn_values[k] if !@values.has_key?(k) && @noncolumn_values
else
res
end
end
# Check all entries in the values hash. If any of the keys are not columns,
# move the entry into the noncolumn_values hash.
def split_noncolumn_values
cols = (@values.keys - columns)
return self if cols.empty?
nc = @noncolumn_values ||= {}
vals = @values
cols.each{|k| nc[k] = vals.delete(k)}
self
end
end
end
end
end
|