【Rails】게시판 앱으로 Topic과 Post를 연관시킨다【연결】

소개



현재, 포트폴리오로서 게시판 앱을 작성하고 있어, 제목에 있는 「Topic과 Post를 끈다」 부분으로 시간이 걸렸으므로 비망록으로서.

조속하지만, 연결하기 위해 필요한 요소로서 다음의 2점을 중심으로 기재합니다.
  • 모델 측 수정
  • controller 측 수정

  • 하고 싶은 일



    복수 있는 Post는 반드시 하나의 Topic에 묶는다
    Post나 Topic은 반드시 하나의 User에 묶는다
    각 모델을 연결하고 '@post.topic.title'과 같은 형태로 값을 얻고 싶습니다.

    환경



    macOS:10.14.6
    Ruby:2.5.7
    Rails:5.2.4.1

    모델측 수정(연결)



    이번에 등장하는 model은, 이하의 3개.
    ・Topic
    ・User(devise를 사용하고 있습니다)
    ・Post

    Topic이 스레드, Post가 스레드에 대한 레스,
    Topic(1)---(다)Post
    User(1)---(다)Post/Topic
    라는 위치 지정이 됩니다.

    이번 경우에는 이미 각 model을 작성(generate)이 끝났으므로, 어소시에이션용의 마이그레이션 파일을 만들어, 마이그레이션 해 나가는 형태로 진행합니다.

    마이그레이션 파일 작성


    $ rails g migration AddUserToTopic
    $ rails g migration AddTopicToPost
    

    마이그레이션 파일 편집



    문법은, 「add_reference table명, reference명」이 기본형이 됩니다.
    index는 옵션이므로 기호로.
    그건 그렇고, 슈퍼 거친이지만, 인덱스는로드/획득 속도를 높이는 것입니다.
    (단, 쓰기 속도는 느려지므로 주의가 필요)

    20200222110925_add_user_to_topic.rb
    class AddUserToTopic < ActiveRecord::Migration[5.2]
      def change
        add_reference :topics, :user, index: true #追記箇所
      end
    end
    

    20200223032448_add_topic_to_post.rb
    class AddTopicToPost < ActiveRecord::Migration[5.2]
      def change
        add_reference :posts,:topic #追記箇所
      end
    end
    

    마이그레이션


    $ rails db:migrate
    

    위의 명령을 실행 한 후 다음과 같은 migrated가 출력되면 OK
    == 20200223032448 AddTopicToPost: migrating ===================================
    -- add_reference(:posts, :topic)
       -> 0.0796s
    == 20200223032448 AddTopicToPost: migrated (0.0797s) ==========================
    

    모델 편집



    topic.rb
    class Topic < ApplicationRecord
      validates :title, presence: true
      has_many :posts #追記
      belongs_to :user #追記
    end
    

    post.rb
    class Post < ApplicationRecord
      belongs_to :topic #追記
      belongs_to :user #追記
    end
    

    user.rb
    class User < ApplicationRecord
      devise :database_authenticatable, :registerable,
             :recoverable, :rememberable, :validatable
      validates :name,:email,:encrypted_password, presence: true
      has_many :topics, through: :posts #追記
    end
    

    이것으로 모델 측은 OK입니다!

    controller 측 수정



    각 model의 관련지을 수 있었으므로 이하와 같은 형태로, 관련처의 값을 주워 이것하게 되었습니다. 세세하게 말하면 파라미터 중에서 명시적으로 값을 취득하는 이미지입니다.
    params[:topic_id]라는 느낌으로.

    posts_controller.rb
    class PostsController < ApplicationController
    
      def new
        @topic_id = params[:topic_id]
        @post = Post.new
      end
    
      def create
        @post = Post.new
        @topic_id = params[:topic_id] #paramsからtopic_idを取得し、インスタンス変数@topic_idに代入
        @post.topic_id = @topic_id #上記を@post.topic_idに代入
        @post.body = params[:post][:body]
        @topic = Topic.find(@topic_id)
        @post.user_id = current_user.id
        if @post.save
          redirect_to topic_path(@topic_id), notice: '投稿しました'
        else
          render 'posts/new', alert: '投稿できませんでした'
        end
      end
    end
    

    조금 더러워, 땀
    취득하고 싶은 값은 「params로부터 취득해 인스턴스에 대입」이라고 쓰는 형태입니다.
    그래서 얻고 싶은 값에 따라 편집하십시오. 상기는 어디까지나 참고로서.

    view 수정(덤)



    다음은 주제 목록 화면(topic#index)입니다만, post의 수나 post의 투고 시간을 취득해 표시할 수 있습니다.

    index.html.erb
    <div class="container mt-5 ml-5">
      <div class="row">
          <% @topics.each do |topic| %>
            <div class="table tabel-hover">
              <%= link_to topic do %>
                <div class="list-group" style="max-width: 500px;">
                  <div class="list-group-item list-group-item-action">
                    <%= topic.title %> (<%= topic.posts.count %>)  #post数を計算
                    <br>
                    <small class="text-muted text-right">
                    最終投稿日時:<%= topic.posts.last.created_at %> #最新のpost投稿時間を取得する
                    </small>
                  </div>
              <% end %>
              </div>
          <% end %>
          </div>
      </div>
    </div>
    

    이런 표시가 됩니다↓



    매우 편리하네요.

    참고문헌



    Active Record 연결

    좋은 웹페이지 즐겨찾기