Skip to content

Repository files navigation

ApiBlocks

GemCode ClimateInch

ApiBlocks provides simple and consistent Rails API extensions.

Links:

Installation

gem'api-blocks'

Configuration

In an initializer such as config/initializers/api_blocks.rb you can enable the optional blueprinter and batch-loader integration:

ApiBlocks.configuredo |config|
config.blueprinter.use_batch_loader=trueend

This allows you to use batch-loader in order to avoid n+1 queries when serializing associations in blueprints.

This has some caveats which are documented in association_extractor.rb.

ApiBlocks::Controller

Include ApiBlocks::Controller in your api controller:

classApi::V1::ApplicationController < ActionController::APIincludeApiBlocks::Controllerpundit_scope:api,:v1end

Including the module will:

  • Setup ApiBlocks::Responder as a responder.
  • Add the verify_request_format! before_action hook.
  • Setup Pundit, rescue its errors, setup its validation hooks and provide the pundit_scope method.

ApiBlocks::Responder

An ActionController::Responder with better error handling and Dry::Monads::Result support.

Errors are handled for the following cases:

  • The responded resource is an ApplicationRecord subclass and has error.
  • The responded resource is a ActiveRecord::RecordInvalid exception.
  • Otherwise the error is re-raised to be handled through the usual Ruby On Rails error handlers.

In addition, the responder will render resources on POST and PUT rather than returning a redirection.

ApiBlocks::Interactor

It implements a basic interactor base class using dry-transaction and dry-validation under the hood.

It provides to predefined steps:

  • validate_input! which will validate the interactor input according to its schema.
  • database_transaction! an around step that wraps the interactor in an ActiveRecord transaction.

Example:

classRequests::MarkAsRead < ApiBlocks::Interactorinputdoschemadorequired(:request).filled(type?: Request)endendaround:database_transaction!step:validate_input!try:update_request!,catch: ActiveRecord::RecordInvalidtry:create_history_item!,catch: ActiveRecord::RecordInvaliddefupdate_request!(request:)request.update!(read_at: Time.now.utc)requestenddefcreate_history_item!(request)request.request_history_items.create!(kind: :read)requestendend

ApiBlocks::Doorkeeper::Passwords

Implement an API for passwords reset using doorkeeper and devise.

Include the ApiBlocks::Doorkeeper::Passwords::Controller module in your passwords api controller and define the user_model method to return the concerned devise user model.

# app/controllers/api/v1/passwords_controller.rbclassApi::V1::PasswordsController < Api::V1::ApplicationControllerincludeApiBlocks::Doorkeeper::Passwords::Controllerprivatedefuser_modelUserendend

Then add the approriate routes to your configuration.

# config/routes.rbRails.application.routes.drawdoscopemodule: :apidonamespace:v1doresources:passwords,only: %i[create]doget:callback,on: :collectionput:update,on: :collectionendendendend

Include the ApiBlocks::Doorkeeper::ResetPassword module so devise will forward the doorkeeper application to the mailer.

# app/models/user.rbclassUser < ApplicationRecordincludeApiBlocks::Doorkeeper::ResetPasswordend

Include the reset password Doorkeeper::Application extensions.

# config/initializers/doorkeeper.rbDoorkeeper.configuredo# ...endclass ::Doorkeeper::Application < ActiveRecord::BaseincludeApiBlocks::Doorkeeper::Passwords::Applicationend

Override your devise mailer #reset_password_instructions method to add the application parameter.

# app/mailers/devise_mailer.rbclassDeviseMailer < Devise::Mailerdefreset_password_instructions(record,token,application=nil,_opts={})@token=token@application=applicationendend

Update the devise mailer template to link to the callback API.

# app/views/devise/mailer/reset_password_instructions.html.erb
<p><%=link_to"Change my password",callback_v1_passwords_url(reset_password_token: @token)%></p>

Finally, generate the required migrations:

bundle exec rails g api_blocks:doorkeeper:passwords:migration

ApiBlocks::Doorkeeper::Invitations

Implement an API for devise_invitable using doorkeeper.

Include the ApiBlocks::Doorkeeper::Invitations::Controller module in your api controller and define the user_model method to return the concerned devise user model.

# app/controllers/api/v1/invitations_controller.rbclassApi::V1::InvitationsController < Api::V1::ApplicationControllerincludeApiBlocks::Doorkeeper::Invitations::Controllerprivatedefuser_modelUserendend

Add the approriate routes to your configuration.

# config/routes.rbRails.application.routes.drawdoscopemodule: :apidonamespace:v1doresources:invitations,only: %i[createshow]doget:callback,on: :collectionput:update,on: :collectionendendendend

Include the invitations Doorkeeper::Application extensions.

# config/initializers/doorkeeper.rbDoorkeeper.configuredo# ...endclass ::Doorkeeper::Application < ActiveRecord::BaseincludeApiBlocks::Doorkeeper::Invitations::Applicationend

Override your devise mailer #invitation_instructions method to add the application parameter.

# app/mailers/devise_mailer.rbclassDeviseMailer < Devise::Mailerdefinvitation_instructions(_record,token,application: nil, **_opts)@token=token@application=applicationsuperendend

Update the devise mailer template to link to the callback API.

# app/views/devise/mailer/invitation_instructions.html.erb
<p><%=link_tot("devise.mailer.invitation_instructions.accept"),callback_v1_invitations_url(invitation_token: @token,client_id: @application.uid)%></p>

Finally, generate the required migrations:

bundle exec rails g api_blocks:doorkeeper:invitations:migration

External Resources

License

Licensed under the MIT license, see the separate LICENSE.txt file.

About

Simple and consistent rails api extensions

Topics

Resources

Stars

9 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages