2012年4月4日水曜日

Ruby on Rails3.2でログイン機能を実装する。

というわけで。
簡易なブログアプリを作っていて、記事の投稿・編集・削除はログインした管理者のみで行いたいので
Rails3.1で追加された認証関連機能を使ってログイン機能をつけました。

参考にしたエントリー
ASCIIcasts - “Episode 270 - Rails 3.1の認証機能"

以下作業メモ
[環境]
CentOS6.2
Ruby 1.9.3(p125)
Ruby on Rails 3.2.2

1. Gemfileにbcryptrubyを追加
Gemfile内のgem 'bcrypt-ruby', '~>3.0.0~のコメントアウトを外した上で
bundle install

2.ユーザmodelの作成
$ rails g model user name:string password_digest:string
$ rake db:migrate

※password_digestのカラム名は変更してはいけない
/app/model/users.rbにhas_secure_passwordを追加
class User < ActiveRecord::Base  
  has_secure_password  
end  
3.管理アカウントの追加 とりあえずユーザアカウントは管理用アカウント1つでいいので、新規登録画面はつけずに直接DBに追加
$rails c
User.create!(:name => "admin", :password => "hoge", :password_confirmation => "hoge")
本来はpasswordなんてカラム無いのでエラーになるはずがこれで登録できている (DB上にはハッシュ化された値で登録されている)
4.ログイン機能実装 ・まずはコントローラの生成
$rails g controller sessions
・ログインフォーム(app/view/sessions/new.html.erb)

Log in

<%= form_tag sessions_path do %>
<%= label_tag :name, 'login name' %> <%= text_field_tag :name, params[:name] %>
<%= label_tag :pass, 'password' %> <%= password_field_tag :pass , params[:pass]%>
<%= submit_tag "ログイン" %>
<% end %>
・ルートの追加 config/routes.rbに以下を追加
resources :sessions do
  end
・コントローラ処理実装 app/controller/session_contoroller.rb ログインに成功したらトップヘリダイレクト 失敗したら同じフォームを再描画
def index
      render "new" 
  end
  def create
    user = User.find_by_name params[:name]
    if user && user.authenticate(params[:pass])
      session[:user_id] = user.id
      redirect_to root_path
    else
      flash.now.alert = "Invalid"
      render "new" 
    end
  end
  def destroy
    session[:user_id] = nil
    redirect_to root_path
  end
5.ビュー用ヘルパーメソッドの定義 ビューからログインユーザを参照できるようにする app/controller/application_contoroller.rb
class ApplicationController < ActionController::Base
app/controller/application_contoroller.rb
  protect_from_forgery

  def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
  end

  helper_method :current_user
end
6.ビューにログイン機能へのパスを追加
<% if current_user == nil %>
  <%= link_to "ログイン", sessions_path %>
<% else %>
  <%= link_to 'ログアウト', session_path(current_user.id), :confirm => 'ログアウトしますか?', :method => :delete %>
<% end %>
こんな感じでログインされてなければログイン表示・ログインしていればログアウト表示に切り替える。
あとは同様にログイン中のみ新規作成等を行えるようにしていけば目的は達成できた。
しかし簡素に書けて便利ですね。

2 件のコメント:

  1. たまたま見つけたのですが、”contoroller”のスペルが間違っております。
    > rails g contoroller sessions

    返信削除
  2. ありがとうございます。修正しました

    返信削除