require "fmrest/spyke/relation"
require "fmrest/spyke/validation_error"
module FmRest
module Spyke
module Model
module Orm
extend ::ActiveSupport::Concern
included do
class_attribute :default_limit, instance_accessor: false, instance_predicate: false
class_attribute :default_sort, instance_accessor: false, instance_predicate: false
end
class_methods do
delegate :limit, :offset, :sort, :order, :query, :match, :omit,
:portal, :portals, :includes, :with_all_portals, :without_portals,
:script, :find_one, :first, :any, :find_some, :find_in_batches,
:find_each, :and, :or, to: :all
def all
current_scope || Relation.new(self, uri: uri)
end
def fetch(options = {})
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
begin
current_scope.has_query? ? scoped_request(:post) : super()
rescue FmRest::APIError::NoMatchingRecordsError => e
raise e if options[:raise_on_no_matching_records]
::Spyke::Result.new({})
end
ensure
self.current_scope = previous
end
def create!(attributes = {})
new(attributes).tap(&:save!)
end
private
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
end
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
def save!(options = {})
save(options.merge(raise_validation_errors: true))
end
def update!(new_attributes, options = {})
self.attributes = new_attributes
save!(options)
end
def destroy(options = {})
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
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
if ActiveModel::VERSION::MAJOR == 4
def validate!(context = nil)
valid?(context) || raise_validation_error
end
end
private
def perform_save_validations(context, options)
return true if options[:validate] == false
options[:raise_validation_errors] ? validate!(context) : validate(context)
end
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
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
def raise_validation_error raise(ValidationError.new(self))
end
end
end
end
end