Ruby on Rails에서 의견 및 응답 시스템을 만드는 방법

29312 단어
Ruby on Rails를 사용하여 간단한 설명과 회신 시스템을 구축하는 데 관한 자습서입니다.나는 줄곧 보석을 사용하지 않는 방법을 찾고 있다.대부분의 강좌는closure_tree나 조상 같은gem를 사용합니다.이것은 내가 원하는 것보다 많은 것 같다.나는 닉 하스킨스에게서 대본 39와 Stack Overflow의 작가라는 지도를 받았다.완료된 항목here을 찾을 수 있습니다.

시작합시다.


먼저 표준 Ruby on Rails 응용 프로그램을 만듭니다."commentapp"이라는 폴더를 만듭니다.터미널을 열고 다음 명령을 실행합니다.mkdir commentapp"commentapp"폴더로 변경cd commentapp새 rails 프로그램 실행 만들기rails new .코드 편집기를 열고 "commentapp"폴더를 엽니다.VS 코드를 사용하고 있습니다.프로그램이 성공적으로 만들어졌는지 테스트합니다.터미널에서 실행 중입니다.rails s브라우저 열기 및 탐색 http://localhost:3000/

부트 추가


우리는 스타일에 안내를 추가할 것이다.이것은 선택할 수 있는 단계다.너의 종점에서 달리는 중.yarn add bootstrapapp/javascript 폴더를 열고'stylesheets'라는 새 폴더를 만듭니다."stylesheets"폴더에 "application.scss"라는 파일을 만듭니다."application.scss"파일을 열고 추가합니다.
// app/javascript/stylesheets/application.scss
@import "bootstrap/scss/bootstrap";
응용 프로그램을 엽니다.js 파일 및 추가.
// app/javascript/packs/application.js
import "../stylesheets/application.scss";
응용 프로그램을 엽니다.html.erb와add.
# app/views/layouts/application.html.erb
<%= stylesheet_pack_tag 'application' %>

게시물 추가


다음 단계에서 우리는 기둥을 위해 비계를 세울 것이다.터미널을 열고 실행합니다.rails g scaffold post title:string body:text이렇게 하면 여러 파일이 생성되고 포스트의 라우팅 파일이 업데이트됩니다.우리는 그 중의 몇 개의 서류만 처리할 것이다.비계는 포스트 모델을 위한 테이블을 만드는 데 사용할 마이그레이션 파일을 만들었습니다.이것은db/migrate 폴더에 있습니다.
# db/migrate/<timestamp>_create_posts.rb
class CreatePosts < ActiveRecord::Migration[6.0]
  def change
    create_table :posts do |t|
      t.string :title
      t.text :body

      t.timestamps
    end
  end
end
이것은 제목과 본문 열을 포함하는 포스트 테이블을 만들 것입니다.이전이 효력을 발생하기 위해서 우리는 운행해야 한다.rails db:migrate만약 우리가 지금 이 프로그램을 실행하고 있다면, 우리는 여전히 기본적인 "예! 당신은 정상입니다!"를 얻을 수 있을 것이다페이지루트 경로를 Posts 인덱스 페이지로 변경해야 합니다.이것은 루트 파일을 업데이트해서 실현할 수 있다.
# config/routes.rb
root to: 'posts#index'
rails 서버를 시작하고 (정지된 경우) 새로 고침 http://localhost:3000/ 하면 페이지가 표시됩니다

"새 게시물"을 클릭하고 새 게시물을 만들어서 응용 프로그램에 내용을 제공합니다.제목이나 본문을 입력하지 않고 [게시글 만들기] 버튼을 클릭하면 빈 게시글이 생성됩니다.이러한 상황을 피하기 위해서 우리는 포스트 모델에 검증을 추가해야 한다.
# app/models/post.rb
class Post < ApplicationRecord
  validates :title, :body, presence: true 
end
나는 일부 게시물 보기에 안내가 있는 스타일을 추가할 것이다.스타일을 추가하기 전에 비계를 만들 때 생성된 스타일시트를 삭제해야 합니다.불행하게도 비계가 생성될 때마다 이 스타일시트가 다시 만들어집니다.따라서 부트를 사용할 때 스타일이 올바르지 않으면 스탠드일 수 있습니다.SCS를 제거해야 합니다.응용 프로그램/자산/스타일시트로 이동하여 비계를 제거합니다.scss 파일.우리는 응용 프로그램에 스타일을 추가하기 시작할 것이다.html.erb 페이지.
# app/views/layouts/application.html.erb
  <body>
    <div class="container">
      <%= yield %>
    </div>
  </body>
색인 페이지를 게시합니다.
# app/views/posts/index.html.erb
<p id="notice"><%= notice %></p>

<h1>Posts</h1>

<%= link_to 'New Post', new_post_path, class: 'btn btn-primary' %>
<hr>
<% @posts.each do |post| %>
  <div class="card">
    <div class="card-body">
      <h5 class="card-title"><%= link_to post.title, post_path(post) %></h5> # changed title to a link to show the post
      <p class="card-text"><%= truncate(post.body, length: 60) %></p>
      <%= link_to 'Edit', edit_post_path(post), class: 'card-link' %>
    </div>
  </div>
<% end %>

체크아웃 양식 섹션
# app/views/posts/_form.html.erb
<%= form_with(model: post, local: true) do |form| %>
  <% if post.errors.any? %>
    <div id="error_explanation">
      <h4 class="text-danger"><%= pluralize(post.errors.count, "error") %> prohibited this post from being saved:</h4>

      <ul class="list-group">
        <% post.errors.full_messages.each do |message| %>
          <li class="list-group-item list-group-item-danger"><%= message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <div class="form-group">
    <%= form.label :title %>
    <%= form.text_field :title, class: 'form-control' %>
  </div>

  <div class="form-group">
    <%= form.label :body %>
    <%= form.text_area :body, class: 'form-control' %>
  </div>

  <%= form.submit "Save Post", class: 'btn btn-primary' %>
<% end %>
새 게시물 양식
# app/views/posts/new.html.erb
<div class="card my-5">
  <div class="card-body">
    <h1>New Post</h1>

    <%= render 'form', post: @post %>

    <%= link_to 'Back', posts_path, class: 'btn btn-light mt-2' %>
  </div>
</div>

양식 편집 후기
# app/views/posts/edit.html.erb
<div class="card my-5">
  <div class="card-body">
    <h1>Edit Post</h1>

    <%= render 'form', post: @post %>

    <div class="mt-2">
      <%= link_to 'Show', @post, class: 'btn btn-info mr-2' %>
      <%= link_to 'Destroy', @post, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-danger mr-2' %> # moved the destroy button from index to here (optional)
      <%= link_to 'Back', posts_path, class: 'btn btn-light' %>
    </div>
  </div>
</div>
공연 후
# app/views/posts/show.html.erb
<div class="card my-5">
  <div class="card-body">
    <p id="notice"><%= notice %></p>

    <h1 class="text-center"><%= @post.title %></h1>
    <hr >
    <div class="my-4">
      <%= simple_format(@post.body) %>
    </div>

    <%= link_to 'Back', posts_path, class: 'btn btn-light' %>
  </div>
</div>

평론


이어서 우리는 평론을 구축할 것이다.터미널을 열고 실행합니다.rails g scaffold comment body:text post_id:integer parent_id:integer마찬가지로, 이것은 몇 개의 파일을 만들지만, 우리는 소수의 파일만 처리한다.주의해야 할 것은 비계를 삭제하는 것이다.부트나 다른 CSS 라이브러리를 사용하고 있다면 scss를 사용하십시오.
이전이 효력을 발생하기 위해서 우리는 운행해야 한다.rails db:migrate우리는 댓글을 댓글에 끼워 넣기 위해 경로를 업데이트해야 한다.노선을 열다.rb 파일을 다음과 같이 변경합니다.그러면 주석 경로가/와 유사하게 됩니다.게시물/1/comments/1.
# config/routes/rb
Rails.application.routes.draw do
  resources :posts do
    resources :comments
  end
  ...
end
댓글 및 게시물 모델을 변경해야 합니다.이 변경을 통해 댓글은 하나의 댓글에 속하고 댓글은 많은 댓글을 달 수 있다.포스트 모델에 다음 내용을 추가합니다.
# app/models/post.rb
has_many :comments
다음 내용을 논평 모델에 추가합니다.
# app/models/comments.rb
belongs_to :post
validates :body, presence: true
만약 당신이 어떤 평론 노선을 시도해 본다면, 그것들은 예상한 것처럼 일하지 않을 것이다. 왜냐하면 우리는 댓글에 평론을 끼워 넣었기 때문이다.작업 프로그램으로 되돌리기 위해서, 우선 Postshow에 새로운 댓글 폼을 추가합니다.html.erb 페이지.
# app/views/posts/show.html.erb
...
<div class="card my-1"> # place this card blow the post body.
  <div class="card-body">
    <p class="font-weight-bold">Comments</p>
    <%= form_with(model: [@post, @post.comments.build]) do |f| %>
      <div class="form-group">
        <%= f.label 'New comment' %>
        <%= f.text_area :body, class: 'form-control' %>
      </div>
      <%= f.submit 'Submit', class: 'btn btn-primary' %>
    <% end %>
  </div>
</div>

이제 Comments controller Create action을 업데이트해야 합니다.
# app/controllers/comments_controller.rb
def create
    @post = Post.find(params[:post_id])
    @comment = @post.comments.new(comment_params)

    respond_to do |format|
      if @comment.save
        format.html { redirect_to @post, notice: 'Comment was successfully created.' } # changed the redirect to @post
...
우선, 우리는 매개 변수와 함께 보내는post\uid를 사용하여post를 찾습니다.다음은 @comment 변수를 업데이트하여 게시물에 대한 새로운 설명을 만듭니다.주석을 만들려고 시도하면 데이터베이스를 검사하지 않으면 생성됩니다.이 문제를 해결하기 위해서 우리는 후기 프로그램을 갱신해야 한다.html.erb.댓글 카드 아래에 다음을 추가합니다.
# app/show.html.erb
...
<%= render @post.comments %>
위의 줄은 주석partial을 사용하여 모든 주석을 훑어볼 것입니다.우리는 일부 주석을 만들어야 한다.앱/views/comments를 열고 설명을 만듭니다.html.erb 파일.섹션에 다음 내용을 추가합니다.
# app/views/comments/_comment.html.erb
<div class="card">
  <div class="card-body">
    <%= comment.body %>
  </div>
</div>
댓글이 게시물 하단에 추가됩니다.너는 빈 카드 한 장이 새로운 평론 아래에 나타날 것을 알아차릴 것이다.어떤 이유로 새 주석이 자동으로 생성되지만 생성되지는 않습니다.

저장된 주석만 표시하려면 주석 섹션을 unless 조건에 봉인해야 합니다.
# app/views/comments/_comment.html.erb
<% unless !comment.persisted? %>
  <div class="card">
    ...
  </div>
<% end %>

회답


우리는 지금 댓글과 댓글을 만들 수 있기 때문에 다음 토론은 답장이다.나의 방법으로 우리는 비계에 대답을 받지 않을 것이다.답장은 기본적으로 평론이기 때문에 우리는 평론을 다시 사용하고 내용을 추가할 것이다.먼저 주석 모델을 변경합니다.
# app/models/comment.rb
class Comment < ApplicationRecord
  belongs_to  :post
  belongs_to  :parent, class_name: 'Comment', optional: true
  has_many    :replies, class_name: 'Comment', foreign_key: :parent_id, dependent: :destroy

  validates :body, presence: :true
end
우리는 논평 모델과 자체 연결을 만들고 있습니다.레일스 가이드에서 더 많은 정보를 읽을 수 있습니다here.이것은comments표에 답장을 저장하고parent id열을 사용하여 답장과 관련된 평론 id를 저장할 수 있도록 합니다.
다음은 답장 링크와 순환을 추가하여 답장을 표시하기 위해 주석 부분을 업데이트합니다.
# app/views/comments/_comment.html.erb
      <%= comment.body %>
      <%= link_to 'reply', new_post_comment_path(@post, parent_id: comment.id), remote: true, class: 'd-block' %>
      </div>
  </div>
  <% if comment.replies.any? %>
    <% comment.replies.each do |reply| %> 
      <%= render partial: 'comments/reply', locals: { reply: reply } %>
    <% end %>
  <% end %>
우리는 remote: true로 응답 링크를 추가해서 rails가 Ajax 호출이라는 것을 알게 하고 자바스크립트로 응답하기를 희망합니다.페이지를 새로 고칠 필요 없이 표시 페이지에 회신 양식을 삽입하는 데 JavaScript가 사용됩니다.링크에서postid와parentid의 매개 변수를 전달합니다. 다음에 댓글에 답장이 있는지 확인하고, 있다면replypartial로 순환합니다.우리는 부분적인 회답을 만들어야 한다.\u 응답을 추가합니다.html.응용 프로그램/보기/주석 폴더의 eb 파일입니다.
# app/views/comments/_reply.html.erb
<div class="card ml-5">
  <div class="card-body">
    <%= reply.body %>
  </div>
</div>
이것은 평론 아래에 다른 카드를 만들고 왼쪽 공백을 남겨 놓고 그것을 위로 밀어 올려 평론에 속하는 것처럼 보일 것이다.우리는 다음 일에 대답을 추가할 수 있을 때까지 볼 수 없을 것이다.우리는 회답을 위해 일부 표를 추가할 것이다.답장 양식을 추가합니다.html.응용 프로그램/보기/주석 폴더의 eb 파일입니다.
# app/views/comments/_reply_form.html.erb
<div class="card ml-5">
  <div class="card-body">
    <%= form_with(model: [@post, @comment]) do |f| %>
      <%= f.hidden_field :parent_id %>
      <div class="form-group">
        <%= f.label 'Reply' %>
        <%= f.text_area :body, class: 'form-control' %>
      </div>
      <%= f.submit 'Submit', class: 'btn btn-primary' %>
      <%= link_to 'Cancel', post_path(@post), class: 'btn btn-secondary' %>
    <% end %>
  </div>
</div>
부모 id에 숨겨진 필드를 추가했습니다. 이 필드는Comments 컨트롤러의 새로운 작업에서 채워집니다.나머지 부분은 상당히 표준적이다.
현재 폼을 만들었습니다. Comments 컨트롤러의 새로운 동작을 업데이트해야 합니다.
# app/controllers/comments_controller.rb
  def new
    @post = Post.find(params[:post_id])
    @comment = @post.comments.new(parent_id: params[:parent_id])
  end
이것은 새로운 답장을 구축할 것이다. 이것은 사실상 새로운 평론으로 답장 표에 전달해야 한다.부모 id를 전달하고 있기 때문에, 답장 폼의 숨겨진 필드를 채울 것입니다.이 댓글에 아버지 id가 있기 때문에, 우리는 이것이 답장이라는 것을 안다.내가 곤혹스러워지기 전에 계속합시다.
응답 링크는 새 동작에 대한 Ajax 호출이기 때문에, 응답과 동작이 같은 JavaScript 파일을 알고 있습니다.새 것을 추가합니다.js.erb 파일을 app/views/comments 폴더로 가져옵니다.
# app/views/comments/new.js.erb
document.querySelector("#reply-form-<%= @comment.parent_id %>").innerHTML = ("<%= j render 'reply_form', comment: @comment %>")
ID가 reply-form-<parent_id>인 div를 찾고 답장 양식을 div에 삽입합니다.\u 주석에서 div를 만들어야 합니다.html.직원 재훈련국 부분.주석에 다음 내용을 추가합니다.html.erb는 답장 순환 아래에 있습니다.
# app/views/comments/_comment.html.erb
  <div id="reply-form-<%= comment.id %>"></div>
이것은 삽입할 답장 폼의 자리 표시자입니다.우리는 주석 id를 사용하여 동적 구축 id를 사용합니다. 주석 id는 응답하는 부모 id입니다.이것이 바로 왜 새로운 시대에js.@ 메모를 사용하고 있습니다.학부모 id. 답장 링크를 누르면 답장 폼이 평론 아래에 표시됩니다.일단 당신이 회답을 받게 되면, 그것은 표를 평론의 마지막 회답 아래에 놓을 것이다.댓글에 대한 답변을 추가합니다.

답장을 작성하면 연관된 설명 아래에 추가되지만 설명으로 표시됩니다.답장이 주석 데이터베이스에 저장되어 있기 때문입니다.이 문제를 해결하기 위해서는\u 주석을 업데이트해야 합니다.html.erb 부분은 또 다른 조건을 포함한다.
# app/views/comments/_comment.html.erb
<% unless comment.parent_id || !comment.persisted? %>
따라서 댓글에 parent_id가 있거나 저장된 댓글이 아니라면 댓글 목록에 표시되지 않고 댓글의 답장에만 표시됩니다.
나는 이것이 도움이 되기를 바란다.
신용
Playbook Thirty-nine 작성자: Nick Haskins
StackOverflow

좋은 웹페이지 즐겨찾기