devise/cancancanを使ってログイン機能を実装する [Rails 4.1]


最近初めて、Rails内だけでユーザーの管理、ログインをする機能を実装しました。簡単にネットで調べた限りでは、『devise』と『cancancan』を使う方法が一番シンプルでしっくりきました。

こういった一般的な機能を実装するときにはRailsには本当に多様なライブラリがあるのが強みだなとつくづく感じます!

(07-02 21:55) 設定の追記やlocaleファイルのダウンロードなどを追記


🐡 次試すメモ

mcasimir/devise-i18n-views』で翻訳したdeviseのviewを生成できそう。次試してみます!

🎃 Gemのインストール

Gemfileに次のコードを追加して、bundle installを実行。

# User Authorization
gem 'devise'
gem 'cancancan'
# form helper
gem 'enum_help'

🤔 deviseの認証画面を作成

コンソール上で次のコマンドを実行。

# devise用の設定ファイルの作成
bundle exec rails g devise:install
# deviseの認証用のviewの作成
bundle exec rails g devise:views
# erbからhamlに変換
bundle exec rake haml:replace_erbs
# 認証ユーザーの作成
bundle exec rails g devise AdminUser
# マイグレーション(テーブルの作成)
bundle exec rake db:migrate
# ログイン後の管理画面の作成
bundle exec rails g controller admin::base index

サインアウトをgetメソッドできるようにdeviseの設定を書き直し。vim config/initializers/devise.rbを開いて次のように変更

config.sign_out_via = :delete
# ↓ 下のように変更
config.sign_out_via = :get

😼 deviseの設定

まずは、default_url_optionsの設定。config/environments/development.rbに以下を追加。

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

次に、app/views/layouts/application.html.hamlに以下を追加。

%p.notice= notice
%p.alert= alert

🚕 翻訳ファイルのダウンロード

次のコマンドを実行して、日本語のlocaleファイルをダウンロード。ついでに英語のlocaleファイルも配置変え。

wget https://raw.githubusercontent.com/tigrish/devise-i18n/master/locales/ja.yml -P config/locales/devise/
mv config/locales/devise.en.yml config/locales/devise/en.yml

😸 ルーティングの書き直し

vim config/routes.rbに管理画面へのルーティングを書き直し。

# 以下を削除
namespace :admin do
get 'base/index'
end
# 以下を追加
root 'admin/base#index' # ログイン画面をルートにする
get '/admin' => 'admin/base#index'

🏀 コントローラの書き直し

続いて、認証ユーザーのみが/adminを見れるようにvim app/controllers/admin/base_controller.rbに以下を追記。

class Admin::BaseController < ApplicationController
# ↓ これを追加
before_filter :authenticate_admin_user!
def index
end
end

🍣 動作確認

まずはWebrickを起動。

bundle exec rails s

起動したら、ブラウザでhttp://0.0.0.0:3000を起動。

スクリーンショット 2014-05-05 18.44.26

するとログイン画面がでるので、まずはユーザー登録のためにSign upを選択してユーザーを作成。ユーザーの作成が完了してログインできると、Admin::Base#indexが表示で成功。

スクリーンショット 2014-05-05 18.46.32

🎳 ユーザーの役割を分けて権限管理

次にAdminUserにroleをつけて、権限管理をしつつcancanでログインユーザーを管理する手順です。コンソールで次のコマンドを実行します。

# AdminUserにroleを追加
bundle exec rails g migration add_role_to_admin_users role
# マイグレーション(テーブルの作成)
bundle exec rake db:migrate
# cancan用の設定を追加
bundle exec rails g cancan:ability

🐹 特定のroleだけが一部の情報を見れるようにする

app/models/admin_user.rbに以下を追記。

(Rails 4。ゼロから採用された『enum』を使っています)

class AdminUser < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# ↓ 以下を追加
ROLE = {admin: "admin", member: "member"}
end

app/models/ability.rbに以下を追記。

class Ability
include CanCan::Ability
# ↓ 以下を追記
def initialize(user)
if user.admin?
can :admin, :all
elsif user.member?
can :member, :all
end
end
end

app/views/admin/base/index.html.hamlに以下を追記。

%h1 Admin::Base#index
%p Find me in app/views/admin/base/index.html.haml
# ↓ 以下を追記
- if can? :admin, current_admin_user
%p admin information
- if can? :member, current_admin_user
%p member information

vim app/views/devise/registrations/new.html.hamlにroleを追加。

.form-inputs
= f.input :email, required: true, autofocus: true
= f.input :password, required: true
= f.input :password_confirmation, required: true
# ↓ 以下の1行を追加
= f.input :role, :include_blank => false, required: true

app/views/devise/registrations/edit.html.hamlにroleを追加。

.form-inputs
= f.input :email, required: true, autofocus: true
= f.input :password_confirmation, required: false
= f.input :current_password, hint: "we need your current password to confirm your changes", required: true
# ↓ 以下の1行を追加
= f.input :role, :include_blank => false, required: true

app/controllers/application_controller.rbでroleをストロングパラメータで受け取れるように変更。

class ApplicationController < ActionController::Base
# ↓ 以下を追加
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :role
devise_parameter_sanitizer.for(:account_update) << :role
end
end

これでrole = "admin"のユーザーの場合はadmin informationが表示。

スクリーンショット 2014-05-05 21.25.16

これでrole = "member"のユーザーの場合はmember informationが表示。

スクリーンショット 2014-05-05 21.24.43

便利便利。でもいろいろハマりました。勉強になったよ!

🏈 GitHubリポジトリ

morizyun/devise_cancan_sample_app - GitHub

今回のサンプルソースです。つっこみお願いします!

🐠 参考リンク

plataformatec/devise - GitHub

devise と cancan を使って権限管理可能な管理画面を作る。 (1) - @Konboi memo

devise と cancan を使って権限管理可能な管理画面を作る。 (2) - @Konboi memo

Rails3.2でユーザー権限を細かく設定~Devise + cancan | Scimpr Blog

🍮 編集来歴

(05-05 21:25) 新規作成

(07-02 21:55) 設定の追記やlocaleファイルのダウンロードなどを追記

📚 おすすめの書籍

🖥 サーバについて

このブログでは「Cloud Garage」さんのDev Assist Program(開発者向けインスタンス無償提供制度)でお借りしたサーバで技術検証しています。 Dev Assist Programは、開発者や開発コミュニティ、スタートアップ企業の方が1GBメモリのインスタンス3台を1年間無料で借りれる心強い制度です!(有償でも1,480円/月と格安)