地方でリモートワーク

プログラミング、先物、fx,仮想通貨なんでもやります

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