👏

[Rails]class_nameオプション

2025/01/29に公開

昨日書いたコメント機能について、
class_nameオプションを使えば、task.task_comments など冗長な部分を
task.comments とシンプルに書くことができると教わったのでそれをまとめます!


class_nameオプションとは

class_nameオプションとは、RailsのActive Recordでモデルの関連を設定するときに使用できるオプション。
モデル内で使用できる。私たちが作成したモデルの親クラスである、Active Recordが持ってるオプションなので、我々が作成したモデルでもこの機能を使用できる。

冗長な変数名を防ぐだけでなく、関連名(アソシエーション名)がモデル名と一致しない時も、class_nameオプションを使用する。
(Railsは、アソシエーション名を元に、関連するモデルを自動で探す)


使い方

現在のTaskモデル↓

class Task < ApplicationRecord
  # :task_comments がアソシエーション名
  has_many :task_comments, dependent: :destroy
end

:task_comments がアソシエーション名。
これでTaskモデルに、Task_commentモデルを関連付けてる。
「has_many」部分からTaskモデルに対して、Task_commentモデルが1:N になるようにしている。
(1個のTaskに対して、コメントは沢山ある)

class_nameオプションを使うと

class Task < ApplicationRecord
  # アソシエーション名は :comments
  has_many :comments, class_name: "TaskComment", dependent: :destroy
end

アソシエーション名が :commentsに変更される。
class_name: "TaskComment" を書いてるので、アソシエーション名がモデル名と一致していない :comments でも、Task_commentモデルと関連付けることができる。


昨日書いたビューはどう変わる?

アソシエーション名が :comments になったことで、下記に変更される。

<div class="index-results">
  <div class="index-card">
    <div class="index-header">
      <ul>
        <b>コメント件数:<%= @task.comments.count %></b>
        <hr size="10">
        <p></p>
        <!-- コメント表示 -->
        <% @task.comments.each do |task_comment| %>
          <li class="comment">
            <div class="comment-container">
              <div class="comment-image">
                <%= link_to user_path(@task.user) do %>
                  <% if task_comment.user.image.attached? %>
                    <%= image_tag task_comment.user.image, alt: "#{task_comment.user.name}のプロフィール画像", class: "profile-image" %>
                  <% else %>
                    <%= image_tag "no_image.jpg", alt: "デフォルトプロフィール画像", class: "profile-image" %>
                  <% end %>
                <% end %>
              </div>
              <div class="comment-content">
                <p class="comment-text"><%= task_comment.comment %></p>
                <span class="task-meta">
                  <%= task_comment.user.name %>
                  <%= task_comment.created_at.in_time_zone('Tokyo').strftime('%m月%d日 %H:%M') %>
                  <% if task_comment.user == current_user %>
                    <%= link_to "削除", task_task_comment_path(task_comment.task, task_comment), method: :delete %>
                  <% end %>
                </span>
              </div>
              <br>
            </div>
          </li>
          <hr size="10">
        <% end %>
        <!-- コメント投稿フォーム -->
        <%= form_with model:[@task, @task_comment] do |f| %>
          <%= f.text_area :comment, placeholder: "コメントを入力", class: "form-input-comment" %>
          <%= button_tag(type: 'submit', class: 'submit-btn') do %>
            <i class="fa-solid fa-paper-plane"></i>
          <% end %>
        <% end %>
      </ul>
    </div>
  </div>
</div>

具体的には・・・
@task.task_comments@task.comments になる。(2行目、5行目)


参考文献

Discussion