Project Name | Stars | Downloads | Repos Using This | Packages Using This | Most Recent Commit | Total Releases | Latest Release | Open Issues | License | Language |
---|---|---|---|---|---|---|---|---|---|---|
Omniauth | 7,687 | 35,314 | 894 | 4 days ago | 66 | August 18, 2022 | 96 | mit | Ruby | |
OmniAuth is a flexible authentication system utilizing Rack middleware. | ||||||||||
Mutations | 1,377 | 105 | 10 | 5 months ago | 19 | April 08, 2020 | 30 | mit | Ruby | |
Compose your business logic into commands that sanitize and validate input. | ||||||||||
Jb | 1,209 | 349 | 2 | 4 months ago | 12 | October 27, 2020 | 17 | mit | Ruby | |
A simple and fast JSON API template engine for Ruby on Rails | ||||||||||
Versionist | 946 | 359 | 3 | 2 years ago | 24 | July 22, 2019 | 7 | mit | Ruby | |
A plugin for versioning Rails based RESTful APIs. | ||||||||||
Logstasher | 806 | 266 | 5 | 6 months ago | 46 | December 29, 2020 | 41 | mit | Ruby | |
Awesome rails logs | ||||||||||
The_role | 777 | 43 | 1 | 2 years ago | 52 | November 06, 2019 | 6 | Ruby | ||
Authorization for Rails + GUI. Semantic, Flexible, Lightweight | ||||||||||
Pluck_to_hash | 264 | 42 | 5 years ago | 11 | August 09, 2017 | 4 | mit | Ruby | ||
Extend ActiveRecord pluck to return array of hashes | ||||||||||
Jsonapi Utils | 207 | 17 | 1 | a year ago | 34 | April 27, 2020 | 24 | mit | Ruby | |
Build JSON API-compliant APIs on Rails with no (or less) learning curve. | ||||||||||
Rabl Rails | 200 | 146 | 1 | 2 years ago | 25 | March 25, 2021 | 6 | mit | Ruby | |
Rails 4.2 & 5 templating system with JSON, XML and Plist support. | ||||||||||
Rails5 Spec Converter | 164 | 1 | 4 years ago | 23 | October 14, 2016 | 9 | mit | Ruby | ||
A tool to upgrade Rails 4-style specs to Rails 5-style |
The general purpose of this gem is to wrap the various best practices of integrating GrapeAPI within the context of a Rails app into an easy-to-use macro-framework and DSL, plus some opinionated value-adds and features. Basically, Grape and Rails play together great, but can be tricky to integrate in a robust, clean way; GrapeApeRails (hopefully) makes your life easier.
GrapeApeRails is opinionated. The goal is to make integration easier, so GrapeApeRails makes a number of integration decisions for you:
http_accept_language
middlewareIf these opinions and features align closely to what you're planning to build for your API, I think you'll find GrapeApeRails very useful. If you're intending to build something very different from the above, you're probably better off integrating Grape on your own, or looking at alternate projects like Rails::API.
Add this line to your application's Gemfile:
gem 'grape_ape_rails'
And then execute:
$ bundle
Or install it yourself as:
$ gem install grape_ape_rails
First, GrapeApeRails needs an initializer as config/initializers/grape_ape_rails.rb
The easiest way to do this is to run the handy rails generator command:
rails g grape_ape_rails:setup
This will:
tilt.root
Rack config to your application.rb for use with Rabl templatesNext, you'll need to create your API::Base
class, which serves as the starting point for all
of your API endpoints and all versions of your API. By default, GrapeApeRails looks for a
base.rb file in app/controllers/api/base.rb
# app/controllers/api/base.rb
module API
class Base < GrapeApeRails::API
grape_apis do
api "V1" do
# ... mounts go here
end
end
end
end
NOTE: the api name needs to look like a class name, with camelcase (e.g. "V1" or "AdminV1"). This actually is the class that GrapeApeRails will then expect you to define for exposing your endpoints. Internally, Grape will translate this to an under-dotted version name (e.g "v1" or "admin.v1") and this is what will be expected in the Accept header string provided by the requestor.
Now that you've got your base.rb ready, you need to mount your various resources/endpoints. This is
done via the grape_mount
command. These should generally be mounted as pluralized resource names.
# inside the base.rb ...
api "V1" do
grape_mount :widgets
grape_mount :robots
grape_mount :pirates
# ... etc
end
If you try to spin up your app now, it will complain that you need to actually create the class files for each of the resources you've mounted. So let's do that in a 'v1' subfolder...
# app/controllers/api/v1/widgets.rb
module API
module V1
class Widgets < GrapeApeRails::API
include GrapeApeRails::Handlers::All
resource :widgets do
desc "Get a single Widget"
get ':id', rabl: 'v1/widget' do
@widget = Widget.find(params[:id])
@widget
end
end
end
end
end
In this case, I've simply created a /widgets/:id
endpoint, but you can define whatever endpoints you want.
Because you've defined this within the :widgets resource, the API will assume all of these endpoints begin
with /widgets
In my example, I'm using the default Rabl-based templating. The rabl
parameter expects a path to the .rabl template file,
as found within /app/views/api/ ... all Rabl functionality should work as expected.
NOTE: Unlike the ActiveModel Serializers, the Rabl formatter doesn't impose any sort of resource-keyed hash for the response. This is your responsibility to define in your Rabl template if you want to use the "plural key, always-array" standard.
Example Rabl templates:
# v1/base_widget.rabl
attributes *Widget.column_names
# single widget (v1/widget.rabl)
collection [@widget] => :widgets
extends "v1/base_widget"
# array of multiple widgets (v1/widgets.rabl)
collection @widgets => :widgets
extends "v1/base_widget"
If you'd prefer ActiveModel Serializers over Rabl, GrapeApeRails supports that as well via a custom Grape formatter
called Grape::Formatter::GarActiveModelSerializers
. To use it, just override the formatter
within each of your API
classes.
module API
module V1
class Monkeys < GrapeApeRails::API
include GrapeApeRails::Handlers::All
formatter :json, Grape::Formatter::GarActiveModelSerializers
resource :monkeys do
desc "Get a single Monkey"
get ':id' do
@monkey = Monkey.find(params[:id])
@monkey
end
end
end
end
end
In this case, it's expected that you've defined a MonkeySerializer class in your models directory, as usual with ActiveModelSerializers.
IMPORTANT: For ActiveModel Serializers, when defining the response structure, I made the decision (based on lots of research) to go with a plural resource key and an always-array approach in the response hash. To put it another way:
If you ask for /widgets/1 you will get
{ "result" : { "widgets" : [ {<widget>} ] } }
and if you ask for /widgets you will get
{ "result" : { "widgets" : [ {widget1}, {widget2}, {widget3}, ... ] } }
If you need, for some reason, to provide a different key in your response hash, you can override the resource key for the plural form of your resource.
Let's say, for example, that you've created a UserSerializer
but you want the JSON to use 'people'...
class UserSerializer < ActiveModel::Serializer
attributes :name, :age, :hair_color
def resource_plural
'people'
end
end
... GrapeApeRails will now always key the hash with "people" : [...one or more people hashes...]
for both single (1-element array) and multiple (n-element array) records.
Similar to the JSON-RPC spec, endpoints exposed using GrapeApeRails will present either a result
hash or an error
hash.
The error hash will be composed of a code
(a machine-friendly enum-like uppercase string) and a
message (human-friendly, user-presentable message that includes the code inside brackets).
# Successful response
{
"result" : {
"widgets" : [
{ "id" : 1, "name" : "Fancy Widget" },
{ "id" : 2, "name" : "Other Thing" },
...
]
}
}
# Error response
{
"error" : {
"code" : "UNAUTHORIZED",
"message" : "[UNAUTHORIZED] Requires a valid user authorization"
}
}
In the case of a validation error on a resource, there will additionally be a data
key inside the error hash that includes Rails-style validation errors.
GrapeApeRails uses Kaminari for pagination via the grape-kaminari gem.
Enabling pagination on a resource is super-simple:
# inside your API resource class...
desc "Return a list of Widgets"
params :pagination do
optional :page, type: Integer
optional :per_page, type: Integer
optional :offset, type: Integer
end
paginate per_page: 30
get '/', rabl: 'v1/widgets' do
@widgets = paginate(@widgets)
end
From the grape-kaminari docs:
Now you can make a HTTP request to your endpoint with the following parameters
page
: your current page (default: 1)per_page
: how many to record in a page (default: 10)offset
: the offset to start from (default: 0)curl -v http://host.dev/widgets?page=3&offset=10
and the response will be paginated and also will include pagination headers
X-Total: 42
X-Total-Pages: 5
X-Page: 3
X-Per-Page: 10
X-Next-Page: 4
X-Prev-Page: 2
X-Offset: 10
git checkout -b my-new-feature
)git commit -am 'Add some feature'
)git push origin my-new-feature
)