Rails | Rails API

# Rails | Rails API

## 概要

Rails::APIはRailsでWeb-APIのみを提供するアプリケーションを作成するためのgemです。

railsコマンドと同等のコマンドが多数用意されていますが、
各種 *generate* 系コマンド実行時に *views* が生成されません。
代わりに各アクションメソッドはJSONを返却します。

## 前提

rails-apiをインストールしておきます

~~~bash
$ gem i rails-api
~~~

## サンプル

### 仕様

下記のモデルを扱います

Person
┠name : string
┗age : integer

### 手順

* 新規プロジェクトを作成します

~~~bash
$ rails-api new api_sample
~~~

* 出力された構成

*views* がないことを確認できます

~~~
$ cd api_sample
$ tree -d
|-- app
|   |-- assets
|   |   `-- images
|   |-- controllers
|   |   `-- concerns
|   |-- mailers
|   `-- models
|       `-- concerns
|-- bin
|-- config
|   |-- environments
|   |-- initializers
|   `-- locales
|-- db
|-- lib
|   |-- assets
|   `-- tasks
|-- log
|-- public
`-- test
    |-- controllers
    |-- fixtures
    |-- helpers
    |-- integration
    |-- mailers
    `-- models
~~~

* scaffoldします

~~~bash
$ rails-api g scaffold person name:string age:integer
      invoke  active_record
      create    db/migrate/20140626233217_create_people.rb
      create    app/models/person.rb
      invoke    test_unit
      create      test/models/person_test.rb
      create      test/fixtures/people.yml
      invoke  api_resource_route
       route    resources :people, except: [:new, :edit]
      invoke  scaffold_controller
      create    app/controllers/people_controller.rb
      invoke    test_unit
      create      test/controllers/people_controller_test.rb
$ rake db:migrate
~~~

* テスト用のデータを挿入します

~~~sql
sqlite> insert into people("name", "age", "created_at", "updated_at") values ('tanaka', 20, datetime('now'), datetime('now'));
sqlite> insert into people("name", "age", "created_at", "updated_at") values ('suzuki', 19, datetime('now'), datetime('now'));
sqlite> select * from people;
1|tanaka|20|2014-06-26 23:38:37|2014-06-26 23:38:37
2|suzuki|19|2014-06-26 23:38:37|2014-06-26 23:38:37
~~~

* Strong Parametersの設定を追加します

PeopleControllerに下記の *private method* を追加

~~~
private

def person_params
  params.require(:person).permit(:name, :age)
end
~~~

PeopleControllerの *create* メソッドの *new* の引数を *person_params* メソッドに変更する

~~~ruby
def create
  # 修正前
  # @person = Person.new(params[:person])
  # 修正後
  @person = Person.new(person_params)

  if @person.save
    render json: @person, status: :created, location: @person
  else
    render json: @person.errors, status: :unprocessable_entity
  end
end
~~~

* Webサーバーを起動します

~~~bash
$ rails s
~~~

* Web-APIを呼び出します。 *index* を呼び出して全 *person* を取得します

~~~bash
$ curl http://xxxxxxxx:3000/people
[{"id":1,"name":"tanaka","age":20,"created_at":"2014-06-26T23:38:37.000Z","updated_at":"2014-06-26T23:38:37.000Z"},{"id":2,"name":"suzuki","age":19,"created_at":"2014-06-26T23:38:37.000Z","updated_at":"2014-06-26T23:38:37.000Z"}]
~~~

* Web-APIを呼び出します。 *show* を呼び出して任意の *id* の *person* を取得します

~~~bash
$ curl http://xxxxxxxx:3000/people/1
{"id":1,"name":"tanaka","age":20,"created_at":"2014-06-26T23:38:37.000Z","updated_at":"2014-06-26T23:38:37.000Z"}
~~~

* Web-APIを呼び出します。 *create* を呼び出して新規 *person* を作成します。

~~~bash
$ curl http://xxxxxxxx:3000/people -X POST -d "person[name]=sato" -d "person[age]=21"
{"id":3,"name":"sato","age":21,"created_at":"2014-06-26T23:51:06.129Z","updated_at":"2014-06-26T23:51:06.129Z"}
~~~

* データを確認

~~~sql
sqlite> select * from people;
1|tanaka|20|2014-06-26 23:38:37|2014-06-26 23:38:37
2|suzuki|19|2014-06-26 23:38:37|2014-06-26 23:38:37
3|sato|21|2014-06-26 23:51:06.129997|2014-06-26 23:51:06.129997
~~~

## 参考
* *scaffold* された PeopleController は以下のようになっています

~~~ruby
class PeopleController < ApplicationController
  # GET /people
  # GET /people.json
  def index
    @people = Person.all

    render json: @people
  end

  # GET /people/1
  # GET /people/1.json
  def show
    @person = Person.find(params[:id])

    render json: @person
  end

  # POST /people
  # POST /people.json
  def create
    @person = Person.new(params[:person])

    if @person.save
      render json: @person, status: :created, location: @person
    else
      render json: @person.errors, status: :unprocessable_entity
    end
  end

  # PATCH/PUT /people/1
  # PATCH/PUT /people/1.json
  def update
    @person = Person.find(params[:id])

    if @person.update(params[:person])
      head :no_content
    else
      render json: @person.errors, status: :unprocessable_entity
    end
  end

  # DELETE /people/1
  # DELETE /people/1.json
  def destroy
    @person = Person.find(params[:id])
    @person.destroy

    head :no_content
  end
end
~~~

## 参照
* rails-api GitHub
https://github.com/rails-api/rails-api

* rails-api RubyGems
https://rubygems.org/gems/rails-api