FreeCamp      

【Rails】Gem devise ユーザー認証機能の作成

世の中の多くのアプリケーションにはユーザー認証機能が備えられています。
投稿したり購入、いいねなどはユーザーを識別して行われるからです。
そこで、Railsを用いたアプリケーションにユーザー認証機能を追加してみます。

目次

  1. Scaffoldで簡易アプリケーションの作成
  2. Gem deviseの導入
  3. ログイン・ログアウトの実装
  4. ログインユーザー・ゲストユーザーの権限設定
  5. ユーザーと投稿の関連付け
  6. 完成ソースコード

1. Scaffoldで簡易アプリケーションの作成

まずはじめにScaffoldを用いて投稿アプリケーションを作成します。
以下を参考にして作成します。

2. Gem deviseの導入

まずはGemfileにdeviseに記載し、bundle installを行います。

...追記
gem 'devise'
$ bundle

そして、deviseをインストールし、モデル(nameを追加)を作成していきます。

$ rails g devise:install
$ rails g devise User name:string

Userモデルにnameカラムを追加しました。
deviseはデフォルトでemailとpasswordのユーザー認証となっています。
これから名前でログインできるよう設定をしていきます。

まずは、deviseのviewとcontrollerを作成していきます。

$ rails g devise:views users
$ rails g devise:controllers users

ルーティングを編集します。

...編集
devise_for :users
↓
devise_for :users, controllers: {
  sessions: 'users/sessions',
  registrations: 'users/registrations'
}

viewを編集します。

...編集
<div class="field">
  <%= f.label :email %><br />
  <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>
↓
<div class="field">
  <%= f.label :name %><br />
  <%= f.text_field :name, autofocus: true, autocomplete: "name" %>
</div>
...追記
<div class="field">
  <%= f.label :name %><br />
  <%= f.text_field :name, autofocus: true, autocomplete: "name" %>
</div>

nameを許可するため、deviseの設定ファイルを編集します。

...編集
# config.authentication_keys = [:email]
↓
config.authentication_keys = [:name]

この設定を行うと、emailが許可されなくなってしまうので、許可の設定をします。

...追記
before_action :configure_permitted_parameters,if: :devise_controller?

private

def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up,keys:[:email, :name])
end

3. ログイン・ログアウトの実装

deviseの導入はできました。
ここからはトップページにログインボタン・新規登録ボタン、
ログインしたらログインボタンを表示します。

...追記(bodyタグの直下)
<header>
  <nav>
    <ul>
      <% if user_signed_in? %>
        <li><%= link_to "ログアウト", destroy_user_session_path, method: :delete %></li>
      <% else %>
        <li><%= link_to "新規登録", new_user_registration_path %></li>
        <li><%= link_to "ログイン", new_user_session_path %></li>
      <% end %>
    </ul>
  </nav>
</header>

ここまでできたらアプリケーションを起動し、試してみましょう。
新規登録・ログイン・ログアウトできることが確認できたと思います。

4. ログインユーザー・ゲストユーザーの権限設定

ここからはログインユーザーの権限を設定していきます。
ログインしていない状態でurlを叩くとログインページにリダイレクトされてしまうことがあると思います。
その機能を実装していきます。
利用するのはdeviseに備わっている以下のメソッドです。

before_action :authenticate_user!

この1文をコントローラに記述するのみです。
では記述していきましょう。

...追記
before_action :authenticate_user!, except: :index

これだけで権限設定の完了です。
この一行でpostsコントローラのindexアクション以外のアクションに遷移した時に、ログインしていなければログインページに遷移させます。
except(あるアクション以外に適用)を利用しましたが、only(あるアクションだけに適用)やonly, except両方指定しなくても大丈夫です。

ここまでできたらログインしない状態でhttp://localhost:3000/posts/1にアクセスしてみましょう。
ログインページに遷移しましたか?

5. ユーザーと投稿の関連付け

さて、ユーザー認証機能・投稿機能は完成しました。
この段階だと誰がどの投稿をしたのかが、判別できません。
自分の投稿を他の人が編集できてしまったり、自分の投稿がどの投稿だったか記憶できていません。
ここからはユーザーと投稿を結びつけていきます。

Railsでモデル間の関連付けをするのは容易です。
今回は一人のユーザーに対して複数(0以上)の投稿が存在しうるので、
関係は1:Nとなります。
その関連付けの定義を行なっていきます。
また、Nの方に1のidを格納しないと関連付けが行えないため、Postモデルにuser_idカラムを追加します。

$ rails g migration AddColumnToPosts user_id:integer
$ rails db:migrate
...追記
belongs_to :user
...追記
has_many :posts

設定できたので試しに投稿してみるとUser must existというエラーが出ます。
投稿する時にuser_idを指定しないといけないので、コントローラも編集します。

def create
...追記
  @post.user_id = current_user.id

これで投稿ができるようになったと思います。
これ以降のカスタマイズは皆さんにお任せします。
ユーザー詳細ページを作成したり、投稿したユーザーでなければ編集できない機能を足すのも良いと思います。
アイデア次第なので、色々試してみてください。

補足

投稿者しか投稿の編集・削除が行えないようにします。

...編集
<% if post.user == current_user %>
  <td><%= link_to 'Edit', edit_post_path(post) %></td>
  <td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
<% end %>
def edit
  post = Post.find(params[:id])
  if post.user != current_user
    redirect_to root_path
  end
end

6. 完成ソースコード

https://github.com/ssshhhooota/rails_devise