Everyday Rails - 9日目

modalが表示しきる前にスクリーンショットを撮っていた件を修正。
適当にsleep 0.5などとしてやると撮れた。0.2だと表示途中だった。面白い。
f:id:yossk:20141210202845p:plain
jQueryAjaxを使う場合は以下の方法が紹介されていた。
Automatically wait for AJAX with Capybara

10.その他のテスト - file upload

見たところ、Paperclipを使っているようなので、それを使い、以前書いたfeatureスペックに追加する。

thoughtbot/paperclip · GitHub

この項は1ページにも満たないが、正直とても時間がかかった。
書籍そのままだと動かない。
Paperclipのテストでの使い方と、FactoryGirlでのfixture_file_uploadの使い方が分からなかった。
一次ソースが見つからず、Stack Overflow様々だった。

$ ./bin/rails g migration add_avatar_to_users
class AddAvatarToUsers < ActiveRecord::Migration
  def change
    add_attachment :users, :avatar
  end
end
class User < ActiveRecord::Base
  has_secure_password

  has_attached_file :avatar, styles: { medium: "300x300>", thumb: "100x100>" },
    default_url: "/images/:style/missing.png"
  validates_attachment_content_type :avatar, content_type: /\Aimage\/.*\Z/

  validates :email, presence: true, uniqueness: true
end
  • spec/features/users_spec.rb
# :
    expect {
      click_link 'Users'
      click_link 'New User'
      fill_in 'Email', with: 'newuser@example.com'
      find('#password').fill_in 'Password', with: 'secret123'
      find('#password_confirmation').fill_in 'Password confirmation',
        with: 'secret123'
      attach_file 'Avatar', Rails.root.join("spec", "factories", "avatar.png")
      page.save_screenshot(sc_file('user_1.png'))
      click_button 'Create User'
    }.to change(User, :count).by(1)

    expect(User.last.avatar_file_name).to eq 'avatar.png'
# :

Featuresのテストはこれで通る。
次にControllerのテスト。

# :
RSpec.configure do |config|
# :
  FactoryGirl::SyntaxRunner.class_eval do
    include ActionDispatch::TestProcess
  end
# :
end


ruby on rails - FactoryGirl and PaperCip attachement - Stack Overflow

  • spec/factories/users.rb
FactoryGirl.define do
  factory :user do
    email { Faker::Internet.email }
    password 'secret'
    password_confirmation 'secret'

    factory :admin do
      admin true
    end

    factory :user_with_avatar do
      avatar {
        fixture_file_upload(
          Rails.root.join("spec", "factories", "avatar.png"),
          'image/png'
        )
      }
    end
  end
end
  • spec/controllers/users_controller_spec.rb
describe UsersController, type: :controller do
  # :
  describe 'Admin access' do
    before do
      set_user_session create(:admin)
    end

    it 'uploads an avatar' do
      post :create, user: attributes_for(:user_with_avatar)
      expect(assigns(:user).avatar_file_name).to eq 'avatar.png'
    end
  end
end

ポイントは、File.newだとPaperclipで使うフィールドには入らないこと。
factoryファイルでfixture_file_uploadを使うには設定がいること。
controllerのテストで書籍ではなぜかcreateしてパラメータを渡しているのでattributes_forに変えること。

今日の感想

今日やったやり方が正しいのかどうかは分からない。
このあたりのノウハウをを溜めていかないといけない。