RailsとGrapeをはじめてつかってみた

RailsでRESTful APIを書くんだったら、Grapeでしょう。

という話をよく聞くので、Railsを使ってWebAPIを書くためにGrapeを使ってみることにしました。

Grapeってなんだろう

GrapeのgithubのREADMEにある通り、

Grape is a REST-like API micro-framework for Ruby

GrapeはRubyでRESTlikeなAPIを実装するための「マイクロフレームワーク」らしいです。 よくRailsと組み合わせで見る事が多いせいか、Rails専用のものだと思っていたのですが、 Rack単体や、Sinatraでも使用することが可能みたいです。 そんなにRailsの機能を使わない場合や、軽さを求められる事案にはこちらのほうがいいのかなと思っています。

とりあえず、今回はRailsと組み合わせて使うサンプルを適当に書いてみました。

Grapeの他にCookpad製のGarageというものもあるので、こちらも今後試してみようかなという感じです。

実際にRailsと組み合わせて使ってみる。

今回実装してみるのは簡単なブログアプリケーションという定番のものを想定しています。

ディレクトリとルーティングについて

ディレクトリ構成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
app/
├── api
│   ├── api.rb
│   └── post_api.rb
├── controllers
│   ├── application_controller.rb
│   └── concerns
├── models
│   ├── concerns
│   └── post.rb
└── views
    └── api
           └── posts
           ├── index.jbuilder
           └── show.jbuilder

ルーティング

1
2
3
4
5
GET        /api/v1/posts(.json)
GET        /api/v1/posts/:id(.json)
POST       /api/v1/posts(.json)
PUT        /api/v1/posts/:id(.json)
DELETE     /api/v1/posts/:id(.json)

今回使用したGemfile

railsのバージョンは投稿日の最新の4.2.3

grapeとgrape-jbuilderを追記しただけなのですが、参考に掲載しておきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
source 'https://rubygems.org'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.2.3'
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# Use CoffeeScript for .coffee assets and views
gem 'coffee-rails', '~> 4.1.0'
# See https://github.com/rails/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby

# Use jquery as the JavaScript library
gem 'jquery-rails'
# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem 'turbolinks'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.0'
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', '~> 0.4.0', group: :doc

# Use ActiveModel has_secure_password
gem 'bcrypt', '~> 3.1.7'

# Use Unicorn as the app server
# gem 'unicorn'
gem 'grape'
gem 'grape-jbuilder'

# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug'

  # Access an IRB console on exception pages or by using <%= console %> in views
  gem 'web-console', '~> 2.0'

  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
end

モデルについて

事前にpostモデルを作って、migrationを流しておいてください。

1
2
bundle exec rails g model post title:string content:text
bundle exec rake db:migrate

初期設定

下準備としてapplication.rbを以下のように編集しましょう。

config/application.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
require File.expand_path('../boot', __FILE__)

require 'rails/all'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module BlogApi
  class Application < Rails::Application
    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration should go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded.

    # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
    # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
    # config.time_zone = 'Central Time (US & Canada)'

    # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
    # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
    # config.i18n.default_locale = :de

    # Do not swallow errors in after_commit/after_rollback callbacks.
    config.active_record.raise_in_transactional_callbacks = true

    # app/api以下にある.rbファイルを読み込みます

    config.paths.add "app/api", glob: "**/*.rb"
    config.autoload_paths += Dir["#{config.root}/app/api"]

    config.middleware.use(Rack::Config) do |env|
      env['api.tilt.root'] = Rails.root.join 'app', 'views', 'api'
    end

  end
end

ベースとなる処理を書きます。 テンプレートにjbuilderを使用していきたいと思います。

app/api/api.rb
1
2
3
4
5
6
7
8
9
10
module API
  class Base < Grape::API
    prefix 'api'
    version 'v1', using: :path
    format :json
    formatter :json, Grape::Formatter::Jbuilder

    mount Post_API
  end
end

Post_API

mountしたPost_APIをざっくり実装していきます。

app/api/post_api.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Post_API < Grape::API
  resource :posts do

    get '/', jbuilder:'posts/index' do
      @posts = Post.all
    end

    get ':id', jbuilder:'posts/show' do
      @post = Post.find(params[:id])
    end

    post do
      Post.create({
                      title: params[:title],
                      content: params[:content]
                  })
    end

    put ':id' do
      Post.find(params[:id])
          .update({
                      title: params[:title],
                      content: params[:content]
                  })
    end

    delete ':id' do
      Post.find(params[:id]).destroy
    end
  end

end

RailsアプリケーションでいうところのControllerみたいなものでしょうか。 なかなかシンプルでわかりやすい感じになっています。

jbuilder

app/views/api/posts/index.jbuilder
1
2
3
  json.posts @posts do |post|
    json.(post, :id, :title, :content)
  end
app/views/api/posts/show.jbuilder
1
  json.(@post, :title, :content, :create_at, :updated_at)

こんなかんじでAPIをサクッと書くことができちゃいました。

jbuilderを使用しているので、複雑なJSON APIを作るときには重宝しそう。

本格的に使用するときにはいろいろこれではいけない部分もありますが、ざっくり概要を理解することはできたかなと。

使ってみての感想

正直なところRails専用のもので、Controllerにちょろっと書くだけのような形式だと思っていたのですが、実際には全然違っていて、 もはや似ている別のフレームワークを触っているような感覚がありました。

とはいっても幾分はシンプルにできているので、そこまで学習コストもないのかなという感じはしました。

今回のgithubリポジトリ

grape_sample

参考にしたサイト

[Ruby on Rails]Grapeを使ってWeb APIを作成する

Grape で Web API 開発

Grape + Railsで、Jbuilderを使ったJSONフォーマットAPIを作る