class Pedanco::Diffr::ChangeSet
A ChangeSet
contains a one or more changes. Change
data can be passed during `new()` or can be added/removed directly from the change instance.
When a change is added, the ChangeSet
provides both a direct method to look up a change or a convience method with a `_changed?` prefix.
inst = Pedanco::Diffr::ChangeSet.new inst.add_change(:age, 40, 39) inst.age_changed? # true inst.changed?(:age) # true
When creating a ChangeSet
you can also pass in ActiveModel::Dirty syntax to the `parse_changes()` method to convert the data into a ChangeSet
.
@author [jpolanco]
Public Class Methods
Initializes the Change
instance. Allows for a hash of array pairs, ex:
{ name: ['Bob', 'Tom'], age: [33, 32] }
which represents a change set to be parsed in on creation.
@param change_hash [Hash]
(optional) hash to be converted into a ChangeSet.
# File lib/pedanco/diffr/change_set.rb, line 33 def initialize(change_hash = {}) @changes = parse_change_hash(change_hash) end
Public Instance Methods
Adds a change to the change set. This method converts the arguments into a Change
object internally.
inst = Pedanco::Diffr::ChangeSet.new inst.add_change(:age, 40, 39) inst.age_changed? # true
@param name [String,Symbol] The name of the value that has changed @param current_value [anything] The current value @param previous_value [anything] (optional) The previous value,
the default is nil
@return [Change] Returns the generated change
# File lib/pedanco/diffr/change_set.rb, line 78 def add_change(name, current_value, previous_value = nil) sym = name.to_sym @changes[sym] = Change.new(sym, current_value, previous_value) @changes[sym] end
Determines if the provided change(s) exist in the change set. When the match type is set to `:any`, if any key matches at least one change the method returns false.
inst = Pedanco::Diffr::ChangeSet.new inst.add_change(:age, 40, 39) inst.add_change(:name, 'George', 'Frank') inst.changed?([:foo, :age]) # true
If the match type is :all, all matches must exist.
inst = Pedanco::Diffr::ChangeSet.new inst.add_change(:age, 40, 39) inst.add_change(:name, 'George', 'Frank') inst.changed?([:foo, :age], :all) # false
@param keys [String,Symbol,Array] Defines a single or list
of names to validate existence of.
@param match_type [Symbol] (optional) Defines how a check is
made, default is :any also accepts :all
@return [Boolean] True if matches found, false if not.
# File lib/pedanco/diffr/change_set.rb, line 128 def changed?(keys, match_type = :any) keys = Array.wrap(keys).map(&:to_sym) if match_type == :all (keys & @changes.keys).length == keys.length else (keys & @changes.keys).present? end end
Looks up a change by name and returns it if found. If the change is not found an empty Change
instance is returned. This prevents having to check for nil.
inst = Pedanco::Diffr::ChangeSet.new inst.add_change(:age, 40, 39) # returns Pedanco::Diffr::Change(:age, current: 40, previous: 39) inst.get_change(:age)
@param name [String,Symbol] The name of the change to lookup.
@return [Change] The Change
object by name,
an empty change is returned if not found.
# File lib/pedanco/diffr/change_set.rb, line 152 def get_change(name) @changes.fetch(name.to_sym, Change.new(name.to_sym)) end
Override to catch `_changed?` postfix convenience calls to determine if a property has changed.
# File lib/pedanco/diffr/change_set.rb, line 41 def method_missing(name, *args, &block) if name.to_s =~ /_changed\?/ @changes.key?(name.to_s.gsub(/_changed\?/, '').to_sym) else super end end
Parses the ActiveModel::Dirty syntax to build a changeset. The Dirty syntax is:
{ 'property_name' => [old_value, new_value] }
@param changes [Hash] An ActiveModel::Dirty changes hash
# File lib/pedanco/diffr/change_set.rb, line 193 def parse_changes(changes) changes.each { |name, change| add_change(name, change[1], change[0]) } end
Removes an existing change by the name of the change. This method is safe to call if a change is not found.
inst = Pedanco::Diffr::ChangeSet.new inst.add_change(:age, 40, 39) inst.age_changed? # true inst.remove_change(:age) # true
@param name [String,Symbol] The name of the change to remove.
@return [Change] The removed change,
nil if no change by that name was found
# File lib/pedanco/diffr/change_set.rb, line 99 def remove_change(name) @changes.delete(name.to_sym) end
Implementation to support respond_to? lookup for `_changed?` postfix convenience calls.
@return [Boolean] true if class responds to the requested
method name
# File lib/pedanco/diffr/change_set.rb, line 55 def respond_to?(name, include_private = false) if name.to_s =~ /_changed\?/ true else super end end
Finds and returns a ChangeSet
as an array, used for legacy rendering that expects changes to be in [current, previous] format.
@param name [String,Symbol] (optional) The name of the change
@return [Array] The Change
as an array or empty if no change is found.
# File lib/pedanco/diffr/change_set.rb, line 163 def to_a(name = nil) if name.present? change = @changes[name.to_sym] change.present? ? change.to_a : [] else @changes.map { |k, v| [k, v.to_a] } end end
Private Instance Methods
# File lib/pedanco/diffr/change_set.rb, line 199 def parse_change_hash(hash) hash_array = hash.map do |k, v| name = k.to_sym value = Array.wrap(v) [name, Change.new(name, value[0], value[1])] end Hash[hash_array] end