【问题标题】:"Create" Action for nested resource with multiple Associations in RailsRails 中具有多个关联的嵌套资源的“创建”操作
【发布时间】:2014-05-10 20:00:53
【问题描述】:

我有items,每个都有多个(线程)comments。
线程是通过parent 键完成的,指向另一个comment

我只是无法让create 操作正常工作,我已经将它提交到数据库中,但它没有设置item_idparent_id

我试过form_for [@item, @comment]而不是form_for :comment, url: item_comments_path( @item ),但也没有用。

当我在 create 操作中查看 comment_params 时,我得到以下信息:

Parameters: {"utf8"=>"✓", "comment"=>{"body"=>"examplecommentgoeshere"}, "parent_id"=>"4", "commit"=>"Create Comment", "item_id"=>"4"}

谁能帮忙?

型号:

class Item < ActiveRecord::Base
  belongs_to :user
  has_many :comments, dependent: :destroy
  has_many :images,   as: :item,
                      dependent: :destroy

  validates :title,       presence: true,
                          allow_blank: false
  validates :description, presence: true,
                          allow_blank: false
  validates :user,        presence: true,
                          allow_blank: false
  validates :layout,        presence: true
end


class Comment < ActiveRecord::Base
  belongs_to :user
  belongs_to :item
  has_many :responses,  class_name: "Comment",
                        foreign_key: "parent_id",
                        dependent: :destroy
  has_one :image,       as: :item,
                        dependent: :destroy
  belongs_to :parent,   class_name: "Comment"

  validates :body,      presence: true,
                        allow_blank: false,
                        length: { minimum: 10 }
end

评论控制器:

class CommentsController < ApplicationController
  before_filter :findParent
  before_filter :find, only: [:update, :destroy, :show]
  before_filter :is_logged_in?, only: [:create, :update, :destroy]
  before_filter :has_permission?, only: [:update, :destroy]

  def new
    @comment = Comment.new
  end

  def create
    logger.debug comment_params.inspect
    @comment = current_user.comments.build(comment_params)

    if @comment.save
      redirect_to @item
    else
      logger.debug @comment.errors.inspect
      session[:errorbj] = @comment
      redirect_to @item
    end
  end
  [...]
  private
  def comment_params
    params.require(:comment).permit(:body, :parent)
  end

  private
  def find
    @comment = Comment.find(params[:id])
  end

  private
  def findParent
    @item = Item.find params[:item_id]
  end

项目视图:

<p>
<h3>Add a comment:</h3>
  <%= render partial: 'comments/form', locals: { parent: @item } %>
</p>

部分cmets/form:

<%= form_for :comment, url: item_comments_path( @item ) do |f| %>
  <p>
    <%= f.label :body %><br>
    <%= f.text_area :body %>
  </p>

  <p>
    <%= f.label :image %><br>
    &lt;nope&gt;
  </p>

  <%= hidden_field_tag :parent_id, parent.id %>
  <p>
    <%= f.submit %>
  </p>
<% end %>

从另一个 stackoverflow 线程我得出结论,在多关联中创建对象的唯一方法是按照以下方式执行操作:

@comment = current_user.comments.build( comment_params.join( { parent_id: <parent.id> } ) )

其他 stackoverflow 帖子却说不做

@item = Item.new( item_params.join( { user_id: current_user.id } )

那么真的没有更好的办法了吗?

【问题讨论】:

    标签: ruby-on-rails activerecord model-associations nested-resources


    【解决方案1】:

    我认为您的代码中有很多错误。我希望我能把它写成一个可以帮助你自己解决问题的表格:

    • 使用form_for [@item, @comment]
    • findParent 应该是 find_parent
    • findParent 应该设置一个 @parent
    • findParent 应该找到 Comment
    • new 操作应使用父级 @comment = Comment.new parent: @parent 进行初始化
    • hidden_field_tag :parent_id, parent.id 应该是 form.hidden_field :parent
    • 父关联应该通过comment_params设置
    • 您不需要Rails.logger 语句,它都在logs/development.log 中
    • 不要将对象放入会话中
    • 为什么会有itemimage

    了解有关调试的更多信息! http://nofail.de/2013/10/debugging-rails-applications-in-development/

    【讨论】:

    • 好吧,findParent 名字不好;它为每个comment 找到item(因为它是嵌套资源中的父级)。在new 操作中,我还没有parent,因为它是上下文相关的,它可能是另一个评论或项目。我试图通过hidden_field_tag :parent_id 存档。项目和评论可能有images,但我不知道为什么我在那里有as: :item....我需要尝试更多的东西,也许在这里报告。
    • 现在回想起来,我意识到我 parent 实际上不是多态的,但 image 是。 image 有一个“所有者帖子”,它被称为item(因此是as :item)。图像可能不存在,因此与此错误无关,我在表单开发的早期阶段省略了它们。
    • 会话中的对象是我从中获取错误消息的地方;可能有更好的方法(比如自己存储完整的消息),但我确保它始终在ApplicationControllerbefore 过滤器中被清除和保护。我试过form.hidden_field :parent,但我不能那样指定一个值,该方法只能从现有的comment对象中取出数据。
    【解决方案2】:

    事实证明这比看起来要容易得多。

    这就是我最终这样做的方式:

    class CommentsController < ApplicationController
      before_filter :findParent, only: [:create]
      [...]
      def create
        @comment = current_user.comments.build(comment_params)
        @comment.item = @item
        if @comment.save
          redirect_to @item
        else
          session[:errorbj] = @comment
          redirect_to @item
        end
      end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多