ユーザ周りの修正: 小林研 Rails Tips (84)

このページの内容は以下のリポジトリに1日遅れで反映されます(記事執筆前に前日分をコミットしています)。

https://github.com/hkob/hkob_blog

はじめに

Rails Tips の 84 回目です。ユーザ周りでいくつか不具合があったので、少し修正していきます。

Rails をはじめよう - Railsガイド

articles/index の修正

まず、ログインしていない時に new_article_path に飛べないようにしていませんでした。user_signed_in? を確認し、ログインしている時だけリンクを表示するようにしました。

- content_for :title do
  - @page_title = t ".title"

%table
  %thead
    = labels Article, %w[title user_name], add_control: true
  %tbody
    - @articles.each do |article|
      - next if article.archived?

      %tr
        %td= article.title
        %td= article.user_name
        %td
          = lotfp article_path(article)
          - if article.owned_by? current_user
            = lotfp edit_article_path(article)
            = destroy_lotfp article_path(article), Article
    - if user_signed_in?
      %tr
        %td= lotfp new_article_path

ログインページへのリンク

そもそもログインのリンクを記述していませんでした。application.html.haml の yield の下に、ログイン中であればログアウトリンクを、ログインしていなければログインリンクを追加しました。

  %body
    #notice= notice
    #alert= alert
    - if @page_title.present?
      %h1= @page_title
    = yield

    %hr
    - if user_signed_in?
      ログイン中:
      = current_user.name
      = destroy_lotfp destroy_user_session_path, User
    - else
      = lotfp new_user_session_path

ログインの翻訳文字列がなかったので、devise.sessions.new.title への翻訳文字列をdevise.views.ja.yml に追加しました。ついでに devise.sessions.destroy.title も追加しています。

ja:
  devise:
    (中略)
    sessions:
      already_signed_out: 既にログアウト済みです。
      new:
        sign_in: ログイン
        title: ログイン
      signed_in: ログインしました。
      signed_out: ログアウトしました。
      destroy:
        title: ログアウト

devise の strong parameter の修正

これでうまくいったかと思ったのですが、user の name が空のままでした。view に name を追加していましたが、strong parameter が設定されていなく、name が許可されていなかったためです。せっかく current_user.name で表示しているのに、その部分が空になっています。

user の編集をするには https://localhost:3000/users/edit にアクセスすればいいのですが、こちらも strong parameter が設定されていないと更新もされません。調べると以下のようにサイタイザーを設定すればよいようです。アカウント作成時は sign_up で設定しますが、今回は account_update でも名前を修正したいので、以下のように二つサニタイザーを設定してみました。

class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

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

コメントの user_id 追加

コメントの追加もログインしている時のみにすべきでした。こちらも user_signed_in? を追加しています。

- content_for :title do
  - @page_title = @article.title

%p= @article.body

- if @article.owned_by? current_user
  %ul
    %li= lotfp edit_article_path(@article)
    %li= destroy_lotfp article_path(@article), Article

%h2 Comments
= render partial: "articles/comments/comment", collection: @comments

- if user_signed_in? && @comment.new_record?
  %h2 Add a comment:
  = render "articles/comments/form"

また、この時 articles#show で新規コメントの雛形を作っていましたが、ここに user_id が設定されていませんでした。

def show
    @article = object_from_params_id Article
    @comments = @article.comments.order_created_at_desc
    @comment = objects_from_params(Comment) || @article.comments.build(user: current_user)
  end

おわりに

記事やコメントの編集については一致を確認していましたが、新規の時にログイン確認が抜けていました。後付けで修正するといろいろ抜けが発生しますね。最初からちゃんと設計しないとこういうことが起こりがちです。