親バカエンジニアのナレッジ帳

webのエンジニアをやっており、日頃の開発で詰まったことや書き残しておきたいことを載せています。

RailsでAPI用のアプリを作成(GET処理編)

APIモードでアプリを作成

前回の内容
ti-tomo-knowledge.hatenablog.com

前回Railsをセットアップして起動させるところまで進めましたが、今回は主にAPI用でRailsを使いたいので、GET処理をするAPIを作ってみたいと思います。(POST処理は次回)
今回は再度APIモードでRailsのプロジェクトを作り直します。
なぜかというと、APIモードでプロジェクトを作成した場合、jbuilderというJSONを生成するためのライブラリが自動で使える状態になるからです。
また、APIでは不要となるview等の描画で使用するファイルをインストールすることも無くなります。
決してAPIしかできなくなるわけではないのでご注意ください。

ではさっそく、、、
前回の手順でいうところの

bundle init

から新たにやり直す形になります。


APIモードで作成する場合は前回以下のようにしていたところを、

bundle exec rails new .


以下のコマンドにしてプロジェクトを作成してください。

bundle exec rails new . --api

モデルの作成

まずはモデルを作成しましょう。
以下のコマンドで、titleとbodyというカラムを持つArticleというモデルを作成してください。

rails g model article title:string body:string


上手くいくと以下のようにファイルが作成されます。

Running via Spring preloader in process 42139
      invoke  active_record
      create    db/migrate/20190712070305_create_articles.rb
      create    app/models/article.rb
      invoke    test_unit
      create      test/models/article_test.rb
      create      test/fixtures/articles.yml

ここで注目していただきたいのが、「db/migrate/20190712070305_create_articles.rb」というマイグレーションのファイルです。

中身を見てみると、以下のようにテーブル作成の定義が書かれています。

class CreateArticles < ActiveRecord::Migration[5.2]
  def change
    create_table :articles do |t|
      t.string :title
      t.string :body

      t.timestamps
    end
  end
end


「rake db:migrate」でマイグレーションを実行できるのですが、先にDBの設定が必要になります。
私はMySQLを使いたいので、MySQLと接続できるライブラリをGemfileに追加します。

gem 'mysql2'

そしてライブラリの反映

bundle install


次に、config/database.ymlファイルを変更しましょう。
もちろん設定値(database、username、password等)はそれぞれの環境に合わせてください。

development:
  adapter: mysql2
  encoding: utf8
  database: rails_test
  username: root
  password:
  host: localhost

※また別の機会に触れますが、本番環境の接続情報は環境変数などで設定しましょうね。

あとはマイグレーションの実行です。

rake db:migrate

マイグレーションが完了です!

== 20190712070305 CreateArticles: migrating ===================================
-- create_table(:articles)
   -> 0.0076s
== 20190712070305 CreateArticles: migrated (0.0077s) ==========================

データベースにarticlesというテーブルができているはずです。
テスト用にデータを適当に挿入しておきます。

INSERT INTO articles(title, body, created_at, updated_at) VALUES ('AAAA', 'BBBB', '2019/04/01', '2019/05/01'),('CCCC', 'DDDD', '2019/04/02', '2019/05/02');

コントローラの作成

次にコントローラの作成です。
APIのコントローラ系はapiディレクトリの下に配置しておきたいので、以下のようなコマンドを発行します。

rails g controller api/articles


すると結果はこんな感じに。

  create  app/controllers/api/articles_controller.rb
  invoke  test_unit
  create    test/controllers/api/articles_controller_test.rb


ここで1つ蛇足ですが、今回APIモードでアプリを作っていますが、APIモードではなく、通常であればこんなに大量にファイルができます。

  create  app/controllers/api/articles_controller.rb
  invoke  erb
  create    app/views/api/articles
  invoke  test_unit
  create    test/controllers/api/articles_controller_test.rb
  invoke  helper
  create    app/helpers/api/articles_helper.rb
  invoke    test_unit
  invoke  assets
  invoke    coffee
  create      app/assets/javascripts/api/articles.coffee
  invoke    scss
  create      app/assets/stylesheets/api/articles.scss

viewやscssなど不要なファイルも盛りだくさんです。
よって、APIをメインで使うサービスであればぜひAPIモードで作成しましょう。

次にURLのルーティングです。
今回は「ドメイン/api/articles」で目的の値を表示させたいと思っているので、「config/routes.rb」ファイルに対して以下のようにしてください。

Rails.application.routes.draw do
  namespace 'api' do
    resources :articles
  end
end


正しく設定できているか確認です。

rake routes
      Prefix Verb   URI Pattern                    Controller#Action
api_articles GET    /api/articles(.:format)        api/articles#index
             POST   /api/articles(.:format)        api/articles#create
 api_article GET    /api/articles/:id(.:format)    api/articles#show
             PATCH  /api/articles/:id(.:format)    api/articles#update
             PUT    /api/articles/:id(.:format)    api/articles#update
             DELETE /api/articles/:id(.:format)    api/articles#destroy

問題ありませんね。


次にコントローラの中身ですが、今回は簡易的にindexだけ作成し、先ほど投入したテストデータが表示されるようにします。

module Api
  class ArticlesController < ApplicationController
    def index
      articles = Article.order(created_at: :desc)
      render json: { status: 'OK', data: articles }
    end
  end
end

apiディレクトリ直下にコントローラを配置しているので、「module Api」を先頭に入れる必要があります。


さあ、いよいよ起動させます。

rails s


初期状態では、ドメインはローカルホストになるので、コンソールから以下URLで確認しましょう。

curl -s http://localhost:3000/api/articles


問題なく値が取れてますね!

{"status":"OK","data":[{"id":2,"title":"CCCC","body":"DDDD","created_at":"2019-04-02T00:00:00.000Z","updated_at":"2019-05-02T00:00:00.000Z"},{"id":1,"title":"AAAA","body":"BBBB","created_at":"2019-04-01T00:00:00.000Z","updated_at":"2019-05-01T00:00:00.000Z"}]}

今回は簡易的な実装なのでコンソールから確認しましたが、実際は他のアプリから呼ばれるものになるはずです。
そうなるとクロスドメインの設定などまだまだやることは盛りだくさん。。。
とりあえず次回はPOST処理編です。