module ApiMe

Constants

VERSION

Public Instance Methods

create() click to toggle source
# File lib/api_me.rb, line 128
def create
  @object = build_resource
  authorize_resource @object
  create_resource!

  render status: :created, json: @object, root: singular_root_key, serializer: serializer_klass
end
destroy() click to toggle source
# File lib/api_me.rb, line 149
def destroy
  @object = find_resource
  authorize_resource @object
  destroy_resource!

  head :no_content
end
edit() click to toggle source
# File lib/api_me.rb, line 136
def edit
  render_errors(['edit endpoint not supported'], :not_found)
end
index() click to toggle source

Currently merge params in filters hash to support common use case of filtering ids using the top level ids array param. Would eventually like to move to support the jsonapi.org standard closer.

# File lib/api_me.rb, line 76
def index
  @policy_scope = policy_scope(resource_scope)
  @filter_scope = filter_scope(@policy_scope)
  @sorted_scope = sort_scope(@filter_scope)
  @pagination_object = paginate_scope(@sorted_scope, page_params)

  respond_to do |format|
    format.csv do
      @csv_includes_scope = csv_includes_scope(@sorted_scope)
      response.headers['Content-Type'] = 'text/csv'
      response.headers['Cache-Control'] = 'no-cache'
      # Hack to work around https://github.com/rack/rack/issues/1619
      response.headers['Last-Modified'] = Time.current.httpdate
      # Disable gzip in nginx
      response.headers['X-Accel-Buffering'] = 'no'
      response.headers['Content-Disposition'] = "attachment; filename=\"#{csv_filename}\""

      ::ApiMe::CsvStreamWriter.generate(response.stream) do |csv|
        # headers
        csv << csv_headers
        @csv_includes_scope.find_each do |object|
          csv << object.try('to_csv')
        end
      end
    ensure
      response.stream.close
    end
    format.all do
      render(
        json: @pagination_object.results,
        root: collection_root_key,
        each_serializer: serializer_klass,
        meta: {
          page: @pagination_object.page_meta,
          sort: sorting_meta(@filter_scope)
        }
      )
    end
  end
end
new() click to toggle source
# File lib/api_me.rb, line 124
def new
  render_errors(['new endpoint not supported'], :not_found)
end
show() click to toggle source
# File lib/api_me.rb, line 117
def show
  @object = find_resource
  authorize_resource @object

  render json: @object, root: singular_root_key, serializer: serializer_klass
end
update() click to toggle source
# File lib/api_me.rb, line 140
def update
  @object = find_resource
  @object.assign_attributes(object_params)
  authorize_resource @object
  update_resource!

  render status: :ok, json: @object, root: singular_root_key, serializer: serializer_klass
end

Protected Instance Methods

authorize_resource(resource) click to toggle source
# File lib/api_me.rb, line 288
def authorize_resource(resource)
  authorize resource
end
build_resource() click to toggle source
# File lib/api_me.rb, line 272
def build_resource
  @build_resource ||= model_klass.new(object_params)
end
collection_root_key() click to toggle source
# File lib/api_me.rb, line 175
def collection_root_key
  model_klass.name.pluralize.underscore
end
create_resource!() click to toggle source
# File lib/api_me.rb, line 276
def create_resource!
  @object.save!
end
csv_filename() click to toggle source
# File lib/api_me.rb, line 159
def csv_filename
  "#{model_klass.name.dasherize}-#{Time.zone.now.to_date.to_s(:default)}.csv"
end
csv_headers() click to toggle source
# File lib/api_me.rb, line 163
def csv_headers
  model_klass.respond_to?('csv_headers') ? model_klass.csv_headers : []
end
csv_includes_scope(scope) click to toggle source
# File lib/api_me.rb, line 167
def csv_includes_scope(scope)
  scope
end
destroy_resource!() click to toggle source
# File lib/api_me.rb, line 284
def destroy_resource!
  @object.destroy!
end
filter_klass() click to toggle source
# File lib/api_me.rb, line 218
def filter_klass
  self.class.filter_klass
end
filter_params() click to toggle source
# File lib/api_me.rb, line 264
def filter_params
  params[:filters]
end
filter_scope(scope) click to toggle source
# File lib/api_me.rb, line 230
def filter_scope(scope)
  filter_klass.new(
    scope: scope,
    filters: filters_hash
  ).results
end
filters_hash() click to toggle source
# File lib/api_me.rb, line 259
def filters_hash
  ids_filter_hash = params[:ids] ? { ids: params[:ids] } : {}
  (filter_params || {}).merge(ids_filter_hash)
end
find_resource() click to toggle source
# File lib/api_me.rb, line 268
def find_resource
  @find_resource ||= model_klass.find_by!(id: params[:id])
end
handle_active_record_errors(active_record_error) click to toggle source
# File lib/api_me.rb, line 195
def handle_active_record_errors(active_record_error)
  Rails.logger.debug "ERROR: #{active_record_error}"
  render_errors(active_record_error.record.errors.messages)
end
Also aliased as: handle_errors
handle_errors(active_record_error)
model_klass() click to toggle source
# File lib/api_me.rb, line 210
def model_klass
  self.class.model_klass
end
object_params() click to toggle source
# File lib/api_me.rb, line 179
def object_params
  params.require(params_klass_symbol).permit(*policy(@object || model_klass).permitted_attributes)
end
page_params() click to toggle source
# File lib/api_me.rb, line 183
def page_params
  params[:page]
end
paginate_scope(scope, params) click to toggle source
# File lib/api_me.rb, line 251
def paginate_scope(scope, params)
  ApiMe::Pagination.new(scope: scope, page_params: params)
end
params_klass_symbol() click to toggle source
# File lib/api_me.rb, line 255
def params_klass_symbol
  model_klass.name.demodulize.underscore.to_sym
end
render_errors(errors, status = :unprocessable_entity) click to toggle source
# File lib/api_me.rb, line 191
def render_errors(errors, status = :unprocessable_entity)
  render(json: { errors: errors }, status: status)
end
resource_not_found() click to toggle source
# File lib/api_me.rb, line 206
def resource_not_found
  head :not_found
end
resource_scope() click to toggle source
# File lib/api_me.rb, line 226
def resource_scope
  model_klass.all
end
serializer_klass() click to toggle source
# File lib/api_me.rb, line 214
def serializer_klass
  self.class.serializer_klass
end
singular_root_key() click to toggle source
# File lib/api_me.rb, line 171
def singular_root_key
  model_klass.name.singularize.underscore
end
sort_klass() click to toggle source
# File lib/api_me.rb, line 222
def sort_klass
  ApiMe::Sorting
end
sort_params() click to toggle source
# File lib/api_me.rb, line 187
def sort_params
  params[:sort]
end
sort_scope(scope, sortable_params = sort_params) click to toggle source
# File lib/api_me.rb, line 244
def sort_scope(scope, sortable_params = sort_params)
  sort_klass.new(
    scope: scope,
    sort_params: sortable_params
  ).results
end
sorting_meta(scope, sortable_params = sort_params) click to toggle source
# File lib/api_me.rb, line 237
def sorting_meta(scope, sortable_params = sort_params)
  sort_klass.new(
    scope: scope,
    sort_params: sortable_params
  ).sort_meta
end
update_resource!() click to toggle source
# File lib/api_me.rb, line 280
def update_resource!
  @object.save!
end
user_not_authorized() click to toggle source
# File lib/api_me.rb, line 201
def user_not_authorized
  payload = { message: "User is not allowed to access #{params[:action]} on this resource" }
  render json: payload, status: :forbidden
end