【问题标题】:Polymorphic comments: can't pass type and id (NoMethodError for nil:NilClass)多态注释:不能传递类型和 id (NoMethodError for nil:NilClass)
【发布时间】:2017-11-21 06:03:02
【问题描述】:

我正在尝试为 QuestionAnswer 创建多态 cmets,但是当我点击“创建评论”表单上的“创建”按钮时,commentable_typecommentable_id 从未通过。我可以通过 rails 控制台成功创建新评论,但不能通过表单(目前我正在测试 cmets 的问题)。我在 cmets_controller 的 load_commentablecreate 中遇到错误,例如:

NoMethodError (undefined method `comments' for nil:NilClass):

app/controllers/comments_controller.rb:9:in `create'

似乎@commentablenil(因为它没有得到commentable_typecommentable_id 参数?)。 我错过了什么?

cmets 迁移:

class CreateComments < ActiveRecord::Migration[5.1]
  def change
    create_table :comments do |t|
      t.references :user, foreign_key: true
      t.text :body, null:false
      t.references :commentable, polymorphic: true, index: true

      t.timestamps
    end
      add_index :comments, [:commentable_id, :commentable_type]
  end
end

routes.rb:

Rails.application.routes.draw do

  resources :comments, only: [:create]

  resources :votes, only: [:create] do
    delete :reset, on: :collection
  end

  resources :attachments, only: :destroy

  devise_for :users

  resources :questions do
    resources :comments, only: :create, defaults: { commentable: 'questions' }
    resources :answers, shallow: true do
      resources :comments, only: :create, defaults: { commentable: 'answers' }
      patch :set_best, on: :member
    end
  end

  root to: "questions#index"

  mount ActionCable.server => '/cable'
end

cmets 表单部分 _comment_form.html.slim:

    h4 Add a comment
    .comment_errors
    = form_for [@commentable, Comment.new], remote: true do |f|
      .form-group
        = f.label :body, 'Comment'
        = f.text_area :body, class: 'form-control'
      p= f.submit 'Create', class: 'btn btn-primary'

cmets_controller:

class CommentsController < ApplicationController
  before_action :authenticate_user!
  before_action :load_commentable, only: [:create]

  def create
    @comment = @commentable.comments.create(comment_params.merge(user: current_user))
  end

  private

  def load_commentable
    if params[:comment][:commentable_type] == 'Answer'
      @commentable = Answer.find(params[:comment][:commentable_id])
      gon.answer_id = @commentable.id
    elsif params[:comment][:commentable_type] == 'Question'
      gon.answer_id = @commentable.id
      @commentable = Question.find(params[:comment][:commentable_id])
    end
  end

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

相关的 cmets 部分的显示视图:

h3 Comments
.question_comments id="comments_section_question_#{@question.id}"
  - if user_signed_in?
    .row
      = render 'comments/comment_form', commentable: @question

错误日志:

app/controllers/comments_controller.rb:7:in `create'
Started POST "/comments" for 10.0.2.2 at 2017-11-20 20:54:42 +0000
Cannot render console from 10.0.2.2! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by CommentsController#create as JS
  Parameters: {"utf8"=>"✓", "comment"=>{"body"=>"kkkk"}, "commit"=>"Create"}
  User Load (0.4ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 41], ["LIMIT", 1]]
Completed 500 Internal Server Error in 3ms (ActiveRecord: 0.4ms)



NoMethodError (undefined method `comments' for nil:NilClass):

app/controllers/comments_controller.rb:7:in `create'

【问题讨论】:

  • 查看您的params"comment"=&gt;{"body"=&gt;"kkkk"}。看到有什么遗漏吗?然后看看你的表格。您有 @commentable,但您在哪里将其值添加到表单中?
  • id、user_id、commentable_type 和 commentable_id 参数丢失,但我不明白为什么以及如何解决此问题
  • Google for hidden_field...顺便说一句,我不知道 id 指的是什么。但我想你不需要user_id,因为你可以通过设计获得它(我认为类似于current_user.id。但是,我不使用设计,所以这可能不完全正确)。
  • id 是评论的 id。我之前尝试过隐藏字段,但这不起作用并给出了类似的错误,我还了解到更好的解决方案是在控制器中动态传递这些字段,但无法修复代码。

标签: ruby-on-rails polymorphic-associations


【解决方案1】:

我认为您的 partial_comment_form.html.slim 应该是这样的:

h4 Add a comment
.comment_errors
= form_for [@commentable, Comment.new], remote: true do |f|
  .form-group
    = f.label :body, 'Comment'
    = f.text_area :body, class: 'form-control'
    = hidden_field_tag 'commentable[id]', @commentable.id
    = hidden_field_tag 'commentable[type]', @commentable.class.name
  p= f.submit 'Create', class: 'btn btn-primary'

这应该给你类似的参数:

Parameters: {"utf8"=>"✓", "comment"=>{"body"=>"kkkk"}, "commentable"=>{"id"=>"1", "type"=>"Question"}, commit"=>"Create"}

然后,您将load_commentable 更改为:

def load_commentable
  @commentable = commentable_params[:type].constantize.find_by(id: commentable_params[:id])
  gon.answer_id = @commentable.id
end

(顺便说一句,当你有问题时,gon.answer_id 似乎很奇怪。但是,我不知道......)

这自然需要类似的东西:

def commentable_params
  param.require(:commentable).permit(:id, :type)
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-19
    • 2016-08-13
    • 1970-01-01
    • 1970-01-01
    • 2023-01-12
    • 2016-01-02
    相关资源
    最近更新 更多