Edited at

User認証を簡単に作れるDevise gemを調べた

More than 5 years have passed since last update.


はじめに

Devise gem で出来ること


  • webの会員登録のフォームを簡単に作れる(新規登録画面・login画面・etc...)

  • sign_in filterなど会員サイトを作るときに必要なhelperが多く用意されている

  • facebookなどのominiauthを使うことができる

こんなことが出来るDevise gemを使ってみたい!ってことで調べたもののまとめです。今回は公式ドキュメンを調べましたので書いてあることは公式とほぼ変わらないと思います。⬇から早速説明になります。


deviseを使う

divise3.0はrails3.2以上で動きます。Gemfileに追加してください

gem 'devise'

そしたらbundleコマンドを使ってinstallしてください

deviseのインストールとGemfileの追加が終わったらgeneratorを走らせる必要があります。

rails generate devise:install

genaratorはすべてのdeviseの設定オプションをインストールするので一回確認しといてください。これが終わったのならdevise modelを使う準備は完了です。

rails generate devise MODEL

MODELの部分はユーザーのアプリケーションとして使う名前で置き換えてください。多くの場合はUseやAdminと言ったものが使われます。これはもし既に存在していなければ新規にmodelを作り、deviseのモジュール設定をしてくれます。次にrake db:migrateをしてmigrationファイルを作ります。またgeneratorはDevise controllerを示すように config/routes.rbを設定してくれます。

( 注意)既にappを作り始めていたのならやり直してください。さもなければroute helperのエラーやloginできないといったエラーが出るでしょう。


controllerのfilterとhelpers

DeviseはcontrollerとViewの中で使えるhelperを使うことができます。controllerをset upするときにbefore_filterを加えるだけでuserがauthenticateか判断することが出来ます。

before_filter :authenticate_user!

userがsign_inしているか判断できるhelperもあります。

user_signed_in?

現在sign-inしているuserを得るhelperもあります。

current_user

またuserの活動範囲を確認できます

user_session

userがsign-inしたり、パスワードを更新したらroot_pathにredirectされます。例えばuser:resourceならばuser_root_pathが存在すればそこに、なければdefaltのroot_pathが使われます。

root to: "home#index"

またafter_sign_in_path_forafter_sign_out_path_forを使ってredirect先を上書きすることも出来ます。

最後に、mailerの為にurl_optionをすべての環境に設定する必要があります。ここでは"config/environments/development.rb"に設定します。

config.action_mailer.default_url_options = { :host => 'localhost:3000' }

(メモ)もしuserといった devise model を使わずに member を使うのならばhelperはこのようになります

before_filter :authenticate_member!

member_signed_in?

current_member

member_session


Modelの設定

modelの devise method は modules の設定を受けます。たとえば暗号化するアルゴリズムを使いたいのなら

devise :database_authenticatable, :registerable, :confirmable, :recoverable, :stretches => 20

:stretchesを除き、:pepper, :encryptor, :confirm_within, :remember_for, :timeout_in, :unlock_in, other valuesで設定することが出来ます。devise:install が使われたときに作られたfileで詳細を見ることが出来ます。


強調するパラメーター

あなたのviewをカスタマイズするときフォームに新しい特徴を追加することが出来ます。このsanitizationパラメーターはRails4になってmodelからcontrollerに移動しました。Deviseがコレに関する扱いをするものは同様にcontrollerに移動しています。たった3つのactionでどんなパラメーターでもmodelに伝えることが出来ます。それ故sanitizationを必要と知っています。名前とパラメーターの許可はdefaultではこのようになっています。


  • sign_in((Devise::SessionsController#new) - emailのような承認キーがある場合のみ許可されます

  • sign_up(Devise::RegistrationsController#create) - 証明キーにpasswordとpassword_confirmationを追加するのを許可します

  • account_update(Devise::RegistrationsController#update) - 証明キーにpassword, password_confirmation, current_passwordを追加するのを許可します。(the lazy way™)のようなパラメーターを追加で許可したい場合はApplicationControllerに簡単なbefore_filterをすることでできます。

class ApplicationController < ActionController::Base

before_filter :configure_permitted_parameters, if: :devise_controller?

protected

def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :username
end
end

defaltの設定を完全に変えたり、習慣的振る舞いを作るためにpass a blockを作ることも出来ます。

def configure_permitted_parameters

devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :email) }
end

もしあなたが複数のDevise modelを持っているのならmodelごとに異なったsanitizerパラメーターをset upすることができます。その場合、私たちはDevise::ParameterSanitizerから継承し、自身のロジックを追加することを推奨します

class User::ParameterSanitizer < Devise::ParameterSanitizer

def sign_in
default_params.permit(:username, :email)
end
end

このときにcontrollerに使うことを設定してください。

class ApplicationController < ActionController::Base

protected

def devise_parameter_sanitizer
if resource_class == User
User::ParameterSanitizer.new(User, :user, params)
else
super # Use the default one
end
end
end

上記の例では:usernameと:emailの両方を使うためのパラメーターを許可してます。パラメータを設定する愚かでない方法はcustom controllerの上にbefore_filterを定義することによって出来るでしょう。私たちは設定の仕方とcontrollerのカスタマイズ方法をsectionの流れに従って記述しました。


Viewの設定

私たちはDeviseを使い簡単にuser認証画面を作ることが出来ます。しかし、この方法でなくても自分で作ることも出来ます。Deviseはengineですから、すべてのViewはgemの内側にあります。これらのviewは作り始めを助けれくれますが、後に変えたいと思うでしょう。その場合はgeneratorを使うことでviewをあなたのアプリケーションにコピーしてくれます。

rails generate devise:views

もしUserやAdminといったDevise modelがあるのならmodelもviewと同じように編集したいと思うでしょう。幸運なことにmodelを改造するのはviewよりも簡単です。"config.scoped_views = true"を "config/initializers/devise.rb"の中に書くだけでいいのです。

これが終わると"users/sessions/new" や "admins/sessions/new"に基づいたviewを持つことができるようになります。 scopeの中にviewが見つからなかったら"devise/sessions/new"というdefaultのviewが使われます。また選んだviewを使うためにgeneratorを使うことも出来ます。

rails generate devise:views users


controllerの設定

viewのcustomizationレベルが十分でないのなら、以下の手順ですべてのcontrollerをカスタマイズすることが出来ます。

1,Admins::SessionsController:のようなcustom controller を作ります。

class Admins::SessionsController < Devise::SessionsController

end

(注意)この例はapp/controller/admins/というディレクトリが既に作られているという前提で進めています

2,使うcontrollerのrouterを書きます

devise_for :admins, :controllers => { :sessions => "admins/sessions" }

3.controllerに変化を加えると"devise/sessions"のviewが使えなくなるので忘れずに"devise/sessions"を"admins/sessions"にコピーしてください。

Deviseはsign_inが成功したか失敗したかflash messageでuserに伝えることが出来ることを覚えていてください。Deviseはあなたのアプリが適切なに"flash[:notice]"や"flash[:alert]"を呼び出すことを期待しています。すべてのflash hash を出力したり、Deviseのhash keyから:timedout keyを削除することの無いようにしてください。


Routesの設定

Deviseはdafalutのroutesがあります。もしそれらをカスタマイズする必要あるのならdevise_for methodを使ってください。これは :class_name, :path_prefixといったname_pathを変えることが出来ます。

devise_for :users, :path => "auth", :path_names => { :sign_in => 'login', :sign_out => 'logout', :password => 'secret', :confirmation => 'verification', :unlock => 'unblock', :registration => 'register', :sign_up => 'cmon_let_me_in' }

詳細はdevise_forというdocumentationを確認してください。

もし "/sign_in"だけでなく"/users/sign_in"のようにもっと深く変更を加えたいのならdevise_scopeをrouterに加えてください。

devise_scope :user do

get "sign_in", :to => "devise/sessions#new"
end

このように "/sign_in" をするとscopeは:userに限定されます。(注意)devise_scopeは通称なので気をつけてください


I18n

Deviseのflash message はI18nで使うことが出来ます。

en:

devise:
sessions:
signed_in: 'Signed in successfully.'

あなたはresourseに基づく固有のmessageをrouteの設定の中に書くことが出来ます

en:

devise:
sessions:
user:
signed_in: 'Welcome user, you are signed in.'
admin:
signed_in: 'Hello admin!'

Devise mailerはsubject messageに似たモノを使うことが出来ます

en:

devise:
mailer:
confirmation_instructions:
subject: 'Hello everybody!'
user_subject: 'Hello User! Please confirm your email'
reset_password_instructions:
subject: 'Reset instructions'

local fileを見ることですべてのメッセージを確認できます。また、どのように翻訳されているか興味があるならこのwikiで確認することが出来ます。

https://github.com/plataformatec/devise/wiki/I18n


Test helper

Deviseはspec機能を使ったいくつかのhelperを持っています。この機能を使うには test/test_helper.rbfileに以下を付け加える必要があります。

class ActionController::TestCase

include Devise::TestHelpers
end

もしあなたがRspecを使っているのならspec/support/devise.rb:の内側に以下を記述して下さい。

RSpec.configure do |config|

config.include Devise::TestHelpers, :type => :controller
end

これでsign_inとsign_outメソッドを使う準備ができました。これはcontrollerと同じ様な機能を持っています。

sign_in :user, @user   # sign_in(scope, resource)

sign_in @user # sign_in(resource)

sign_out :user # sign_out(scope)
sign_out @user # sign_out(resource)

あなたは2つのことを心にとどめておく必要があります

1.このhelperはcapybaraなどとは統一することが出来ません機能的なテストだけを使うことが出来ます。そのかわりuser formは既に埋まった状態で使うことが出来ます

2.もしDevise controllerやDeviseを継承したcontrolelrのテストをしたいのならば、使う前にrequestをする必要があります。Deviseはroutesから情報を受け取っているのでこれは不可欠です。しかし、testはrouterを使わないので使うことを明確に示すことが必要と成ります。例えば、user scopeのtestをしたいのならこのようにしてください

@request.env["devise.mapping"] = Devise.mappings[:user]

get :new


Omniauth

Deviseはominiauthのサポートを使ったユーザー認証を使用することが出来ます。使うにはconfig/initializers/devise.rbにominiauthの設定を明記してください。

config.omniauth :github, 'APP_ID', 'APP_SECRET', :scope => 'user,public_repo'

ominiauthoの機能を使いたい場合は専用のwikiがあるのでこれを良く読んでください


multiple model設定

Deviseは好きな数だけDevise modelを作ることが出来ます。User model 以外にauthenticationとtime out機能を付け加えたAdmin modelを作りたいのなら以下のようにしてください

# Create a migration with the required fields

create_table :admins do |t|
t.string :email
t.string :encrypted_password
t.timestamps
end

# Inside your Admin model
devise :database_authenticatable, :timeoutable

# Inside your routes
devise_for :admins

# Inside your protected controller
before_filter :authenticate_admin!

# Inside your controllers and views
admin_signed_in?
current_admin
admin_session

この代わりにDevise generatorを使うだけでも大丈夫です。

このようなmodelは異なったrouteを持つことを覚えておいてください。sign_inやsign_outなどと同じcontrollerを共有して使うことは出来ません。同じactionで異なったroleを使いたい場合は role-based approach を使うことを勧めます。


追加情報


Heroku(重要)

Rails3.1でDeviseをherokuで使いたいのならこのような設定が必要です

config.assets.initialize_on_precompile = false

その他の潜在的問題についてはコレを読んでください http://guides.rubyonrails.org/asset_pipeline.html