module ArSync::ApiControllerConcern

Public Instance Methods

graphql_call() click to toggle source
# File lib/ar_sync/rails.rb, line 59
def graphql_call
  render json: ArSerializer::GraphQL.serialize(
    schema,
    params[:query],
    operation_name: params[:operationName],
    variables: (params[:variables] || {}).as_json,
    context: current_user
  )
rescue StandardError => e
  render json: { error: handle_exception(e) }
end
graphql_schema() click to toggle source
# File lib/ar_sync/rails.rb, line 55
def graphql_schema
  render plain: ArSerializer::GraphQL.definition(schema.class)
end
schema() click to toggle source
# File lib/ar_sync/rails.rb, line 45
def schema
  raise 'you must implement method `schema`'
end
static_call() click to toggle source
# File lib/ar_sync/rails.rb, line 71
def static_call
  _api_call :static do |model, current_user, query|
    case model
    when ArSync::Collection, ActiveRecord::Relation, Array
      ArSerializer.serialize model.to_a, query, context: current_user
    when ArSerializer::Serializable
      ArSerializer.serialize model, query, context: current_user
    else
      model
    end
  end
end
sync_call() click to toggle source
# File lib/ar_sync/rails.rb, line 49
def sync_call
  _api_call :sync do |model, current_user, query|
    ArSync.sync_serialize model, current_user, query
  end
end

Private Instance Methods

_api_call(type) { |model, current_user, as_json| ... } click to toggle source
# File lib/ar_sync/rails.rb, line 86
def _api_call(type)
  if respond_to?(ArSync.config.current_user_method)
    current_user = send ArSync.config.current_user_method
  end
  responses = params[:requests].map do |request|
    begin
      api_name = request[:api]
      sch = schema
      info = sch.class._serializer_field_info api_name
      raise ArSync::ApiNotFound, "#{type.to_s.capitalize} API named `#{api_name}` not configured" unless info
      api_params = (request[:params].as_json || {}).transform_keys(&:to_sym)
      model = sch.instance_exec(current_user, api_params, &info.data_block)
      { data: yield(model, current_user, request[:query].as_json) }
    rescue StandardError => e
      { error: handle_exception(e) }
    end
  end
  render json: responses
end
exception_trace(exception) click to toggle source
# File lib/ar_sync/rails.rb, line 114
def exception_trace(exception)
  backtrace_cleaner = request.get_header 'action_dispatch.backtrace_cleaner'
  wrapper = ActionDispatch::ExceptionWrapper.new backtrace_cleaner, exception
  trace = wrapper.application_trace
  trace.empty? ? wrapper.framework_trace : trace
end
handle_exception(exception) click to toggle source
# File lib/ar_sync/rails.rb, line 131
def handle_exception(exception)
  log_internal_exception exception
  backtrace = exception_trace exception unless ::Rails.env.production?
  case exception
  when ArSerializer::InvalidQuery, ArSync::ApiNotFound, ArSerializer::GraphQL::Parser::ParseError
    { type: 'Bad Request', message: exception.message, backtrace: backtrace }
  when ActiveRecord::RecordNotFound
    message = exception.message unless ::Rails.env.production?
    { type: 'Record Not Found', message: message.to_s, backtrace: backtrace }
  else
    message = "#{exception.class} (#{exception.message})" unless ::Rails.env.production?
    { type: 'Internal Server Error', message: message.to_s, backtrace: backtrace }
  end
end
log_internal_exception(exception) click to toggle source
# File lib/ar_sync/rails.rb, line 121
def log_internal_exception(exception)
  ActiveSupport::Deprecation.silence do
    logger.fatal '  '
    logger.fatal "#{exception.class} (#{exception.message}):"
    log_internal_exception_trace exception.annoted_source_code if exception.respond_to?(:annoted_source_code)
    logger.fatal '  '
    log_internal_exception_trace exception_trace(exception)
  end
end
log_internal_exception_trace(trace) click to toggle source
# File lib/ar_sync/rails.rb, line 106
def log_internal_exception_trace(trace)
  if logger.formatter&.respond_to? :tags_text
    logger.fatal trace.join("\n#{logger.formatter.tags_text}")
  else
    logger.fatal trace.join("\n")
  end
end