Repository URL to install this package:
|
Version:
0.8.0 ▾
|
module JSONAPI
class OperationsProcessor
include Callbacks
define_jsonapi_resources_callbacks :operation,
:operations,
:find_operation,
:show_operation,
:show_relationship_operation,
:show_related_resource_operation,
:show_related_resources_operation,
:create_resource_operation,
:remove_resource_operation,
:replace_fields_operation,
:replace_to_one_relationship_operation,
:replace_polymorphic_to_one_relationship_operation,
:create_to_many_relationship_operation,
:replace_to_many_relationship_operation,
:remove_to_many_relationship_operation,
:remove_to_one_relationship_operation
class << self
def operations_processor_for(operations_processor)
operations_processor_class_name = "#{operations_processor.to_s.camelize}OperationsProcessor"
operations_processor_class_name.safe_constantize
end
end
def process(request)
@results = JSONAPI::OperationResults.new
@request = request
@operations = request.operations
# Use transactions if more than one operation and if one of the operations can be transactional
# Even if transactional transactions won't be used unless the derived OperationsProcessor supports them.
@transactional = false
@operations.each do |operation|
@transactional |= operation.transactional
end
run_callbacks :operations do
transaction do
# Links and meta data global to the set of operations
@operations_meta = {}
@operations_links = {}
@operations.each do |operation|
@operation = operation
# Links and meta data for each operation
@operation_meta = {}
@operation_links = {}
run_callbacks :operation do
@result = nil
run_callbacks @operation.class.name.demodulize.underscore.to_sym do
@result = process_operation(@operation)
end
@result.meta.merge!(@operation_meta)
@result.links.merge!(@operation_links)
@results.add_result(@result)
rollback if @results.has_errors?
end
end
@results.meta = @operations_meta
@results.links = @operations_links
end
end
@results
end
private
# The base OperationsProcessor provides no transaction support
# Override the transaction and rollback methods to provide transaction support.
# For ActiveRecord transactions you can use the ActiveRecordOperationsProcessor
def transaction
yield
end
def rollback
end
# If overriding in child operation processors, call operation.apply and
# catch errors that should be handled before JSONAPI::Exceptions::Error
# and other unprocessed exceptions
def process_operation(operation)
with_default_handling do
operation.apply
end
end
def with_default_handling(&block)
yield
rescue JSONAPI::Exceptions::Error => e
raise e
rescue => e
if JSONAPI.configuration.exception_class_whitelisted?(e)
raise e
else
@request.server_error_callbacks.each { |callback| safe_run_callback(callback, e) }
internal_server_error = JSONAPI::Exceptions::InternalServerError.new(e)
Rails.logger.error { "Internal Server Error: #{e.message} #{e.backtrace.join("\n")}" }
return JSONAPI::ErrorsOperationResult.new(internal_server_error.errors[0].code, internal_server_error.errors)
end
end
def safe_run_callback(callback, error)
begin
callback.call(error)
rescue => e
Rails.logger.error { "Error in error handling callback: #{e.message} #{e.backtrace.join("\n")}" }
internal_server_error = JSONAPI::Exceptions::InternalServerError.new(e)
return JSONAPI::ErrorsOperationResult.new(internal_server_error.errors[0].code, internal_server_error.errors)
end
end
end
end
class BasicOperationsProcessor < JSONAPI::OperationsProcessor
end