rAPId Code Climate Build Status Test Coverage

NOT PRODUCTION READY

A framework for rapid development of Rails APIs-- RapidApi aims to reduce code maintenance and testing costs, while increasing speed of development. Because the ceremony of rendering resource actions is performed for you, you can focus more time on what makes your app unique.

Installation

Include in your Gemfile:

gem 'rapid_api', git: 'git://github.com/briandavidwetzel/rapid_api.git'

Documentation

Rapid Actions

Including rapid_actions in your controller will give you conventional resourceful actions: #index, #show, #create, #update, and #destroy.

class BricksController < ApplicationController
  rapid_actions

  permit_params     :color, :weight, :material
  filterable_params :color
end

Permitted Params

The permit_params macro secures member requests using strong params. Just pass the attributes that you want to be used in creation or update of your model.

Filterable Params

The filterable_params macro is similar permit_params, except that it applies to the collection instead of the member. RapidApi supports basic filtering on the index action. A hash of keys and values will be passed to the model adapter secured via strong params.

Error Handling

Error handling is provided automatically for the generated actions. There are currently three potential errors that can be raised and are rendered:

  • NotFoundError (:not_found) - obviously, when a member is not found to be shown, updated, or destroyed.
  • NotProcessableError (:unprocessable_entity) - this will be rendered when a member has errors added during the create or update process.
    • NOTE: For ActiveRecord, this pattern emphasizes using errors.add over raising exceptions. Also, for AMS, this convention works well with Ember Data's ActiveModelAdapter errors object out of the box.
  • StandardError (:internal_server_error) - Everything else gets caught as an internal server error. The error message is serialized in the json response body.

Configuration

By default, RapidApi will attempt to use ActiveRecord, ActiveModelSerializer and the Rails naming conventions to discover your model and serializer per controller, but you are able to customize the definition. You can pass optional arguments to the rapid_actions macro as follows.

rapid_actions model: YourModel, serializer: YourSerializer, model_adapter: CustomModelAdapter, serializer_adapter: CustomSerializerAdapter

These settings could also be set globally using the configuration object. For example,

RapidApi.config.model_adapter      = CustomModelAdapter
RapidApi.config.serializer_adapter = CustomSerializerAdapter

You can also override the response codes, if necessary.

RapidApi.config.response_codes[:created] = :ok

Scoping

If you want to scope your controller by a given attribute or attributes, you can use the scope_by macro

class BricksController < ApplicationController
  rapid_actions

  permit_params     :color, :weight, :material
  filterable_params :color

  scope_by :user_id do |controller|
    controller.authenticated.id
  end
end

The scope by block should return the corresponding value for the attribute(s), passed to scope_by. In the event that there are multiple scoping attributes, you should return an array of values in the block. The scope will apply to all generated actions.

Authentication

NOTE: The authentication functionality is likely to be moved to another gem by the release of v1

Some basic API appropriate authentication is available in the form json web tokens. However, you can use RapidApi without taking advantage of this functionality.

The Sessions Controller

class SessionsController < ApplicationController
  rapid_sessions_controller

  authenticates_with :username, :password do |params|
    User.where(username: params[:username], password: params[:password]).first
  end

  responds_with do |authenticated|
    {
      token: jwt_encode({ secret: 'foo' }),
      user: {
        id:       authenticated.id,
        username: authenticated.username
      }
    }
  end
end

rapid_sessions_controller will generate an authenticate method, that can be called to initiate a session with your api. The authenticates_with macro accepts the parameters that will be used to authenticate, and a block that will do the actual authentication. The block should return the authenticated object. In the example given, the authenticated User. Returning nil, well render an :unauthorized response. Otherwise, responds_with is passed the authenticated object to build the auth token payload for the authentication response.

Authenticated Controllers

class ApplicationController
  rapid_base_controller

  authorize do |controller|
    token = controller.decode_jwt_token!(controller.request.headers.env['Authorization'])
    user_id = token[0].try :[], 'user_id'
    if user_id.present?
      User.find user_id
    else
      nil
    end
  end
end

rapid_base_controller can be added to the base class for your api controllers to provide a before_action that checks authentication. Note if your SessionController is derived from the same base class, then you should add skip_before_action :authorize! to your SessionsController. The authenticate macro should be passed a block that returns the authenticated object. In the example, the 'Authorization' token is parsed to return the current user. If your authenticate block returns nil, then :unauthorized will be rendered.

Also note that the decode_jwt_token! can raise errors that will result in the rendering of an :unauthorized response.

Extending RapidApi

If you don't want to use ActiveRecord or ActiveModelSerializer, that is OK. You can create your own adapters.

There are two abstract classes that can be used as base classes for your own implementation: RapidApi::ModelAdapters::Abstract and RapidApi::SerializerAdapters::Abstract. See the implemented adapters and tests for examples on how to implement an adapter. Post an issue if you get stuck.