大阪のホームページ制作会社 i.M.Design INFORMATION MEDIA DESIGN ロゴ

06-6809-5021

Columnコラム

WEBサイト制作

2015.12.02

Ruby on Rails4で簡単なログイン機能の実装方法

Ruby on Rails4で簡単なログイン機能の実装方法

今回はユーザーテーブルを作成しメールアドレスとパスワードでログインできる機能を実装します。
新規プロジェクトでユーザーテーブルまでを作成したところから説明していきます。
ユーザーテーブルを作成するまではCentOS6での環境構築後にRuby on Rails4でhello world! 的なアプリケーションを作成する方法。を参照してください。

usersテーブルにpasswordカラムを追加

・マイグレーション作成

$ bundle exec rails g migration addPasswordDigestToUsers password_digest:string

上記を行うと既存カラムの最後に新しいカラムができてしまいます。
emailカラムの後にpasswordを入力させたいのでマイグレーションを少し修正します。
※SQLiteではこれは効かないようで常に末尾に追加されます
db/migrate/20151201xxxxxx_add_password_digest_to_users.rb
class AddPasswordDigestToUsers < ActiveRecord::Migration
  def change
    # :after => :email を追加
    add_column :users, :password_digest, :string, :after => :email
  end
end

・フィクスチャにテストデータを投入する

テストデータにパスワードを追加しておかないと誰もログインできないので各ユーザーのemailの下にpassword_digestを追加します。 ※password_digestはハッシュ値です
test/fixtures/users.yml
user_1:
  id: 1
  name: "Test Taro"
  email: "test@imd-net.com" 
  password_digest: $2a$10$VWjalZaXZcp8TJpjS3U9de8osH7PwVCOpMXFWxomFkfaIHB7oUERG

・databaseを一度削除してフィクスチャの流し込みを実行する

$ bundle exec rake db:migrate:reset
$ bundle exec rake db:fixtures:load

Userモデルにパスワードを扱うための記述を追加

Userモデルにhas_secure_passwordを追加する

※これを追加するとパスワードの暗号化や認証の機能が追加されます。
app/models/user.rb
class User < ActiveRecord::Base
  # 以下を追加することで passwordとpassword_confirmationが自動で追加され、存在チェックのバリデーションも設定されます。
そして、password_digestへ暗号化されて登録されます。
  has_secure_password
end

暗号化のためにGemfileに下記gemを有効化してbundle installする

gem 'bcrypt', '~> 3.1.7'

bundle install

ログインチェック処理追加

全コントローラの共通クラスに、ログインしてない場合は強制的にログイン画面に遷移する処理を追加する

app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.

  ### ここから追加 ###
  before_action :user_logged_in? #ログインチェックの事前認証

  def reset_user_session
    session[:user] = nil
    @current_user = nil
  end

  def user_logged_in?
    user_id = session[:user]
    if user_id then
      begin
        @current_user = User.find(user_id)
      rescue ActiveRecord::RecordNotFound
        reset_user_session
      end
    end

    # current_userが取れなかった場合はログイン画面にリダイレクト
    unless @current_user
      flash[:referer] = request.fullpath
      redirect_to "/login"
    end
  end
  ### ここまで追加 ###
end
上記までを行えばlocalhost:3000/usersにアクセスしたら/loginにリダイレクトされることを確認できます。

ログイン用のコントローラを作成

ログイン画面の表示やログイン処理を実装するコントローラを作成します。

rails generate で自動作成

app/controllers/application_controller.rb
$ bundle exec rails g controller session index --no-assets

sessionというコントローラ名でindexだけ作作成。css、jsは使わないので--no-assetsとします。

リソースでセッションを作成する。

config/routes.rb
resources :session, path: "login", only: [:index, :create] do
  collection do
    delete  '/', to: "session#delete"
  end
end

コントローラ編集 1

ログイン画面表示するときはログインチェック不要。 セッションコントローラに以下を追加して、全コントローラ共通のbefore_actionをスキップさせます。 app/controllers/session_controller.rb
skip_before_action :user_logged_in?

ログイン画面表示時に使用する変数を設定する処理を追加する

app/controllers/session_controller.rb
def index
  @user = User.new
end

ビュー編集

app/views/session/index.html.erb
<h1>Login</h1>

<%= form_for(@user, url: session_index_path, method: :post) do |f| %>
  <% if flash[:error] %>
    <div id="error_explanation">
      <h2>ユーザー名またはパスワードが違います</h2>
    </div>
  <% end %>

  
  <%= hidden_field_tag :referer, flash[:referer] %>

  <div class="field">
    <%= f.label :email %>
<%= f.text_field :email %> </div> <div class="field"> <%= f.label :password %>
<%= f.password_field :password %> </div> <div class="actions"> <%= f.submit %> </div> <% end %>
ここまで行ったらlocalhost:3000/usersにアクセスするとログイン画面にリダイレクトされます。

コントローラ編集 2

sessions_controllerのcreateメソッドを実装してログインできるようにします。
ログアウト用処理のdeleteも実装。
app/controllers/session_controller.rb
def create
  @user = User.find_by(email: user_params[:email])
  if @user && @user.authenticate(user_params[:password])
    reset_user_session
    session[:user] = @user.id
    redirect_to params[:referer].present? ? params[:referer] : users_path
  else
    @user = User.new
    flash.now[:referer] = params[:referer]
    flash.now[:error] = true
    render :index
  end
end

def delete
  reset_user_session
  redirect_to session_index_url
end

private
  def user_params
    params.require(:user).permit(:email, :password)
  end

ログアウト用のリンクを追加レイアウトにログアウト用のリンクを追加する

<%= yield %>の上に以下を追記する。
app/views/layouts/application.html.erb
<%= link_to "Logout", session_index_path, method: :delete %>

完成した結果は下記のようになります

login01

login02

login03

まとめ

今回の内容で簡単なメールアドレスとパスワードでのログイン機能が実装できました。今回はBootstrapでレイアウトを整えませんでしたが、やはり見栄えが寂しく感じます。 Ruby on Rails4でレイアウトを整えたい方はRuby on Rails4でransackを使った検索機能の実装を参考にしていただければ幸いです。

この記事を共有する