lib/rom/repository/changeset/update.rb
require 'rom/repository/changeset/restricted'
module ROM
class Changeset
# Changeset specialization for update commands
#
# Update changesets will only execute their commands when
# the data is different from the original tuple. Original tuple
# is fetched from changeset's relation using `by_pk` relation view.
# This means the underlying adapter must provide this view, or you
# you need to implement it yourself in your relations if you want to
# use Update changesets.
#
# @see Changeset::Stateful
#
# @api public
class Update < Stateful
include Restricted
command_type :update
# Commit update changeset if there's a diff
#
# This returns original tuple if there's no diff
#
# @return [Hash]
#
# @see Changeset#commit
#
# @api public
def commit
diff? ? super : original
end
# Return original tuple that this changeset may update
#
# @return [Hash]
#
# @api public
def original
@original ||= Hash(relation.one)
end
# Return true if there's a diff between original and changeset data
#
# @return [TrueClass, FalseClass]
#
# @api public
def diff?
! diff.empty?
end
# Return if there's no diff between the original and changeset data
#
# @return [TrueClass, FalseClass]
#
# @api public
def clean?
diff.empty?
end
# Calculate the diff between the original and changeset data
#
# @return [Hash]
#
# @api public
def diff
@diff ||=
begin
data = pipe.for_diff(__data__)
data_tuple = data.to_a
data_keys = data.keys & original.keys
new_tuple = data_tuple.to_a.select { |(k, _)| data_keys.include?(k) }
ori_tuple = original.to_a.select { |(k, _)| data_keys.include?(k) }
Hash[new_tuple - (new_tuple & ori_tuple)]
end
end
end
end
end