module Protip::Resource

Public Class Methods

new(message_or_attributes = {}) click to toggle source
Calls superclass method
# File lib/protip/resource.rb, line 275
def initialize(message_or_attributes = {})
  if self.class.message == nil
    raise RuntimeError.new('Must define a message class using `resource`')
  end
  if message_or_attributes.is_a?(self.class.message)
    self.message = message_or_attributes
  else
    self.message = self.class.message.new
    assign_attributes message_or_attributes
  end

  super()
end

Public Instance Methods

assign_attributes(attributes) click to toggle source
# File lib/protip/resource.rb, line 289
def assign_attributes(attributes)
  old_attributes = {}
  descriptor = message.class.descriptor
  keys = attributes.keys.map(&:to_s)
  keys.each do |key|
    field = descriptor.lookup(key)
    value = message[key]
    # If the current value is a message, we need to clone it to get a reasonable comparison later,
    # since we might just assign attributes to the current instance of the message directly
    old_attributes[key] = field && field.type == :message && value ? value.clone : value
  end
  @decorator.assign_attributes attributes
  keys.each do |key|
    old_value = old_attributes[key]
    new_value = message[key]
    changed = !(old_value.class == new_value.class && old_value == new_value)

    if changed
      send "#{key}_will_change!"
    end
  end
  nil # return nil to match ActiveRecord behavior
end
attributes() click to toggle source
# File lib/protip/resource.rb, line 356
def attributes
  # Like `.as_json`, but includes nil fields to match ActiveRecord behavior.
  self.class.message.descriptor.map{|field| field.name}.inject({}) do |hash, attribute_name|
    hash[attribute_name] = public_send(attribute_name)
    hash
  end
end
errors() click to toggle source
# File lib/protip/resource.rb, line 364
def errors
  @errors ||= ActiveModel::Errors.new(self)
end
message=(message) click to toggle source
# File lib/protip/resource.rb, line 313
def message=(message)
  @decorator = Protip::Decorator.new(message,
    self.class.transformer, self.class.nested_resources)
end
persisted?() click to toggle source
# File lib/protip/resource.rb, line 352
def persisted?
  id != nil
end
save() click to toggle source
# File lib/protip/resource.rb, line 318
def save
  success = true
  begin
    if persisted?
      # TODO: use `ActiveModel::Dirty` to only send changed attributes?
      update!
    else
      create!
    end
    changes_applied
  rescue Protip::UnprocessableEntityError => error
    success = false
    error.errors.messages.each do |message|
      errors.add :base, message
    end
    error.errors.field_errors.each do |field_error|
      errors.add field_error.field, field_error.message
    end
  end
  success
end
save!() click to toggle source
# File lib/protip/resource.rb, line 343
def save!
  success = save
  if !success
    error_messages = errors.full_messages.join(", ")
    raise RecordInvalid.new("Validation failed: #{error_messages}")
  end
  success
end