class Unpoly::Rails::Change::Context

Attributes

changes[R]
input[R]
unmutated_input[R]

Public Class Methods

new(input, changes) click to toggle source
# File lib/unpoly/rails/change/context.rb, line 6
def initialize(input, changes)
  # Response headers will only include changed keys
  @changes = ensure_indifferent_access(changes)

  # Keep a structure-cloned copy of the input hash, so we can
  # detect changes of sub-keys and sub-arrays in #finalize_changes.
  @input = ensure_indifferent_access(input)
  @unmutated_input = input.deep_dup
end

Public Instance Methods

[](key) click to toggle source
# File lib/unpoly/rails/change/context.rb, line 16
def [](key)
  if changes.key?(key)
    changes[key]
  else
    input[key]
  end
end
[]=(key, value) click to toggle source

Although we have mutation tracking in finalize_changes, we're still tracking direct changes in []=. We don't want to force user code know whether to use up.context[]= or up.fail_context[]=. Changes in either will be pushed to the client in the X-Up-Context header.

# File lib/unpoly/rails/change/context.rb, line 32
def []=(key, value)
  # No need to persist it through redirects (via params) anymore.
  input.delete(key)
  changes[key] = value
end
delete(key) click to toggle source
# File lib/unpoly/rails/change/context.rb, line 24
def delete(key)
  self[key] = nil
end
finalize_changes() click to toggle source
# File lib/unpoly/rails/change/context.rb, line 54
def finalize_changes
  unmutated_input.each do |key, unmutated_value|
    if input.key?(key) && !changes.key?(key)
      input_value = input[key]
      if unmutated_value != input_value
        self[key] = input_value
      end
    end
  end
end
replace(new_hash) click to toggle source
# File lib/unpoly/rails/change/context.rb, line 42
def replace(new_hash)
  new_hash = new_hash.stringify_keys
  # The frontend merges X-Up-Context updates.
  # Hence we must nilify every key that no longer exists in the
  # replaced hash.
  deleted_keys = (input.keys | changes.keys) - new_hash.keys
  changes.replace(new_hash)
  deleted_keys.each { |deleted_key| changes[deleted_key] = nil }
  input.clear
  unmutated_input.clear
end
to_h() click to toggle source
# File lib/unpoly/rails/change/context.rb, line 38
def to_h
  input.merge(changes)
end

Private Instance Methods

ensure_indifferent_access(hash) click to toggle source
# File lib/unpoly/rails/change/context.rb, line 69
def ensure_indifferent_access(hash)
  if hash.is_a?(ActiveSupport::HashWithIndifferentAccess)
    hash
  else
    raise Error, "Constructor args must be an ActiveSupport::HashWithIndifferentaccess"
  end
end