【问题标题】:Rails: c.id submits nil in comment.each do |c.id| blockRails: c.id 在 comment.each 中提交 nil 做 |c.id|堵塞
【发布时间】:2014-11-02 23:09:12
【问题描述】:

我正在尝试为用户实施一个评论系统,其中每个评论都可以被投票。我有一个模型 UpVote,它多态地属于多个模型,包括评论,而每个用户都有_很多评论。

UpVote 模型:

class UpVote < ActiveRecord::Base
  belongs_to :voteable, polymorphic: true
end

评论模型:

class Comment < ActiveRecord::Base
  belongs_to :user
  has_many :up_votes, as: :voteable
end

用户模型:

class User < ActiveRecord::Base
  has_many :comments
  has_many :up_votes, as: :voteable
end

用户展示:我在错误所在的行周围加了星号。

<% @user.comments.each do |c| %>
  <%= c.text %>
  <%= c.username %>
  <%= c.id %>
  ***<%= link_to "upvote", upvote_comment_path(c.id), method: :post, :class => "btn btn-small" %>***
<% end %>

评论控制器:

def upvote
  @comment = Comment.find(params[:id])
  UpVote.create!(voteable_id: params[:id], voteable_type: 'Comment')
  redirect_to root_path
end

路线:

post 'comments/:id/upvote' => 'comments#upvote', as: 'upvote_comment'

但是当我在用户页面上为评论提交 UpVote 时,我收到以下错误:

ActionController::UrlGenerationError in Users#show
No route matches {:action=>"upvote", :controller=>"comments", :id=>nil} missing required keys: [:id]

link_to 似乎不接受c.id,这很奇怪,因为c.id 自己会正常打印@comment.id。我做错了什么?

赏金消息中的错误:我的意思是赏金消息中的“@comment.id”,而不是“@comment.up_vote.count”,但我似乎无法对其进行编辑。

【问题讨论】:

  • 请在您的config/routes.rb 中显示为此操作定义的路线。
  • @spickermann 我把它贴在上面了。

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


【解决方案1】:

我怀疑您在@user.comments 中有一条评论,它的idnil,因为它还没有被持久化。如果您使用@user.comments.new@user.comments.build 设置新评论,则可能会发生这种情况。这两种方法都会将空白注释添加到@user.comments 数组中。

有多种方法可以避免显示未持久化的 cmets (see this question)。我认为最好的解决方案是避免在关联上使用buildnew。相反,如果您需要显示新评论(例如在表单中),则首选 Comment.new 而不是 @user.comments.build@user.comments.new

【讨论】:

  • 我认为不可能,因为我为一个有两个 cmets 的用户测试了 ;第一个打印“1”,另一个打印“3”。
  • 如果您有一个包含所有 nil 值的评论,它将不会显示,因为 &lt;%= nil %&gt; 不显示任何内容。一个很好的检查方法是查看@user.comments.length 是什么。
  • 哇,你说得对,它返回 3。你建议我做什么?我必须擦除数据库吗?
  • 不,问题是您在@user.comments 中有一条评论尚未保存到数据库中(这就是为什么idnil)。有关如何防止这种情况,请参阅我的更新答案。
【解决方案2】:

解决问题的正确方法是修改routes.rb,将动作upvote改为on: :member

  resources :comments do
    post :upvote, on: :member
  end

post 'comments/:id/upvote' => 'comments#upvote', as: 'upvote_comment'

【讨论】:

  • 两种方法都试过了;第一种方式,我收到错误undefined local variable or method 'on' for #&lt;ActionDispatch::Routing::Mapper:0xb220f8c0&gt;,第二种方式我收到与我在问题中发布的相同的错误。
  • 我已经更新了答案,并使用了正确的路线约定。 :id 必须出现在操作之前。
  • 嗯,现在这条路线似乎可行,但我再次收到原始错误,即使我使用的是(id: c.id)
  • 我已经用upvote_comment_path(c.id) 对其进行了测试,它的工作原理。你能仔细检查你的控制器是否被称为“评论”(复数)?
  • 是的,它叫做评论。这很奇怪,它对你有用,但对我不起作用。
【解决方案3】:

可能发生的情况是您创建了静态路由,而不是资源丰富的路由。在这种情况下,您可能必须在 link_to 中明确指定 id

<%= link_to "upvote", upvote_comment_path(:id => c.id), method: :post, :class => "btn btn-small" %>

您可以通过创建一个资源丰富的路线来避免这种额外的标记,就像您在示例中尝试的那样

resources :comments do
 member do
   post 'upvote'
 end
end

不知道为什么“on::member”语法对你不起作用,因为它在功能上等同于块语法。我相信问题可能是您使用符号而不是字符串指定操作(upvote)。

祝你好运

【讨论】:

    猜你喜欢
    • 2016-08-09
    • 2023-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-08
    • 1970-01-01
    • 2014-08-18
    • 1970-01-01
    相关资源
    最近更新 更多