Class: Pedanco::Diffr::ChangeSet

Inherits:
Object
  • Object
show all
Defined in:
lib/pedanco/diffr/change_set.rb

Overview

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

Instance Method Summary collapse

Constructor Details

#initialize(change_hash = {}) ⇒ ChangeSet

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.

Parameters:

  • change_hash (Hash) (defaults to: {})

    (optional) hash to be converted into a ChangeSet.



33
34
35
# File 'lib/pedanco/diffr/change_set.rb', line 33

def initialize(change_hash = {})
  @changes = parse_change_hash(change_hash)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object

Override to catch ‘_changed?` postfix convenience calls to determine if a property has changed.



41
42
43
44
45
46
47
# 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

Instance Method Details

#add_change(name, current_value, previous_value = nil) ⇒ Change

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

Parameters:

  • name (String, Symbol)

    The name of the value that has changed

  • current_value (anything)

    The current value

  • previous_value (anything) (defaults to: nil)

    (optional) The previous value, the default is nil

Returns:

  • (Change)

    Returns the generated change



78
79
80
81
82
83
# 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

#changed?(keys, match_type = :any) ⇒ Boolean

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

Parameters:

  • keys (String, Symbol, Array)

    Defines a single or list of names to validate existence of.

  • match_type (Symbol) (defaults to: :any)

    (optional) Defines how a check is made, default is :any also accepts :all

Returns:

  • (Boolean)

    True if matches found, false if not.



128
129
130
131
132
133
134
135
# 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

#get_change(name) ⇒ Change

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)

Parameters:

  • name (String, Symbol)

    The name of the change to lookup.

Returns:

  • (Change)

    The Change object by name, an empty change is returned if not found.



152
153
154
# File 'lib/pedanco/diffr/change_set.rb', line 152

def get_change(name)
  @changes.fetch(name.to_sym, Change.new(name.to_sym))
end

#parse_changes(changes) ⇒ Object

Parses the ActiveModel::Dirty syntax to build a changeset. The Dirty syntax is:

{ 'property_name' => [old_value, new_value] }

Parameters:

  • changes (Hash)

    An ActiveModel::Dirty changes hash



193
194
195
# 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

#remove_change(name) ⇒ Change

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

Parameters:

  • name (String, Symbol)

    The name of the change to remove.

Returns:

  • (Change)

    The removed change, nil if no change by that name was found



99
100
101
# File 'lib/pedanco/diffr/change_set.rb', line 99

def remove_change(name)
  @changes.delete(name.to_sym)
end

#respond_to?(name, include_private = false) ⇒ Boolean

Implementation to support respond_to? lookup for ‘_changed?` postfix convenience calls.

Returns:

  • (Boolean)

    true if class responds to the requested method name



55
56
57
58
59
60
61
# 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

#to_a(name = nil) ⇒ Array

Finds and returns a ChangeSet as an array, used for legacy rendering that expects changes to be in [current, previous] format.

Parameters:

  • name (String, Symbol) (defaults to: nil)

    (optional) The name of the change

Returns:

  • (Array)

    The Change as an array or empty if no change is found.



163
164
165
166
167
168
169
170
# 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

#to_hashHash

Converts the Change Set into an Hash.

{
  name: [current, previous]
}

Returns:

  • (Hash)

    The Change Set as an hash.



181
182
183
# File 'lib/pedanco/diffr/change_set.rb', line 181

def to_hash
  Hash[@changes.map { |k, v| [k, v.to_a] }]
end