【问题标题】:Rails 4. Set up comment editing functionality with nested resourcesRails 4. 使用嵌套资源设置评论编辑功能
【发布时间】:2015-08-30 12:48:55
【问题描述】:

我有以下型号:User、Product 和 Comment。用户可以对产品添加、编辑和删除 cmets。我已经成功设置了添加和删除功能,现在我正在为编辑而苦苦挣扎,由于某种原因,这给我带来了很多困难。

当我点击edit comment 链接时,我当前的代码返回此错误:

/products/800/cmets/8/edit 处的 NoMethodError

nil:NilClass 的未定义方法 `cmets'


这是我的评论模型的样子:

#  id         :integer          not null, primary key
#  body       :text
#  created_at :datetime         not null
#  updated_at :datetime         not null
#  user_id    :integer
#  product_id :integer

class Comment < ActiveRecord::Base
  belongs_to :user
  belongs_to :product
  # validations ...
end

在User 模型中我有has_many :comments 和Product - has_many :comments, dependent: :destroy。

在我的routes.rb 文件中,我有以下嵌套资源:

  resources :products, only: [:show] do
    resources :comments, only: [:create, :edit, :update, :destroy]
  end

我的 ProductsController 有唯一的方法 show 没有别的,它的样子如下:

  def show
    product = Product.find(params[:id])
    photos = ProductsPhoto.where(product: product)
    case product.products_category.name
    when 'Violin'
      @product = [product, Violin.where(product: product).first, photos]
    when 'Guitar'
      @product = [product, Guitar.where(product: product).first, photos]
    when 'Saxophone'
      @product = [product, Saxophone.where(product: product).first, photos]
    when 'Piano'
      @product = [product, Piano.where(product: product).first, photos]
    end
    @comment = Comment.new
    @comments = Comment.where(product_id: product.id).order('created_at DESC')
  end

现在这是我的CommentsController,其中有create、edit、update 和destroy:

class CommentsController < ApplicationController
  def create
    @product = Product.find(params[:product_id])
    @comment = @product.comments.create(comment_params)
    @comment.user_id = current_user.id
    if @comment.save
      redirect_to @product, notice: 'Comment Created!'
    else
      redirect_to @product, notice: 'Something went wrong...'
    end
  end

  def show
  end

  def edit
    @product = Product.find(params[:product_id])
    @comment = @product.comments.find(params[:id])
  end

  def update
    @product = Product.find(params[:product_id])
    @comment = @product.comments.find(params[:id])
    respond_to do |format|
      if @comment.update_attributes(comment_params)
        format.html do
          redirect_to [@comment.product, @comment], notice: 'Comment Updated!'
        end
      else
        format.html { render action: 'edit', notice: 'Something went wrong...' }
      end
    end
  end

  def destroy
    @product = Product.find(params[:product_id])
    @comment = @product.comments.find(params[:id])
    @comment.destroy!
    redirect_to @product, notice: 'Comment Deleted!'
  end

  private

  def comment_params
    params.require(:comment).permit(:body)
  end
end

我的_form 视图位于views/products/_form.html.erb,如下所示:

  <%= simple_form_for([@product[0], @product[0].comments.build]) do |f| %>
        <%= f.error_notification %>
        <%= f.input :body, required: true, placeholder: 'Type in your comment...', input_html: { class: 'form-control'}, label: false %>
        <%= f.button :submit, class: 'btn btn-primary btn-block' %>
  <% end %>

而在views/products/show.html.erb我渲染了cmets的部分,并且有销毁和编辑评论的链接,它们看起来像这样:

<%= link_to edit_product_comment_path(comment.product, comment) do %>
  <span class="glyphicon glyphicon-pencil"></span>
<% end %>
<%= link_to [comment.product, comment], method: :delete do %>
  <span class="glyphicon glyphicon-remove"></span>
<% end %>

删除链接可以正常工作,而编辑链接不行。

可能我弄错了路线,这里是cmets的路线:

product_comments POST       /products/:product_id/comments(.:format)          comments#create
edit_product_comment GET        /products/:product_id/comments/:id/edit(.:format) comments#edit
product_comment PATCH      /products/:product_id/comments/:id(.:format)      comments#update
PUT        /products/:product_id/comments/:id(.:format)      comments#update
DELETE     /products/:product_id/comments/:id(.:format)      comments#destroy

在我的views/comments/edit.html.erb 中,我呈现相同的表单:

  <%= render 'products/form' %>

但是,当我单击编辑链接时,我收到以下错误:

/products/800/cmets/8/edit 处的 NoMethodError

nil:NilClass 的未定义方法 `cmets'

_form.html.erb 的第一行。


我希望我已经提供了足够的信息来描述问题。

那么,您能帮我解决 cmets 编辑的问题吗?

【问题讨论】:

  • @Pavan 这在同一个地方给了我完全相同的错误...... :(
  • 您是否尝试在 Comments 控制器中调试您的 edit 操作以查看是否找到了产品?
  • @Nathan 我不确定我应该如何调试它。我无法访问update 方法,但我可以调试edit,并且可以正确找到@product 和@comment 变量。
  • 您如何调试编辑操作以了解正在设置@product?
  • @product 和 @comment 正在设置中。我在edit 操作的末尾使用了byebug

标签: ruby-on-rails ruby-on-rails-4


【解决方案1】:

今天早上太早了……

这是不正确的:

  <%= simple_form_for([@product, @product.comments.build]) do |f| %>

试试:

 <%= simple_form_for [@comment.product_id, @comment],  url: product_comment_path(@comment.product_id, @comment)  do |f| %>

添加部分

(所有这些都假设我们正在使用单个 @comment,而不是 @cmets 集合。基于您的 cmets 关于删除工作。)

要回复您的评论,是的,您的子表 cmets 的“新建”和“编辑”操作绝对需要单独的表单。

表单“新”命名约定为 cmets/_form.html.erb,“编辑”表单为 cmets/_form_edit.html.erb,

我会为 cmets 打开“新”操作表单...

<%= simple_form_for([:product, @comment]) do |f| %>

还有“编辑”动作……

<%= simple_form_for [@comment.product_id, @comment],  url: product_comment_path(@comment.product_id, @comment)  do |f| %>

对不起,我忘记了以前版本的 URL,我已经更新了上面的代码 sn-p 以反映这个变化。警告:可能有其他方法可以构建此链接,但这就是我实现产品(父级)与评论/cmets(许多子级)的案例的方式。

嵌套属性

在进一步回复您的评论时,我相信您正在寻找的一些内容可以通过在表单中​​使用嵌套属性来实现。这是另一个话题。我会让新/编辑表单简单的情况下工作,然后增加复杂性。

【讨论】:

  • 如果你试一试,请告诉我进展如何。
  • 这给了我undefined method comments_path。请看我的_form.html.erb 的更新代码,ProductsController 中的@product 变量是第一个元素是Product 对象的数组。我应该如何更改当前表单以使 edit 操作起作用?也许我应该有不同的形式来创建评论(如views/products/_form.html.erb)和编辑(如views/comments/_form.html.erb)?因为@product 在CommentsController 中是一个Product 对象,而在ProductsController 中它是一个数组
  • 是的。我遗漏了一些东西。对不起。添加部分回答。
  • 我按照你说的做了,编辑表格确实有效!但是现在当我在编辑评论时单击提交按钮时,我得到products/:id/comments/:id的路由错误
  • 现在我更改了comments_controller 中的重定向,一切正常。感谢您的详细解释和正确答案!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-09
  • 1970-01-01
相关资源
最近更新 更多