【问题标题】:Why won't rails create associated records/objects from nested form using strong parameters?为什么 Rails 不使用强参数从嵌套表单创建关联的记录/对象?
【发布时间】:2015-03-23 15:00:14
【问题描述】:

我正在尝试创建一条记录,它是使用强参数从嵌套表单中关联的记录。我的主要模型是:

class MaterialDonationRequest < ActiveRecord::Base
  has_many :donation_items, dependent: :destroy
  accepts_nested_attributes_for :donation_items, allow_destroy: true
  validates :name, presence: true

  attr_accessor :due_on_event, :date, :donation_items_attributes, :event_id
end

我的关联(嵌套)模型是:

class DonationItem < ActiveRecord::Base
  validates :name, presence: true
  belongs_to :material_donation_request
  belongs_to :global_profile

  validates :name, presence: true
  attr_accessor :_destroy
end

在我的 material_donation_requests_controller.rb 中,我有以下强参数:

    def material_donation_request_params
      params.require(:material_donation_request).permit(:name, :description, :event_flag, :due_on_event, :date, :event_id, donation_items_attributes: [:id, :name, :description, :amount, :_destroy])
    end

这是我创建对象的 create 方法中的一行:

    @material_donation_request = MaterialDonationRequest.new(material_donation_request_params)

完成此操作后,@material_donation_request 会从表单中正确创建和填充。但是关联的donation_items 不会被创建。例如,在调试器中,当我输入@material_donation_request.donation_items.first 时,Rails 返回nil

作为参考,以下是 Rails 在我正在运行的手动测试中为 material_donation_request_params 返回的内容:

{"name"=>"Name", "description"=>"", "due_on_event"=>"true", "date"=>"", "donation_items_attributes"=>{"0"=>{"name"=>"", "amount"=>"1", "_destroy"=>""}, "1427122183210"=>{"name"=>"", "amount"=>"2", "_destroy"=>""}}}

为什么 Rails 不从表单中创建关联的对象呢?在我看过的所有地方,似乎这个结构应该创建所有内容,并且后续保存应该保存所有内容(或者至少在这种情况下抛出验证错误 - 请参阅下面的更新)。我有什么遗漏吗?

更新

因为它是在答案中提出的,是的,上面显示的material_donation_params 不会通过验证。这就是我一直在手动测试的场景。它应该在保存时生成一个验证错误,而是简单地保存 MaterialDonationRequest 而没有任何类型的错误,并且不保存任何内容到 DonationItems。

但要明确的是,如果我完整填写表格并获得以下material_donation_request_params

{"name"=>"Name", "description"=>"", "due_on_event"=>"true", "date"=>"", "donation_items_attributes"=>{"0"=>{"name"=>"first", "amount"=>"1", "_destroy"=>""}, "1427122183210"=>{"name"=>"second", "amount"=>"2", "_destroy"=>""}}}

然后执行@material_donation_request.save,它只保存MaterialDonationRequest,而不是任何DonationItems

最终更新

好的。我已经删除了我之前的“最终更新”,因为我写的内容,以及我在某些 cmets 中写的内容是错误的。最终解决这个问题的不是 Rails 4.1.8 的更新。在使用新的 Rails 版本实际保存 gem 文件之前,我运行了 bundle update 命令。所以真的,最终解决这个问题的只是更新所有没有固定版本号的 gem。上帝只知道为什么事情不能与之前的一组宝石一起工作。抱歉,这不是很有帮助...

【问题讨论】:

  • 你的attr_accessors 字段在数据库中吗?
  • 没有。他们不是。但我想出了答案(请参阅下面的答案和我的最终更新)。 Rails 4.0.2 似乎没有正确处理事情。我升级到 4.1.8,就像变魔术一样,一切正常。
  • 您已经解决了问题。但是问题的原因(我相信)仍未得到证实,我不敢相信这是 Rails 版本的问题。
  • 您是否可以看到任何可能导致问题的原因?
  • attr_accessor 中包含donation_items_attributes 似乎很可疑,可能会覆盖accepts_nested_attributes 定义的设置器。

标签: ruby-on-rails nested-forms strong-parameters


【解决方案1】:

来自Rails Validations guide

存在 This helper validates that the specified attributes are not empty. It uses the blank? method to check if the value is either nil or a blank string, that is, a string that is either empty or consists of whitespace.

您需要 donation_item 存在,但您生成的参数哈希显然有捐赠名称空白,验证失败。在调试这些东西时调用 save! 会很有帮助,因为它会在失败时抛出错误。

【讨论】:

  • 其实(后续的)保存不会抛出错误。它只是保存 MaterialDonationRequest,甚至不尝试保存任何其他内容,因为无论出于何种原因,从一开始就不会创建关联。
  • 意思是说“从一开始就永远不会创建相关的捐赠项目。”
【解决方案2】:

我想出了答案。绝望之下,我将我的 Rails 版本从我一直使用的 4.0.2 升级到了 4.1.8。完成此操作后,没有任何其他更改(当然除了 gem 依赖项),它刚刚开始按预期的方式工作。所以我猜 Rails 4.0.2 存在嵌套表单和强参数的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-28
    相关资源
    最近更新 更多