Rails:未定义的方法`id'

时间:2015-05-19 17:05:35

标签: ruby-on-rails

每个用户has_many:通知,每个通知has_many:注释,每个类通知。每个通知/评论has_one:supernotice,即发表评论的通知。 尝试提交评论后,我收到此错误消息:undefined method 'id' for "#<Notice:0x0000010eed6958>":String。为什么Rails认为我的NoticeString

notices_controller.rb:

def create
  @notice = user.notices.build(notice_params)
  if @notice.save
    if !params[:notice][:commentee].nil?
      @notice.create_comment(params[:notice][:commentee])
    end
  end
end

private
  def notice_params
    params.require(:notice).permit(:content, :comentee)
  end

notice.rb:

belongs_to :user
has_one :active_comment_relationship, class_name: "Commentrelationship", foreign_key: "commenter_id", dependent: :destroy
has_one :supernotice, through: :active_comment_relationship, source: :commentee

def create_comment(other_notice)
  active_comment_relationship.create(commentee_id: other_notice.id)
end

在_notice.html.erb中提交有关通知的评论:

  <%= form_tag( {controller: "notices", action: "create"}, method: "post", id: "comment_form" ) do %>
    <%= hidden_field_tag :callsign, @user.callsign %>
    <%= hidden_field_tag "notice[commentee]", notice %>
    <%= text_area_tag "notice[content]", '', id: "commentField" %>
    <%= submit_tag "Reply" %>
  <% end %> 

服务器日志:

Parameters: {"utf8"=>"✓", "authenticity_token"=>"...", "callsign"=>"bazzer", "notice"=>{"commentee"=>"#<Notice:0x00000110a49140>", "content"=>"Hello there."}, "commit"=>"Reply"}

1 个答案:

答案 0 :(得分:0)

因为它只能以表单值的形式呈现为字符串。反复序列化也不会对你有任何好处。显而易见的选择是传递该通知的id并进行查找。但我个人更喜欢不同的做法。

如果评论张贴在该通知的notice_id页面上,您可能根本不需要从表单中传递show:id已经是路线的一部分那里。如果您创建嵌套资源:

resources :notices do
  resources :comments
end

...你的评论&#39;路线贴在通知的顶部&#39;路线。您可以为注释创建控制器,并且可以使用以下路由访问注释集合:

notices_comments_path(@notice)
# => /notices/42/comments

因此,当您将评论发布到上述格式的网址时,您必须传递根本没有隐藏的参数

  • Commentee 可以从路线中的给定params[:note_id]查找
  • callsign可以在控制器层的current_user上查找(使用Devise或Sorcery)

这样做的原因是因为隐藏的输入隐藏在视线之外,而不是来自开发人员工具,并且因此被篡改。为了解决这个问题,在控制器中使用额外的检查是很诱人的,但是为什么如果控制器能够自己分配它们呢?

反模式警告:不要过多地嵌套资源。 2级是可以的,3级是关注的,4级是可怕的。