Everyday Rails - 12日目

続けたい日記が続けられなかった。
Android本は返却要請があったので、中止。残念。
しかし、あの本は良かった。

Everyday Rails続き!

p.106、107 APIのテスト

Web APIのテスト。
Web APIってただJSON形式などで返しとけばOKなんだろ?って思ってたけど、そんな単純な話ではないようだ。

せっかくなので、grapeというgemを使用してみた。

intridea/grape · GitHub

  • config/application.rb
# :
    config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb')
    config.autoload_paths += Dir[Rails.root.join('app', 'api', '*')]
# :
  • app/api/v1/contacts.rb
module Contacts
  class API < Grape::API
    version 'v1', using: :path, vendor: 'contacts'
    format :json
    prefix :api

    resource :contacts do
      desc "Return a Contact."
      params do
        requires :id, type: Integer, desc: "Contact ID."
      end

      route_param :id do
        get do
          begin
            Contact.find params[:id]
          rescue
            {}
          end
        end
      end

      desc "Update a Contact"
      route_param :id do
        params do
          requires :contact, type: Hash do
            requires :firstname, type: String, desc: 'Contact Firstname.'
            requires :lastname, type: String, desc: 'Contact Lastname.'
            requires :email, type: String, desc: 'Contact Email.'
          end
        end
        patch do
          begin
            contact = Contact.find params[:id]
            contact.update({
              firstname: params[:contact][:firstname],
              lastname: params[:contact][:lastname],
              email: params[:contact][:email]
            })
            contact
          rescue
            {}
          end
        end
      end
    end
  end
end
  • config/routes.rb
# :
mount Contacts::API => "/"
# :
  • ./spec/requests/api/v1/contacts_spec.rb
require 'rails_helper'

describe 'Contacts API', type: :request do
  it 'sends and individual contact' do
    contact = create(:contact)

    get "/api/v1/contacts/#{contact.id}", nil, \
      { 'HTTP_ACCEPT' => 'application/vnd.contacts.v1' }
    expect(response.code).to eq "200"

    json = JSON.parse(response.body)
    expect(json['firstname']).to eq contact.firstname
    expect(json['lastname']).to eq contact.lastname
    expect(json['email']).to eq contact.email
  end

  it 'update a contact' do
    contact = create(:contact)
    attrs = attributes_for(:contact)

    patch "/api/v1/contacts/#{contact.id}", { contact: attrs }, \
      { 'HTTP_ACCEPT' => 'application/vnd.contacts.v1' }
      expect(response.code).to eq "200"
    json = JSON.parse(response.body)
    expect(json['id']).to eq contact.id
    expect(json['firstname']).to eq attrs[:firstname]
    expect(json['lastname']).to eq attrs[:lastname]
    expect(json['email']).to eq attrs[:email]
  end
end
  • 結果

f:id:yossk:20141227224312j:plain

今日の感想

grapeの使い方が全然分からなくて苦労した。
これであっているのかもよくわからない。
普通にControllerで対応した方が全然楽な気がするが、それでダメな理由がよくわからない。
よくわからないことだらけ。