module FmRest::Spyke::Model::Orm

This module adds and extends various ORM features in Spyke models, including custom query methods, remote script execution and exception-raising persistence methods.

Public Instance Methods

all() click to toggle source

Spyke override – Use FmRest's Relation instead of Spyke's vanilla one

# File lib/fmrest/spyke/model/orm.rb, line 37
def all
  current_scope || Relation.new(self, uri: uri)
end
create!(attributes = {}) click to toggle source

Exception-raising version of `#create`

@param attributes [Hash] the attributes to initialize the

record with
# File lib/fmrest/spyke/model/orm.rb, line 77
def create!(attributes = {})
  new(attributes).tap(&:save!)
end
destroy(options = {}) click to toggle source

Spyke override – Adds support for Data API script execution.

@option options [String] :script the name of a FileMaker script to execute

upon deletion
# File lib/fmrest/spyke/model/orm.rb, line 179
def destroy(options = {})
  # For whatever reason the Data API wants the script params as query
  # string params for DELETE requests, making this more complicated
  # than it should be
  script_query_string = if options.has_key?(:script)
                          "?" + Faraday::Utils.build_query(FmRest::V1.convert_script_params(options[:script]))
                        else
                          ""
                        end

  self.attributes = delete(uri.to_s + script_query_string)
end
execute_script(script_name, param: nil) click to toggle source

Requests execution of a FileMaker script.

@param script_name [String] the name of the FileMaker script to

execute

@param param [String] an optional paramater for the script

# File lib/fmrest/spyke/model/orm.rb, line 87
def execute_script(script_name, param: nil)
  params = {}
  params = {"script.param" => param} unless param.nil?
  request(:get, FmRest::V1::script_path(layout, script_name), params)
end
extend_scope_with_fm_params(scope, prefixed: false) click to toggle source
# File lib/fmrest/spyke/model/orm.rb, line 95
def extend_scope_with_fm_params(scope, prefixed: false)
  prefix = prefixed ? "_" : nil

  where_options = {}

  where_options["#{prefix}limit"] = scope.limit_value if scope.limit_value
  where_options["#{prefix}offset"] = scope.offset_value if scope.offset_value

  if scope.sort_params.present?
    where_options["#{prefix}sort"] =
      prefixed ? scope.sort_params.to_json : scope.sort_params
  end

  unless scope.included_portals.nil?
    where_options["portal"] =
      prefixed ? scope.included_portals.to_json : scope.included_portals
  end

  if scope.portal_params.present?
    scope.portal_params.each do |portal_param, value|
      where_options["#{prefix}#{portal_param}"] = value
    end
  end

  if scope.script_params.present?
    where_options.merge!(scope.script_params)
  end

  scope.where(where_options)
end
fetch() click to toggle source

Spyke override – allows properly setting limit, offset and other options, as well as using the appropriate HTTP method/URL depending on whether there's a query present in the current scope.

@example

Person.query(first_name: "Stefan").fetch # -> POST .../_find
Calls superclass method
# File lib/fmrest/spyke/model/orm.rb, line 48
def fetch
  if current_scope.has_query?
    scope = extend_scope_with_fm_params(current_scope, prefixed: false)
    scope = scope.where(query: scope.query_params)
    scope = scope.with(FmRest::V1::find_path(layout))
  else
    scope = extend_scope_with_fm_params(current_scope, prefixed: true)
  end

  previous, self.current_scope = current_scope, scope

  # The DAPI returns a 401 "No records match the request" error when
  # nothing matches a _find request, so we need to catch it in order
  # to provide sane behavior (i.e. return an empty resultset)
  begin
    current_scope.has_query? ? scoped_request(:post) : super
  rescue FmRest::APIError::NoMatchingRecordsError => e
    raise e if raise_on_no_matching_records
    ::Spyke::Result.new({})
  end
ensure
  self.current_scope = previous
end
reload(options = {}) click to toggle source

(see destroy)

@option (see destroy)

# File lib/fmrest/spyke/model/orm.rb, line 196
def reload(options = {})
  scope = self.class
  scope = scope.script(options[:script]) if options.has_key?(:script)
  reloaded = scope.find(__record_id)
  self.attributes = reloaded.attributes
  self.__mod_id = reloaded.mod_id
end
save(options = {}) click to toggle source

Spyke override – Adds a number of features to original `#save`:

  • Validations

  • Data API scripts execution

  • Refresh of dirty attributes

@option options [String] :script the name of a FileMaker script to execute

upon saving

@option options [Boolean] :raise_validation_errors whether to raise an

exception if validations fail

@return [true] if saved successfully @return [false] if validations or persistence failed

# File lib/fmrest/spyke/model/orm.rb, line 141
def save(options = {})
  callback = persisted? ? :update : :create

  return false unless perform_save_validations(callback, options)
  return false unless perform_save_persistence(callback, options)

  true
end
save!(options = {}) click to toggle source

Exception-raising version of `#save`.

@option (see save)

@return [true] if saved successfully

@raise if validations or presistence failed

# File lib/fmrest/spyke/model/orm.rb, line 158
def save!(options = {})
  save(options.merge(raise_validation_errors: true))
end
update!(new_attributes, options = {}) click to toggle source

Exception-raising version of `#update`.

@param new_attributes [Hash] a hash of record attributes to update

the record with

@option (see save)

# File lib/fmrest/spyke/model/orm.rb, line 169
def update!(new_attributes, options = {})
  self.attributes = new_attributes
  save!(options)
end
validate!(context = nil) click to toggle source
# File lib/fmrest/spyke/model/orm.rb, line 207
def validate!(context = nil)
  valid?(context) || raise_validation_error
end

Private Instance Methods

build_params_for_save(options) click to toggle source
# File lib/fmrest/spyke/model/orm.rb, line 240
def build_params_for_save(options)
  to_params.tap do |params|
    if options.has_key?(:script)
      params.merge!(FmRest::V1.convert_script_params(options[:script]))
    end
  end
end
perform_save_persistence(callback, options) click to toggle source
# File lib/fmrest/spyke/model/orm.rb, line 219
def perform_save_persistence(callback, options)
  run_callbacks :save do
    run_callbacks(callback) do

      begin
        send self.class.method_for(callback), build_params_for_save(options)

      rescue APIError::ValidationError => e
        if options[:raise_validation_errors]
          raise e
        else
          return false
        end
      end

    end
  end

  true
end
perform_save_validations(context, options) click to toggle source
# File lib/fmrest/spyke/model/orm.rb, line 214
def perform_save_validations(context, options)
  return true if options[:validate] == false
  options[:raise_validation_errors] ? validate!(context) : validate(context)
end
raise_validation_error() click to toggle source

Overwrite ActiveModel's raise_validation_error to use our own class

# File lib/fmrest/spyke/model/orm.rb, line 250
def raise_validation_error # :doc:
  raise(ValidationError.new(self))
end