app/api/locomotive/api/helpers/persistence_helper.rb
module Locomotive
module API
module Helpers
# Sets up model/repository methods.
# @example
#
# def translation_params
# permitted_params[:translation]
# end
#
# def auth(meth)
# authorize Translation, meth
# end
#
# def translations
# current_site.translations
# end
#
# def translation
# @translation ||= translations.find(params[:id])
# end
#
module PersistenceHelper
attr_accessor :resource_name, :use_form_object
def setup_resource_methods_for(resource_name)
self.resource_name = resource_name.to_s
setup_plural_method
setup_singular_getter_method
setup_singular_setter_method
setup_params_method
setup_object_auth_method
end
# @return [Class] a class constant for the matching form class.
def form_klass
namespaced_klass("#{singular}_form")
end
# @param [Object] the object to send to the policy class. Leave empty for
# the singular (default) object to be sent.
# @return [Class] a class constant for the current Pundit policy on the object.
def current_policy(obj = nil)
obj = obj ? obj : send(singular)
policy_klass.new(pundit_user, obj)
end
# @param [Object] an object that responds to #serializable_hash is fed into
# the persistence class and save is called.
# @note if the object exists it will be updated
def persist_from_form(form_object)
send(singular).assign_attributes(form_object.serializable_hash)
send(singular).save!
end
def auth(meth)
authorize persistence_klass, meth
end
private
def policy_klass
namespaced_klass("#{singular}_policy")
end
def persistence_klass
# Change unscoped class to whatever repository/persistence class needed.
namespaced_klass(singular)
end
def namespaced_klass(klass_name)
un_namespaced_klass = klass_name.classify
if un_namespaced_klass.ends_with?('Form')
"Locomotive::API::Forms::#{un_namespaced_klass}"
else
"Locomotive::#{un_namespaced_klass}"
end.constantize
end
def use_form_object?
use_form_object
end
def singular
@singular ||= plural.singularize
end
def plural
@plural ||= resource_name
end
def setup_params_method
self.class.send(:define_method, "#{singular}_params") do
permitted_params[singular.to_sym]
end
end
# Authenticate an action against an instance
def setup_object_auth_method
self.class.send(:define_method, :object_auth) do |meth|
authorize send(singular), meth
end
end
def setup_plural_method
# is it already defined by the resource itself?
return if self.respond_to?(plural)
self.class.send(:define_method, plural) do
current_site.send(plural)
end
end
def setup_singular_getter_method
self.class.send(:define_method, singular) do
instance_variable = "@#{singular}"
if instance_variable_defined?(instance_variable)
instance_variable_get(instance_variable)
else
if params[:id]
instance_variable_set(instance_variable, send(plural).find(params[:id]))
else
instance_variable_set(instance_variable, send(plural).new)
end
end
end
end
def setup_singular_setter_method
self.class.send(:define_method, "#{singular}=") do |var|
instance_variable_set("@#{singular}", var)
end
end
end
end
end
end