Ruby on Rails - 设置评论功能

问题描述 投票:0回答:5

我正在尝试在 Ruby on Rails 应用程序上设置一项功能,让用户可以查看图片。

我已按照本指南作为参考。

http://ruby.about.com/od/rubyonrails/ss/blogpart4_4.htm

根据我在其他 Ruby on Rails 项目上的工作经验,我认为帖子/评论关系模型可用于此处的图片/评论关系。

我首先生成了一个脚手架。

rails g scaffold review name:string body:text picture:references

我希望每个图片页面都有一个单独的页面用于自己的评论。

由于我的评论控制器不需要索引页,我从我的routes.rb 文件中删除了这一行

resources: reviews

我通过创建路线来替换它

match '/pictures/:id/reviews', to: 'reviews#show', via: 'get'
match '/pictures/:id/reviews/edit', to: 'reviews#edit', via: 'get'
match '/pictures/:id/reviews/new', to: 'reviews#new', via: 'get'

在这里,我的路径涉及将评论嵌套在图片中。

路线

favorite_picture_path   PUT     /pictures/:id/favorite(.:format)    pictures#favorite
pictures_path           GET     /pictures(.:format)                 pictures#index
                        POST    /pictures(.:format)                 pictures#create
new_picture_path        GET     /pictures/new(.:format)             pictures#new
edit_picture_path       GET     /pictures/:id/edit(.:format)        pictures#edit
picture_path            GET     /pictures/:id(.:format)             pictures#show
                        PATCH   /pictures/:id(.:format)             pictures#update
                        PUT     /pictures/:id(.:format)             pictures#update
                        DELETE  /pictures/:id(.:format)             pictures#destroy
users_path              GET     /users(.:format)                    users#index
                        POST    /users(.:format)                    users#create
new_user_path           GET     /users/new(.:format)                users#new
edit_user_path          GET     /users/:id/edit(.:format)           users#edit
user_path               GET     /users/:id(.:format)                users#show
                        PATCH   /users/:id(.:format)                users#update
                        PUT     /users/:id(.:format)                users#update
                        DELETE  /users/:id(.:format)                users#destroy
sessions_path           POST    /sessions(.:format)                 sessions#create
new_session_path        GET     /sessions/new(.:format)             sessions#new
session_path            DELETE  /sessions/:id(.:format)             sessions#destroy
contacts_path           POST    /contacts(.:format)                 contacts#create
new_contact_path        GET     /contacts/new(.:format)             contacts#new
root_path               GET     /                                   pictures#welcome
users_new_path          GET     /users/new(.:format)                users#new
about_path              GET     /about(.:format)                    pictures#about
                        GET     /contacts(.:format)                 contacts#new
                        GET     /users/:id/favorites(.:format)      users#favorites
signup_path             GET     /signup(.:format)                   users#new
signin_path             GET     /signin(.:format)                   sessions#new
signout_path            DELETE  /signout(.:format)                  sessions#destroy
                        GET     /pictures/:id/reviews(.:format)     reviews#show
                        GET     /pictures/:id/reviews/edit(.:format)    reviews#edit
                        GET     /pictures/:id/reviews/new(.:format) reviews#new
updated_path            GET     /updated(.:format)              pictures#newest_updates
                        GET     /top-rated(.:format)            pictures#high_ratings

评论控制器

class ReviewsController < ApplicationController
  before_action :set_review, only: [:show, :edit, :update, :destroy]

  def show
    @picture = Picture.find(params[:id])
    @review = Review.find(params[:id])
  end

  def new
    @review = Review.new
  end

  def edit
     @picture = Picture.find(params[:picture_id])
     @review = Review.find(params[:id])
  end

  def create
    @picture = Picture.find(params[:picture_id])
    @review = @picture.reviews.build(params[:review])

    if @review.save
      ;flash[:notice] = 'Review was successfully created.'
      redirect_to @picture
    else
      flash[:notice] = "Error creating review: #{@review.errors}"
      redirect_to @picture
    end
  end

  def update
    @picture = Picture.find(params[:picture_id])
    @review = Review.find(params[:id])

    if @review.update_attributes(params[:review])
      flash[:notice] = "Review updated"
      redirect_to @picture
    else
      flash[:error] = "There was an error updating your review"
      redirect_to @picture
    end
  end

  def destroy
    @picture = Picture.find(params[:picture_id])
    @review = Review.find(params[:id])
    @review.destroy
    redirect_to(@review.post)
  end

  private

    def set_review
      @review = Review.find(params[:id])
    end

    def review_params
      params.require(:review).permit(:username, :body, :picture_id)
    end
end

我从 ReviewsController 中删除了索引操作。

型号

class Review < ActiveRecord::Base
  belongs_to :picture
end

class Picture < ActiveRecord::Base
  has_many :reviews
end

上面我建立了图片和评论的一对多关系。

评论迁移

class CreateReviews < ActiveRecord::Migration
  def change
    create_table :reviews do |t|
      t.string :username
      t.text :body
      t.references :picture, index: true

      t.timestamps
    end
  end
end

根据我对 Rails 的理解,这应该可行。

图片#显示页面

<% @title = "#{@picture.title}" %>

<h4 class = 'indent'>Picture Statistics</h4>

  <ul id = 'view'>
    <li><strong>Title:</strong> <%= @picture.title %></li>
    <li><strong>Category:</strong> <%= @picture.category %></li>
    <li><strong>Rating:</strong> <%= pluralize(@picture.rating, 'Star') %></li>
    <li><strong>Favorited:</strong> By <%= pluralize(@picture.users.count, 'User') %></li></br>
  </ul>

  <% if @picture.rating > 4 %>

  <button class = 'top-picture'>Top Rated</button>

  <% end %>

<%= form_for @picture do |f| %>

  <p>
    <%= f.label :stars, 'Rating', class: 'indent' %>
    <div class= "rating">
      1 &#9734;<%= f.radio_button :stars, '1' %>
      2 &#9734;<%= f.radio_button :stars, '2' %>
      3 &#9734;<%= f.radio_button :stars, '3' %>
      4 &#9734;<%= f.radio_button :stars, '4' %>
      5 &#9734;<%= f.radio_button :stars, '5' %>
    </div>
  </p>

  <p class = 'indent'>
   <input class="btn btn-info" type="submit" value="Review">
  </p>

  <a href = "/pictures/:id/reviews">Reviews</a>

<% end %>
<p class = 'indent'>
  <a class="btn btn-info" href="/pictures" role="button">Index</a>
</p>

但是,当我点击图片/:id(显示页面)中的链接时

<a href = "/pictures/:id/reviews">Reviews</a>

未找到记录错误

Active Record::RecordNotFound in ReviewsController#show
Couldn't find Review with id=:id

Extracted source (around line #54):
53 def set_review
54  @review = Review.find(params[:id])
55 end
56
57 def review_params

由于我遇到了 RecordNotFound 错误,我怀疑问题出在 ReviewsController 上,很可能与参数有关。

我相信我的想法是正确的,但我在某个地方犯了错误。非常感谢反馈和批评。抱歉,如果这听起来像是一个愚蠢的问题,我只是不太擅长 Ruby。

ruby-on-rails ruby orm associations scaffolding
5个回答
2
投票

路线

为了子孙后代,您最好按如下方式设置路线:

#config/routes.rb
resources :pictures do
   resources :reviews, only: [:show, :edit, :new]
end

每当您在 Rails 中创建路由时,您需要记住整个框架是围绕“对象”/“资源”构建的。这就是为什么这些路由被称为

resourceful
路由(以及它们具有
resources
指令的原因) - 它们允许您定义围绕应用程序的不同资源

的路由

我建议使用

nested
资源结构。

--

帮手

您的问题已使用

Santosh
等提供的代码解决。即:

<%= link_to "Your Link", your_link_path(@object) %>

您需要了解如何这是有效的。每次您在 Rails 中使用

route
帮助程序(在
link_to
帮助程序中)时,它都会查看您的路线并找到所需的详细信息。

您引用了以下路径:

pictures/:id/reviews
- 据发现,这是错误的,因为 Rails 除了在渲染时构建链接之外,对链接的 URL 没有任何影响。

考虑到 Rails 是一个基于 HTTP 的无状态框架,Rails 必须根据每个请求整理所有数据。这意味着如果你想构建链接,你必须让 Rails 在渲染时构建链接,将一组静态数据传递到后端的控制器

希望这有帮助?


2
投票
match '/pictures/:id/reviews', to: 'reviews#show', via: 'get'
match '/pictures/:id/reviews/edit', to: 'reviews#edit', via: 'get'

这 2 条路线没有评论 ID,但您的控制器操作需要它们。进行此更改

match '/pictures/:picture_id/reviews/:id', to: 'reviews#show', via: 'get'
match '/pictures/:picture_id/reviews/:id/edit', to: 'reviews#edit', via: 'get'

改变这个

<a href = "/pictures/:id/reviews">Reviews</a>

<a href = "/pictures/#{@picture.id}/reviews/#{@review.id}">Reviews</a>

但是你应该认真考虑使用资源丰富的路线助手


2
投票

由于您有

.html.erb
文件,请尽量避免编写原始 HTML。

只需更新此链接:

<a href = "/pictures/:id/reviews">Reviews</a>

<%= link_to "Reviews", picture_reviews_path(@picture) %>

编辑:

您应该为您的

match
语句指定名称,例如:

match '/pictures/:id/reviews', to: 'reviews#show', via: 'get', :as => 'picture_reviews'

它将生成:

picture_reviews GET    /pictures/:id/reviews(.:format)          reviews#show

1
投票

考虑使用嵌套资源而不是手动构建它们

resources :pictures, except: [:index] do
  resources :reviews
end

正如其他人提到的,您应该使用 Rails link_to 来生成正确的 URL


0
投票

是的,他们可能是骗局,他们也骗了我。使用 Paypal 不会为您的购买提供保护或退款 https://zerothought.in/rails/

© www.soinside.com 2019 - 2024. All rights reserved.