module FmRest::Spyke::Model::Attributes

Extends Spyke models with support for mapped attributes, `ActiveModel::Dirty` and forbidden attributes (e.g. Rails' `params.permit`).

Public Instance Methods

_fmrest_attribute_methods_container() click to toggle source
# File lib/fmrest/spyke/model/attributes.rb, line 92
def _fmrest_attribute_methods_container
  @fmrest_attribute_methods_container ||= Module.new.tap { |mod| include mod }
end
_fmrest_define_attribute(from, to) click to toggle source
# File lib/fmrest/spyke/model/attributes.rb, line 96
def _fmrest_define_attribute(from, to)
  # We use a setter here instead of injecting the hash key/value pair
  # directly with #[]= so that we don't change the mapped_attributes
  # hash on the parent class. The resulting hash is frozen for the
  # same reason.
  self.mapped_attributes = mapped_attributes.merge(from => to).freeze

  _fmrest_attribute_methods_container.module_eval do
    define_method(from) do
      attribute(to)
    end

    define_method(:"#{from}=") do |value|
      send("#{from}_will_change!") unless value == send(from)
      set_attribute(to, value)
    end
  end

  # Define ActiveModel::Dirty's methods
  define_attribute_method(from)
end
attributes(*attrs) click to toggle source

Spyke override

Similar to Spyke::Base.attributes, but allows defining attribute methods that map to FM attributes with different names.

@example

class Person < Spyke::Base
  include FmRest::Spyke::Model

  attributes first_name: "FstName", last_name: "LstName"
end

p = Person.new
p.first_name = "Jojo"
p.attributes # => { "FstName" => "Jojo" }
# File lib/fmrest/spyke/model/attributes.rb, line 59
def attributes(*attrs)
  if attrs.length == 1 && attrs.first.kind_of?(Hash)
    attrs.first.each { |from, to| _fmrest_define_attribute(from, to) }
  else
    attrs.each { |attr| _fmrest_define_attribute(attr, attr) }
  end
end
attributes=(new_attributes) click to toggle source

Spyke override – Adds support for forbidden attributes (i.e. Rails' `params.permit`, etc.)

# File lib/fmrest/spyke/model/attributes.rb, line 128
def attributes=(new_attributes)
  @spyke_attributes ||= ::Spyke::Attributes.new(scope.params)
  return unless new_attributes && !new_attributes.empty?
  use_setters(sanitize_for_mass_assignment(new_attributes))
end
new_or_return(attributes_or_object, *_) click to toggle source

Spyke override (private)

Called whenever loading records from the HTTP API, so we can reset dirty info on freshly loaded records

See: github.com/balvig/spyke/blob/master/lib/spyke/http.rb

Calls superclass method
# File lib/fmrest/spyke/model/attributes.rb, line 76
def new_or_return(attributes_or_object, *_)
  # In case of an existing Spyke object return it as is so that we
  # don't accidentally remove dirty data from associations
  return super if attributes_or_object.is_a?(::Spyke::Base)
  super.tap do |record|
    # In ActiveModel 4.x #clear_changes_information is a private
    # method, so we need to call it with send() in that case, but
    # keep calling it normally for AM5+
    if record.respond_to?(:clear_changes_information)
      record.clear_changes_information
    else
      record.send(:clear_changes_information)
    end
  end
end
reload(*args) click to toggle source

Spyke override – Adds AM::Dirty support

Calls superclass method
# File lib/fmrest/spyke/model/attributes.rb, line 121
def reload(*args)
  super.tap { |r| clear_changes_information }
end

Private Instance Methods

changed_params() click to toggle source
# File lib/fmrest/spyke/model/attributes.rb, line 136
def changed_params
  attributes.to_params.slice(*mapped_changed)
end
changes_applied_after_save() click to toggle source
# File lib/fmrest/spyke/model/attributes.rb, line 152
def changes_applied_after_save
  changes_applied
  portals.each(&:parent_changes_applied)
end
inspect_attributes() click to toggle source

Spyke override (private) – Use known mapped_attributes for inspect

# File lib/fmrest/spyke/model/attributes.rb, line 146
def inspect_attributes
  mapped_attributes.except(primary_key).map do |k, v|
    "#{k}: #{attribute(v).inspect}"
  end.join(', ')
end
mapped_changed() click to toggle source
# File lib/fmrest/spyke/model/attributes.rb, line 140
def mapped_changed
  mapped_attributes.values_at(*changed)
end