module OpenStax::Api::Roar

Public Instance Methods

render_api_errors(errors, status = :unprocessable_entity) click to toggle source
# File lib/openstax/api/roar.rb, line 149
def render_api_errors(errors, status = :unprocessable_entity)
  return if errors.blank?

  hash = { status: Rack::Utils.status_code(status) }

  case errors
  when ActiveModel::Errors
    hash[:errors] = errors.map do |error|
      attribute = error.attribute
      message = error.message

      {
        code: "#{attribute.to_s}_#{message.to_s.gsub(/[\s-]/, '_').gsub(/[^\w]/, '')}",
        message: errors.full_message(attribute, message)
      }
    end
  when Lev::Errors
    hash[:errors] = errors.map do |error|
      { code: error.code, message: error.message, data: error.data }
    end
  else
    hash[:errors] = [errors].flatten.map do |error|
      error.is_a?(Hash) ? error :
                          { code: error.to_s.underscore, message: error.to_s.humanize }
    end
  end

  render json: hash, status: status
end
standard_create(model, represent_with=nil, options={}) { |model| ... } click to toggle source
# File lib/openstax/api/roar.rb, line 45
def standard_create(model, represent_with=nil, options={})
  represent_with_options = { user_options: options, represent_with: represent_with }

  model.class.transaction do
    consume!(model, represent_with_options.dup)
    yield model if block_given?
    OSU::AccessPolicy.require_action_allowed!(:create, current_api_user, model)

    if model.save
      respond_with model, { status: :created, location: nil }.merge(represent_with_options)
    else
      render_api_errors(model.errors)
    end
  end
end
standard_destroy(model, represent_with=nil, options={}) { |model| ... } click to toggle source
# File lib/openstax/api/roar.rb, line 99
def standard_destroy(model, represent_with=nil, options={})
  OSU::AccessPolicy.require_action_allowed!(:destroy, current_api_user, model)

  return render_api_errors(code: "#{model.model_name.element}_is_already_deleted",
                           message: "#{model.model_name.human} is already deleted") \
    if model.respond_to?(:deleted?) && model.deleted?

  responder_options = { responder: ResponderWithPutPatchDeleteContent }
  represent_with_options = { user_options: options, represent_with: represent_with }

  model.with_lock do
    if model.destroy
      model.send :clear_association_cache
      yield model if block_given?
      respond_with model, responder_options.merge(represent_with_options)
    else
      render_api_errors(model.errors)
    end
  end
end
standard_index(relation, represent_with, options={}) click to toggle source
# File lib/openstax/api/roar.rb, line 12
def standard_index(relation, represent_with, options={})
  model_klass = relation.base_class
  OSU::AccessPolicy.require_action_allowed!(:index, current_api_user, model_klass)

  represent_with_options = { user_options: options, represent_with: represent_with }

  relation.each do |item|
    # Must be able to read each record
    OSU::AccessPolicy.require_action_allowed!(:read, current_api_user, item)
  end

  respond_with(Lev::Outputs.new(items: relation), represent_with_options)
end
standard_nested_create(model, container_association, container, represent_with=nil, options={}) click to toggle source
# File lib/openstax/api/roar.rb, line 61
def standard_nested_create(model, container_association, container,
                           represent_with=nil, options={})
  # Must be able to update the container
  OSU::AccessPolicy.require_action_allowed!(:update, current_api_user, container)

  model.send("#{container_association.to_s}=", container)

  standard_create(model, represent_with, options)
end
standard_read(model, represent_with=nil, use_timestamp_for_cache=false, options={}) click to toggle source
# File lib/openstax/api/roar.rb, line 71
def standard_read(model, represent_with=nil, use_timestamp_for_cache=false, options={})
  OSU::AccessPolicy.require_action_allowed!(:read, current_api_user, model)

  respond_with(model, { user_options: options, represent_with: represent_with }) \
    if !use_timestamp_for_cache || stale?(model, template: false)
end
standard_restore(model, represent_with=nil, options={}) { |model| ... } click to toggle source
# File lib/openstax/api/roar.rb, line 120
def standard_restore(model, represent_with=nil, options={})
  OSU::AccessPolicy.require_action_allowed!(:restore, current_api_user, model)

  return render_api_errors(code: "#{model.model_name.element}_is_not_deleted",
                           message: "#{model.model_name.human} is not deleted") \
    if !model.respond_to?(:deleted?) || !model.deleted?

  recursive = options.has_key?(:recursive) ? options[:recursive] : true

  responder_options = { responder: ResponderWithPutPatchDeleteContent }
  represent_with_options = {
    user_options: options.except(:recursive), represent_with: represent_with
  }

  model.with_lock do
    if model.restore(recursive: recursive)
      model.send :clear_association_cache
      yield model if block_given?
      respond_with model, responder_options.merge(represent_with_options)
    else
      render_api_errors(model.errors)
    end
  end
end
standard_sort(*args) click to toggle source
# File lib/openstax/api/roar.rb, line 145
def standard_sort(*args)
  raise NotYetImplemented
end
standard_update(model, represent_with=nil, options={}) { |model| ... } click to toggle source
# File lib/openstax/api/roar.rb, line 78
def standard_update(model, represent_with=nil, options={})
  # Must be able to update the record before and after the update itself
  OSU::AccessPolicy.require_action_allowed!(:update, current_api_user, model)

  responder_options = { responder: ResponderWithPutPatchDeleteContent }
  represent_with_options = { user_options: options, represent_with: represent_with }

  model.with_lock do
    consume!(model, represent_with_options.dup)
    yield model if block_given?
    OSU::AccessPolicy.require_action_allowed!(:update, current_api_user, model)

    if model.save
      # http://stackoverflow.com/a/27413178
      respond_with model, responder_options.merge(represent_with_options)
    else
      render_api_errors(model.errors)
    end
  end
end