Gearhead turns your database into a RESTful API. It's like if ActiveAdmin, InheritedResources, and Grape had a baby.
Purpose
For internal projects I was always standing up API endpoints that were separate from my regular controllers. The boilerplate got old real fast. This eliminates boilerplate and leaves enough configuration for you to make it your own.
Goal
Rid the boilerplate for JSON APIs with opinions, while providing enough customization to work for most applications.
Installation
Gearhead is a Rails engine, for now.
gem 'gearhead'
And then copy over the initializers:
rails g gearhead:install
which generates:
config/initializers/gearhead.rb
app/gears/.keep
and modifies your routes:
Gearhead.routes(self)
Configuration
You can change most of these on the Gear-level, but we have opinions.
Gearhead.setup do |config|
# == Routing
#
# The endpoint in which to mount gearhead on.
# Default is "/gearhead" — must start with a slash, and have no trailing slash
# config.endpoint = "/api/v314"
#
# The default actions a Gear can respond to
# Default is [:index, :create, :show, :update, :destroy]
# config.actions = [:index, :show]
#
# == Querying
#
# The default scope of a Gear will be the default scope of the resource.
# Default is nil
# config.scope = :visible
#
# == Params
#
# Ignored params for creating/updating records
# Default is [:id, :created_at, :updated_at]
# config.ignored_params = [:id, :created_at, :updated_at]
#
# == Automount
#
# Change this to true if you want to automatically mount all your resources.
# config.automount.enabled = false
#
# Automatically mount most of your resources
# config.automount.resources = ['User', 'Post', 'Comment']
#
# Don't automatically mount these resources
# config.automount.excluded = ['User', 'Post']
#
# == Serialization
#
# Change the default serializer
# Currently supports FastJSONAPI (:fast_jsonapi) and ActiveModelSerializers (:active_model_serializers)
# Default is :fast_jsonapi
# config.serialization.adapter = :fast_jsonapi
#
# == Pagination
#
# Change the default paginator
# Currently supports :pagy and :will_paginate
# Default is :pagy
# config.pagination.adapter = :pagy
#
# == Controller
#
# Base class for the Gearhead controller
# Default is 'ApplicationController'
# config.base_controller = 'ApplicationController'
#
end
Exposing your data
Gearhead does some metaprogramming to generate standard RESTful endpoints for your defined Rails models. They do this with Gears.
A Gear is responsible for configuring the controller, including resource retrieval, serialization, and response.
By default, Gearhead doesn't automatically mount all your resources. You can change this if you want in your initializer.
To create a Gear, drop it in /app/gears
and register it with Gearhead.register Model, options
. Prefer a constant over a string.
Gearhead.register Post; end
will generate /gearhead/posts
— or whatever Model.model_name.route_key
is. Change the path:
Gearhead.register Post, path: "postz"; end
A note about automount: If you have automount enabled and call /posts
, and you have explicitly defined this Gear,
the defined Gear will take precedence. If you define a custom path such as postz
and navigate to /posts
with automount
enabled, the defined Gear will still take precedence.
Customizing Gears
Actions
Change what CRUD actions the Gear can respond to:
Gearhead.register Post do
actions :index, :show
# or
actions except: [:create, :update, :delete]
end
Want to expose /gearhead/posts/favorites
?
Gearhead.register Post do
collection_action :favorites, via: :get do
# do something
end
end
Expose GET /gearhead/posts/:id/report
and POST /gearhead/posts/:id/report
:
Gearhead.register Post do
member_action :report, via: [:get, :post] do
if request.get?
resource.reports.all
elsif request.post?
resource.reports.create!
end
end
end
Handling pagination
Gearhead.register Post do
per_page 5
# or disable it
pagination false
end
Serializing your objects
Just define what attributes you want exposed:
Gearhead.register Post do
attributes :id, :title
end
And customize one-off attributes:
Gearhead.register Post do
attributes :id, :title
attribute :excerpt do |resource|
resource.content.first(100)
end
end
Finding resources
Change your finder:
Gearhead.register Post do
finder do
resource_class.find_by(token: params[:resource_id])
end
end
Querying
Uses Ransack under the hood. Just send the normal q
in the query, like:
GET /gearhead/posts?q[user_id]=1
Permitting params
Works just like the params you're used to:
Gearhead.register Post do
permit_params :user_id, :content
# or do it for a certain subset of actions
permit_params :user_id, :content, only: :create
permit_params :content, only: :update
end
TODO
- Better param handling
- Handling params for member actions and collection actions
- Callbacks
- Documentation about authentication and
current_user
-ish stuff - Wiki
- Logo
Contributing
Do things.
License
The gem is available as open source under the terms of the MIT License.