目的
Deviseでユーザー認証を行い、CanCanで権限管理をする。
新規ユーザーは、管理者のみ作成可能
E-MailをユーザーIDとして利用しない
参考
https://github.com/plataformatec/devise/wiki
http://kitbc.s41.xrea.com/main/?use_devise
http://sinki.cc/blog/archives/130
http://d.hatena.ne.jp/dimros/20110326/1301145073
インストール
Gemfileに追記
# Authentication gem 'devise' group :development do gem 'erb2haml' gem 'haml2slim' end
gemをインストール
bundle install
Devise設定
Deviseインストール
rails g devise:install
=============================================================================== Some setup you must do manually if you haven't yet: 1. Ensure you have defined default url options in your environments files. Here is an example of default_url_options appropriate for a development environment in config/environments/development.rb: config.action_mailer.default_url_options = { :host => 'localhost:3000' } In production, :host should be set to the actual host of your application. 2. Ensure you have defined root_url to *something* in your config/routes.rb. For example: root :to => "home#index" 3. Ensure you have flash messages in app/views/layouts/application.html.erb. For example: <p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p> 4. If you are deploying Rails 3.1 on Heroku, you may want to set: config.assets.initialize_on_precompile = false On config/application.rb forcing your application to not access the DB or load models when precompiling your assets. ===============================================================================
インストール時に表示されたメッセージに従って、設定
- config/environments/development.rb に記述を追加
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
ログイン後は、config/routes.rbに記載したrootに戻ってくるとのことだからrootを設定
- config/routes.rb
root :to => "home#index"
※Twitter Bootstrapですでに記述済み
application.html.hamlにnoticeとalertを設定
- app/views/layouts/application.html.slim
- yieldの上部に記述
p.notice= notice -if alert.present? p.alert= alert
- 以下の記述だと、枠が表示される
p.notice= notice p.alert= alert
- config/application.rb
config.assets.initialize_on_precompile = false
認証用モデルを作成
rails g devise user user_id:string user_name:string invoke active_record create db/migrate/20120611131651_devise_create_users.rb create app/models/user.rb invoke rspec create spec/models/user_spec.rb insert app/models/user.rb route devise_for :users
ビューを生成
rails g devise:views
_links.erbをリネーム
mv app/views/devise/shared/_links.erb app/views/devise/shared/links.html.erb
※後述のhaml変換が行われないため
生成されたビューはerbなので、hamlに変換する
rake haml:convert_erbs
hamlをslimに変換する
for i in `find app/views/devise -name '*.haml'` ; do haml2slim $i ${i%haml}slim ; done
erb,hamlを削除
for i in `find app/views/devise -name '*.erb'` ; do rm $i ; done for i in `find app/views/devise -name '*.haml'` ; do rm $i ; done
links.html.slimをリネーム
mv app/views/devise/shared/links.html.slim app/views/devise/shared/_links.slim
Userモデルを以下のように変更
- ./app/models/user.rb
class User < ActiveRecord::Base # Include default devise modules. Others available are: # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :rememberable, :trackable, :validatable, :authentication_keys => [:user_id] # Setup accessible (or protected) attributes for your model attr_accessible :user_name, :user_id, :email, :password, :password_confirmation, :remember_me # attr_accessible :title, :body def email_required? false end end
マイグレーションファイル一部修正
- ./db/migrate/20120611131651_devise_create_users.rb
修正前:
add_index :users, :email, :unique => true
修正後:
add_index :users, :user_id, :unique => true
rake db:migrate
ルーティング設定に以下が追記されていることを確認
- config/routes.rb
devise_for :users
を
devise_for :users, :path => "auth", :path_names => { :sign_in => 'login', :sign_out => 'logout', :password => 'secret', :confirmation => 'verification', :unlock => 'unblock', :registration => 'register', :sign_up => 'sign_up' }
に変更
Deviseの簡単な使い方
コントローラーの最初などに埋め込む
認証済みかどうかチェックし、認証していない場合はログイン画面へリダイレクトされる
before_filter :authenticate_user!
現在ユーザーがログイン中か否か
user_sined_in?
ログインするためのパス
new_user_session_path
ログアウトするためのパス
destroy_user_session_path
ログイン済みのユーザーオブジェクト
current_user
おまけ
http://localhost:3000/login
↓リダイレクト
http://localhost:3000/auth/login
- config/routes.rb
match "login", :to => redirect("/auth/login"), :as => "login"
日本語化
- config/application.rb
config.i18n.default_locale = :ja
ja.ymlをダウンロード
wget https://raw.github.com/svenfuchs/rails-i18n/master/rails/locale/ja.yml -P ./config/locales/
devise.ja.ymlをダウンロード ( http://pastebin.com/LvFTDgHj )
wget http://pastebin.com/raw.php?i=LvFTDgHj -O ./config/locales/devise.ja.yml
- config/locales/devise.ja.yml をちょっと修正
ja: "Sign in": "ログイン" "Registration": "ユーザー登録" "Sign up": "ユーザー登録" "Update": "更新" "Forgot your password?": "パスワード忘れはこちら" "Send me reset password instructions": "パスワード再発行" "Resend confirmation instructions": "パスワード再発行" "Didn't receive confirmation instructions?": "確認メールの再送信" "Didn't receive unlock instructions?": "アカウント凍結解除メールの再送信" errors: messages: expired: "は期限切れになりました。登録し直してください。" # expired: "has expired, please request a new one" not_found: "は見つかりませんでした" # not_found: "not found" already_confirmed: "は既に登録済みです" # already_confirmed: "was already confirmed" not_locked: "は凍結されていません" # not_locked: "was not locked" not_saved: one: "%{resource}にエラーが発生しました。" # one: "1 error prohibited this %{resource} from being saved:" other: "%{resource}に%{count}個のエラーが発生しました。" # other: "%{count} errors prohibited this %{resource} from being saved:" devise: failure: already_authenticated: 'すでにログインしています。' # already_authenticated: 'You are already signed in.' unauthenticated: 'ログインしてください。' # unauthenticated: 'You need to sign in or sign up before continuing.' unconfirmed: '本登録を行ってください。' # unconfirmed: 'You have to confirm your account before continuing.' locked: 'あなたのアカウントは凍結されています。' # locked: 'Your account is locked.' invalid: 'ユーザーIDかパスワードが違います。' # invalid: 'メールアドレスかパスワードが違います。' # invalid: 'Invalid email or password.' invalid_token: '認証キーが不正です。' # invalid_token: 'Invalid authentication token.' timeout: 'セッションがタイムアウトしました。もう一度ログインしてください。' # timeout: 'Your session expired, please sign in again to continue.' inactive: 'アカウントがアクティベートされていません。' # inactive: 'Your account was not activated yet.' sessions: signed_in: 'ログインしました。' # signed_in: 'Signed in successfully.' signed_out: 'ログアウトしました。' # signed_out: 'Signed out successfully.' passwords: send_instructions: 'パスワードのリセット方法を数分以内にメールでご連絡します。' # send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.' updated: 'パスワードを変更しました。' # updated: 'Your password was changed successfully. You are now signed in.' updated_not_active: 'パスワードを変更しました。' # updated_not_active: 'Your password was changed successfully.' send_paranoid_instructions: "データベースにメールアドレスが存在する場合は、パスワード変更ページへのリンクがあるメールをお送りします。" # send_paranoid_instructions: "If your e-mail exists on our database, you will receive a password recovery link on your e-mail" confirmations: send_instructions: '登録方法を数分以内にメールでご連絡します。' # send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.' send_paranoid_instructions: 'データベースにメールアドレスがあった場合は、登録方法を数分以内にメールでご連絡します。' # send_paranoid_instructions: 'If your e-mail exists on our database, you will receive an email with instructions about how to confirm your account in a few minutes.' confirmed: 'アカウントを登録しました。' # confirmed: 'Your account was successfully confirmed. You are now signed in.' registrations: signed_up: 'アカウントを登録しました。' # signed_up: 'アカウント登録を受け付けました。確認のメールをお送りします。' # signed_up: 'You have signed up successfully. If enabled, a confirmation was sent to your e-mail.' inactive_signed_up: 'アカウント登録を受け付けました。%{reason}ため、ログインできませんでした。' # inactive_signed_up: 'You have signed up successfully. However, we could not sign you in because your account is %{reason}.' updated: 'アカウントを更新しました。' # updated: 'You updated your account successfully.' destroyed: 'アカウントを削除しました。またのご利用をお待ちしております。' # destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.' reasons: inactive: 'アクティベートされていない' # inactive: 'inactive' unconfirmed: '確認されていない' # unconfirmed: 'unconfirmed' locked: '凍結されている' # locked: 'locked' unlocks: send_instructions: 'アカウントの凍結解除方法を数分以内にメールでご連絡します。' # send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.' unlocked: 'アカウントを凍結解除しました。' # unlocked: 'Your account was successfully unlocked. You are now signed in.' send_paranoid_instructions: 'アカウントが存在した場合は、アカウントの凍結解除方法を数分以内にメールでご連絡します。' # send_paranoid_instructions: 'If your account exists, you will receive an email with instructions about how to unlock it in a few minutes.' omniauth_callbacks: success: '%{kind}アカウントから承認されました。' # success: 'Successfully authorized from %{kind} account.' failure: '"%{reason}"であるため、%{kind}から承認されませんでした。' # failure: 'Could not authorize you from %{kind} because "%{reason}".' mailer: confirmation_instructions: subject: 'アカウントの登録方法' # subject: 'Confirmation instructions' reset_password_instructions: subject: 'パスワードの再設定' # subject: 'Reset password instructions' unlock_instructions: subject: 'アカウントの凍結解除' # subject: 'Unlock Instructions'
- config/locales/attributes.ja.yml
ja: activerecord: attributes: user: email: 'メールアドレス' password: 'パスワード' password_confirmation: 'パスワード(再入力)' remember_me: 'ログイン状態を保持する post: title: '題名' body: '内容'
- config/locales/helpers.ja.yml
ja: helpers: submit: create: "登録する" update: "更新する" submit: "保存する" label: user: email: "メールアドレス" password: "パスワード" title: new: '新規投稿'
- config/locales/views.ja.yml
ja: devise: sessions: new: user_id: "ユーザーID" password: "パスワード" remember_me: "ログイン状態を保持する" registrations: new: user_name: "ユーザー名" user_id: "ユーザーID" password: "パスワード" password_confirmation: "パスワード(再入力)" edit: edit: "登録情報の修正" user_name: "ユーザー名" user_id: "ユーザーID" password: "変更後のパスワード" leave_blank_if_you_dont_want_to_change_it: "(変更の必要がなければ,空にしておいて下さい。)" password_confirmation: "確認のためもう一度パスワードを入力して下さい。" current_password: "現在のパスワード" we_need_your_current_password_to_confirm_your_changes: "(認証のため現在のパスワードを入力して下さい。)" remove_account: "アカウントを削除" confirm: "本当によろしいですか?" back: "戻る"
ログイン画面の日本語化
- app/views/devise/sessions/new.html.slim
= twitter_bootstrap_form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| = f.inputs t 'Sign in', :class => 'sign_in' do = f.text_field :user_id, t(".user_id") = f.password_field :password, t(".password") - if devise_mapping.rememberable? = f.check_box :remember_me, t(".remember_me") = f.actions do = f.submit t "Sign in"
- app/views/devise/registrations/new.html.slim
= twitter_bootstrap_form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| = devise_error_messages! = f.inputs t 'Sign up', :class => 'sign_in' do = f.text_field :user_name, t(".user_name") = f.text_field :user_id, t(".user_id") = f.password_field :password, t(".password") = f.password_field :password_confirmation, t(".password_confirmation") = f.actions do = f.submit t "Sign up"
- app/views/devise/shared/_links.slim
- if controller_name != 'sessions' = link_to "#{t "Sign in"}", new_session_path(resource_name) br/ - if devise_mapping.registerable? && controller_name != 'registrations' = link_to "#{t "Sign up"}", new_registration_path(resource_name) br/ - if devise_mapping.recoverable? && controller_name != 'passwords' = link_to "#{t "Forgot your password?"}", new_password_path(resource_name) br/ - if devise_mapping.confirmable? && controller_name != 'confirmations' = link_to "#{t "Didn't receive confirmation instructions?"}", new_confirmation_path(resource_name) br/ - if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' = link_to "#{t "Didn't receive unlock instructions?"}", new_unlock_path(resource_name) br/ - if devise_mapping.omniauthable? - resource_class.omniauth_providers.each do |provider| = link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider) br/