読者です 読者をやめる 読者になる 読者になる

Everyday Rails - 11日目

Ruby Rails Everyday Rails

10.その他のテスト VCR、geocorder

VCRは外部API用、結果保存ライブラリかな。

vcr/vcr · GitHub

geocorderは地図情報(位置情報か)を取得するライブラリ。

alexreisner/geocoder · GitHub

Gemfileに、それぞれを追加。
以下テストを通すために簡単に。
一点、UserとAddressのresourcesを入れ子にしたかったが、うまく動作しなかったので断念した。

  • Address関連
./bin/rails g scaffold Address latitude:float longitude:float street city state
  • app/models/address.rb
class Address < ActiveRecord::Base
  geocoded_by :address
  before_save :geocode
  belongs_to :user

  def address
    "#{street}, #{city} #{state}"
  end
end

geocoded_byで指定した事により、addressメソッドで指定した文字列から、位置情報を取得する。

  • app/models/user.rb

has_one追加

class User < ActiveRecord::Base
  has_secure_password
  has_one :address
  # :
end
  • spec/models/address_spec.rb
require 'rails_helper'

describe Address, type: :model do
  describe 'geocoding' do
    it 'geocoding a new address' do
      VCR.use_cassette('allen_fieldhouse') do
        address = FactoryGirl.create(
          :address,
          street: '1651 Maismith Drive',
          city: 'Lawrence',
          state: 'KS'
        )

        expect(address.latitude).to eq 38.954145
        expect(address.longitude).to eq -95.25277919999999
      end
    end
  end
end
  • feature用
  • routeとcontrollerにusers#show追加
  • app/views/users/show.html.haml
%h1 Edit User

%table
  %thead
    %tr
      %th Email
      %th Address
  %tbody
    %tr
      %td= @user.email
      %td#address
        = @user.address.try(:address)
        = link_to 'Edit', edit_address_url(@user, @user.address)
  • app/views/addresses/_form.html.haml
= form_for @address do |f|
  - if @address.errors.any?
    #error_explanation
      %h2= "#{pluralize(@address.errors.count, "error")} prohibited this address from being saved:"
      %ul
        - @address.errors.full_messages.each do |msg|
          %li= msg

  .field
    = f.label :street
    = f.text_field :street
  .field
    = f.label :city
    = f.text_field :city
  .field
    = f.label :state
    = f.select :state, ["US", "JP", "KS"]
  .actions
    = f.submit 'Update Address'
  • app/controllers/addresses_spec.rb
  def update
    if @address.update(address_params)
      redirect_to user_path(@address.user), notice: 'Successfully updated address.'
    else
      render :edit
    end
  end
  • spec/features/addresses_spec.rb
require 'rails_helper'

feature 'Addresses', type: :feature, js: true do
  let(:user) { create(:admin) }
  let(:address) do
    VCR.use_cassette('busch_stadium') do
      create(
        :address,
        user: user,
        street: '700 Clark Avenue',
        city: 'St. Louis',
        state: 'MO',
      )
    end
  end

  background do
    sign_in user
  end

  scenario 'user edits a address' do
    old_address = address
    visit user_path(user)

    save_screenshot(sc_file('address_1.png'))

    within '#address' do
      click_link 'Edit'
    end

    save_screenshot(sc_file('address_2.png'))

    VCR.use_cassette('allen_fieldhouse') do
      fill_in 'Street', with: '1651 Naismith Drive'
      fill_in 'City', with: 'Lawrence'
      select 'KS', from: 'State'
      click_button 'Update Address'
    end

    save_screenshot(sc_file('address_3.png'))
    expect(current_path).to eq user_path(user)
    expect(page).to have_content 'Successfully updated address.'
    expect(page).to have_content '1651 Naismith Drive'
    expect(page).not_to have_content old_address.street
  end
end

f:id:yossk:20141212235900p:plain
f:id:yossk:20141212235914p:plain
f:id:yossk:20141212235924p:plain

細かいところを帳尻があうように書籍とはちょっと変えている。

今日の感想

今日使用したgemは二つとも使ったことがなかった。
使い方が分かるまで時間がかかった。
routingの入れ子の際のformの指定がうまくいかなかった。
form_for [@user, @address] などとしたがだめだった。
また調査しておく。