Rails3アプリにDeviseで簡単に認証システムを組み込む

co-meetingではユーザ管理をDeviseをベースに開発しています。
開発過程でDeviseについて調べたことを、何度かに分けて書いていこうと思います。

Devise(http://rubygems.org/gems/devise)とは、Railsアプリにログインの仕組みを組み込む場合にデファクトスタンダードになっているgemで、メールによるコンファームなど必要な仕組みが揃っていて非常に便利です。*1

Rails3のインストールからプロジェクトの作成、Deviseの使い方については以下のサイトで詳しく解説されています。
http://www.oiax.jp/rails/rails3.html
チュートリアル的に習得するならこちらのページの方が参考になります。

ここでは、Deviseの導入から、独自ログインのみのシステムでDeviseを使うに当たって最低限必要と思われる設定についてのみまとめていきます。

scaffoldでアプリを生成

Deviseを試すためのアプリをscaffoldで作成しておきます。
scaffoldを使ったアプリ作成については以下を参考にしました。
Rails3のscaffoldを試す

Deviseのインストール

gemのインストール

Gemfileに以下を追加して、bundle installします。

gem 'devise', '1.4.2'
$ bundle install
Railsプロジェクトにインストール
$ rails g devise:install
hrendoh@hrendoh-UL20A:~/workspace-rails/hello-device$ rails g devise:install
      create  config/initializers/devise.rb
      create  config/locales/devise.en.yml

===============================================================================

Some setup you must do manually if you haven't yet:

  1. Setup default url options for your specific environment. Here is an
     example of development environment:

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

     This is a required Rails configuration. In production it must be 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>

===============================================================================

1. config/environments/development.rbの最後に「config.action_mailer.default_url_options = { :host => 'localhost:3000' }」を追記

  ...
  # Only use best-standards-support built into browsers
  config.action_dispatch.best_standards_support = :builtin
  
  config.action_mailer.default_url_options = { :host => 'localhost:3000' }
end

2. config/routes.rbに「root :to => "item#index"」を追記

  ...
  # This is a legacy wild controller route that's not recommended for RESTful applications.
  # Note: This route will make all actions in every controller accessible via GET requests.
  # match ':controller(/:action(/:id(.:format)))'
  root :to => "items#index"
end

Deviseはログイン、アカウントのコンファームおよびパスワードの変更の後、root :toに指定されたパスにアクセスします。*2
(public/index.htmlを消すのを忘れずに)

3. とりあえずapp/views/layouts/application.html.erbのbodyの一番上に追記

<!DOCTYPE html>
<html>
<head>
  <title>HelloDevice</title>
  <%= stylesheet_link_tag :all %>
  <%= javascript_include_tag :defaults %>
  <%= csrf_meta_tag %>
</head>
<body>
 <p class="notice"><%= notice %></p>
 <p class="alert"><%= alert %></p>
<%= yield %>

</body>
</html>
ModelをDBに反映

認証情報を保持するModelを作成して、DBに反映

$ rails g devise User
$ rake db:migrate
Controllerに認証チェックを追加

app/controller/items_controller.rbに認証チェックのフィルターを追加

  before_filter :authenticate_user!

メール送信設定

config/environments/development.rbの以下の「config.action_mailer.raise_delivery_errors = false」をコメントにする

  # Don't care if the mailer can't send
  #config.action_mailer.raise_delivery_errors = false

producation.rbはデフォルトでコメントされています。

SMTPサーバーの設定

config/environments/development.rbに以下を追記

  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
    :address => 'smtp.gmail.com',
    :port => 587,
    :authentication => :plain,
    :user_name => 'hrendoh@gmail.com',
    :password => '****'
  }
サインアップ時に確認メールを出す

サインアップ時に確認メールを送信するかどうかの設定はdeviseのモデル app/models/user.rbのdeviseメソッドの引数として指定します。
confirmableを追加します。

  devise :database_authenticatable, :registerable,:confirmable,
         :recoverable, :rememberable, :trackable, :validatable

db/migrate/nnnnnn_devise_create_users.rbのt.confirmableのコメントを外します。

   create_table(:users) do |t|
      t.database_authenticatable :null => false
      t.recoverable
      t.rememberable
      t.trackable

      # t.encryptable
      t.confirmable
      # t.lockable :lock_strategy => :failed_attempts, :unlock_strategy => :both
      # t.token_authenticatable


      t.timestamps

確認メールの「Confirm my accounts」のリンクを変更するには、config/environments/development.rbに設定する場合、以下の箇所を修正します。

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

ビューのカスタマイズ

最後にビューのカスタマイズについて説明します。

Deviseのビューをプロジェクトにコピーします。

$ rails generate devise:views
 devise:views
      invoke  Devise::Generators::SharedViewsGenerator
      create    app/views/devise/mailer
      create    app/views/devise/mailer/confirmation_instructions.html.erb
      create    app/views/devise/mailer/reset_password_instructions.html.erb
      create    app/views/devise/mailer/unlock_instructions.html.erb
      create    app/views/devise/shared
      create    app/views/devise/shared/_links.erb
      invoke  form_for
      create    app/views/devise/confirmations
      create    app/views/devise/confirmations/new.html.erb
      create    app/views/devise/passwords
      create    app/views/devise/passwords/edit.html.erb
      create    app/views/devise/passwords/new.html.erb
      create    app/views/devise/registrations
      create    app/views/devise/registrations/edit.html.erb
      create    app/views/devise/registrations/new.html.erb
      create    app/views/devise/sessions
      create    app/views/devise/sessions/new.html.erb
      create    app/views/devise/unlocks
      create    app/views/devise/unlocks/new.html.erb

生成されたそれぞれのビューを編集すると、デフォルトのビューの変わりに表示されるようになります。

例えば、ログインフォームを編集する場合は、以下のファイルを編集します。
app/views/devise/sessions/new.html.erb

*1:実際には、デフォルトの機能に独自の仕組みを追加しようとすると大抵はgemのソースを読む羽目になりそうな感じなので、システム構成が大きくなりそうなアプリケーションの場合は設計の参考にするくらいが良いかもしれません。

*2:Rails3のルーティングについてはこちら:http://guides.rubyonrails.org/routing.html