/rails-rest-framework

A framework for DRY RESTful APIs in Ruby on Rails.

Primary LanguageRubyMIT LicenseMIT

Rails REST Framework

Gem Version Pipeline Coverage Maintainability

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 building awesome APIs.

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

  # The page_size attribute doesn't exist on the `BaseControllerMixin`, but for child controllers
  # that include the `ModelControllerMixin`, they will inherit this attribute and will not overwrite
  # it.
  class_attribute(:page_size, default: 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
    return api_response(
      {
        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
    return api_response({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.
    return api_response(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 server and rails console).