Rails REST Framework
A framework for DRY RESTful APIs in Ruby on Rails.
The Problem: Building controllers for APIs usually involves writing a lot of redundant CRUD logic, and routing them can be obnoxious. Building and maintaining features like ordering, filtering, and pagination can be tedious.
The Solution: This framework implements browsable API responses, CRUD actions for your models, and features like ordering/filtering/pagination, so you can focus on your application logic.
Website/Guide: rails-rest-framework.com
Demo API: rails-rest-framework.com/api/demo
Source: github.com/gregschmit/rails-rest-framework
YARD Docs: rubydoc.info/gems/rest_framework
Installation
Add this line to your application's Gemfile:
gem "rest_framework"
And then run:
bundle install
Quick Usage Tutorial
This section provides some simple examples to quickly get you started using the framework.
For the purpose of this example, you'll want to add an api_controller.rb
to your controllers, as
well as a directory for the resources:
controllers/
├─ api_controller.rb
└─ api/
├─ root_controller.rb
├─ movies_controller.rb
└─ users_controller.rb
Controller Mixins
The root ApiController
can include any common behavior you want to share across all your API
controllers:
class ApiController < ApplicationController
include RESTFramework::BaseControllerMixin
# Setting up a paginator class here makes more sense than defining it on every child controller.
self.paginator_class = RESTFramework::PageNumberPaginator
self.page_size = 30
end
A root controller can provide actions that exist on the root of your API. It's best to define a
dedicated root controller, rather than using the ApiController
for this purpose, so that actions
don't propagate to child controllers:
class Api::RootController < ApiController
self.extra_actions = {test: :get}
def root
render(
api: {
message: "Welcome to the API.",
how_to_authenticate: <<~END.lines.map(&:strip).join(" "),
You can use this API with your normal login session. Otherwise, you can insert your API
key into a Bearer Authorization header, or into the URL parameters with the name
`api_key`.
END
},
)
end
def test
render(api: {message: "Hello, world!"})
end
end
And here is an example of a resource controller:
class Api::MoviesController < ApiController
include RESTFramework::ModelControllerMixin
self.fields = [:id, :name, :release_date, :enabled]
self.extra_member_actions = {first: :get}
def first
# Always use the bang method, since the framework will rescue `RecordNotFound` and return a
# sensible error response.
render(api: self.get_records.first!)
end
def get_recordset
return Movie.where(enabled: true)
end
end
When fields
is nil, then it will default to all columns. The fields
attribute can also be a hash
to include or exclude fields rather than defining them manually:
class Api::UsersController < ApiController
include RESTFramework::ModelControllerMixin
self.fields = {include: [:calculated_popularity], exclude: [:impersonation_token]}
end
Routing
Use rest_route
for non-resourceful controllers, or rest_resource
/ rest_resources
resourceful
routers. These routers add some features to the Rails builtin resource
/resources
routers, such
as automatically routing extra actions defined on the controller. To route the root, use
rest_root
.
Rails.application.routes.draw do
# If you wanted to route actions from the `ApiController`, then you would use this:
# rest_root :api # Will find `api_controller` and route the `root` action to '/api'.
namespace :api do
rest_root # Will route `Api::RootController#root` to '/' in this namespace ('/api').
rest_resources :movies
rest_resources :users
end
end
Development/Testing
After you clone the repository, cd'ing into the directory should create a new gemset if you are
using RVM. Then run bin/setup
to install the appropriate gems and set things up.
The top-level bin/rails
proxies all Rails commands to the test project, so you can operate it via
the usual commands (e.g., rails test
, rails console
). For development, use bin/dev
to run the
web server and the job queue, which serves the test app and coverage/brakeman reports:
- Test App: http://127.0.0.1:3000
- API: http://127.0.0.1:3000/api
- Reports: http://127.0.0.1:3000/reports