deviseで複数モデル対応とRspecでのテスト

deviseで複数モデル対応とRspecのテストの方法です。

スペルミスでテストが通らなくて、4時間くらいはまってました。みなさんもスペルミスには気を付けましょう。
かなり調べたので勉強にはなりましたが…。

configにコードを追加

$ rails g devise:isntall

これでconfig/initializers配下にdevise.rbが生成される。以下のコードのコメントアウトを外します。

config/initializers/devise.rb

config.scoped_views = true

deviseと関連したmodelを生成する

今回はadminとuserで生成したいと思います。既存のmodelも上書き可能です。

$ rails g devise user
$ rails g devise admin

各modelに対応するcontrollerの生成

各modelに対応するcontollerファイルを生成します。

$ rails g devise:controllers users
$ rails g devise:controllers admins

これでusersの場合は

  • controllers/users/confirmations_controller.rb
  • onmiauth_callbacks_controller.rb
  • passwords_controller.rb
  • registrations_controller.rb
  • sessions_controller.rb,unlocks_controller.rb

が生成されます。

各modelに対応するviewを生成する

$ rails g devise:views users
$ rails g devise:views admins

これでviews/users/confirmationsなどのviewを一気に生成してくれます。

routing設定

devise_for :users
devise_for admins

このままだとcontroller#actionがdevise/registrations#createなどになっています。
これだとcontroller/devise/confirmationsが呼ばれてしまいます。
せっかくrails g devise:controllerで生成したファイルが使われません。

そのため以下のように修正します。

  devise_for :users, :controllers => {
:sessions => 'customer_users/sessions',
:passwords => 'customer_users/passwords',
:registrations => 'customer_users/registrations'
}
devise_for :admins, :controllers => {
:sessions           => 'admin_users/sessions',
:passwords          => 'admin_users/passwords',
:registrations      => 'admin_users/registrations',
}

こうすると`users/registrations#create’などのroutingが生成されます。

$ rake routes

を叩いて変化を確認してください。
私はroutingのスペルミスでroutingが変わっていなくて、この後のテストが通らず4時間位はまってました。

modelをdevise管理下におく

modelファイルに以下を追加して、devise管理下においてください!adminも同様です。

models/user.rb

class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable

カラムを追加した場合

deviseのdefaultにカラムを追加した場合はstrong parameterを追加してください。
今回はsign up時のみ追加カラムのstrong parameterを許可してみました。

app/controllers/users/registrations_controller.rb

class Users::RegistrationsController < Devise::RegistrationsController
before_action :configure_sign_up_params, only: [:create]
# POST /resource
def create
super
end
protected
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up, keys: [:name, :agreement, :sex, :telephone_number, :address1, :address2, :status, :pay_type])
# keysの後の[]に追加カラムのシンボルを指定する
end
end

Rspecのテスト(参考)

Rspecのテストの参考例です。
今回はsignupのテストのみです。前述のrouting設定missでno route matchエラーが発生してはまりました。

factories/user.rb

FactoryGirl.define do
factory :customer_user do
sequence(:name) { |n| "test #{n}" }
profile 'test'
sequence(:email) { |n| "user#{n}@test2.com" }
password "testtesttest"
password_confirmation "testtesttest"
sex :male
agreement 1
telephone_number '000-1111-2222'
address1 '住所1'
address2 '住所2'
status :active
pay_type :CreditCard
end
end

spec/controllers/user_registrations_controller_spec.rb

require 'rails_helper'
RSpec.describe CustomerUsers::RegistrationsController, type: :controller do
before do
@request.env["devise.mapping"] = Devise.mappings[:customer_user]
@customer_user = attributes_for(:customer_user)
end
describe 'POST #sign_up' do
subject { post :create, customer_user: @customer_user}
context "正常なデータでサインアップ" do
it "サインアップできる" do
expect {
subject
}.to change(CustomerUser, :count).by(1)
end
end
end
end

@request.env["devise.mapping"] = Devise.mappings[:customer_user]でdeviseであることを明記してださい!
attributes_forでfactorygirlでテストデータを生成します。
その後のsubjectでparameterとして格納した変数を渡します。
changeで元ある件数からの変化を確認できます。
今回は元から+1されているかを確認しています。

最後に

スペルミスには気を付けましょう!

パーフェクト Ruby on Rails

パーフェクト Ruby on Rails

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です