accepts_nested_attributes_for也应该正确设置关联吗?

时间:2016-08-11 05:11:37

标签: ruby-on-rails ruby nested-attributes

鉴于某种Thing

class Thing < ApplicationRecord
  include CustomFieldable
  #...
end

可以附加自定义字段值:

module CustomFieldable
  extend ActiveSupport::Concern

  included do
    has_many :custom_field_values, as: :custom_fieldable, dependent: :destroy
    validates_associated :custom_field_values
    accepts_nested_attributes_for :custom_field_values
  end
end

自定义字段值基本上只是一个字符串值(至少目前为止),并引用其所有者:

class CustomFieldValue < ApplicationRecord
  belongs_to :custom_fieldable, polymorphic: true, dependent: :destroy
  belongs_to :custom_field, dependent: :destroy

  validates_presence_of :custom_fieldable
  validates_presence_of :custom_field
  validates_presence_of :string_value
end

自定义字段,它只是名称的包装:

class CustomField < ApplicationRecord
  validates_presence_of :name
  validates_uniqueness_of :name
end

当我用哈希初始化Thing时:

"thing"=>{
  //...other stuff...
  "custom_field_values_attributes"=>{
    "0"=>{
      "custom_field_id"=>"1",
      "string_value"=>"value 1"
    }
  }
}

我希望ActiveRecord能够设置从CustomFieldValue回到Thing的关联。但它看起来并非如此,因为我收到了验证错误:

  

以下字段存在问题:

     
      
  • 自定义字段值custom customable不能为空
  •   
  • 自定义字段值无效
  •   

所以当我使用accepts_nested_attributes_for时,就没有设置父关联。这是预期的行为吗?

更新#1:

允许字段的控制器逻辑如下所示:

class ThingController < ApplicationController

  def thing_params(action)
    common_params = [ omitting common stuff... ]
    params.fetch(:licence).permit(*common_params,
                                  custom_field_values_attributes: [
                                    :custom_field_id, :string_value ])
  end
end

更新#2:

如果我为模型编写两个测试,我可以看到同样的事情发生。

失败:

  test "adding a custom field value on construction via nested attributes" do
    thing = Thing.new custom_field_values_attributes: [
      { custom_field_id: custom_fields(:environment).id,
        string_value: 'Testing' }
    ]
    assert_attribute_not_invalid thing, :custom_field_values
    assert_equal 'Testing', thing.custom_field_values[0].string_value
  end

通行证:

  test "adding a custom field value via nested attributes" do
    thing = things(:one)
    thing.update_attributes custom_field_values_attributes: [
      { custom_field_id: custom_fields(:environment).id,
        string_value: 'Testing' }
    ]
    assert_valid thing
    assert_equal 'Testing', thing.custom_field_values[0].string_value
  end

因此,如果记录尚未保存,Rails不会正确设置嵌套模型,但如果已经保存,则会正确设置。

2 个答案:

答案 0 :(得分:1)

我一时兴起尝试了一些东西。改变了这个:

    has_many :custom_field_values, as: :custom_fieldable, dependent: :destroy

对此:

    has_many :custom_field_values, as: :custom_fieldable, inverse_of: :custom_fieldable, dependent: :destroy

所以似乎Rails无法猜测多态关联的反向关系 - 即使我已经被迫使用:as来告诉它。指定它两次工作正常。

答案 1 :(得分:0)

根据给出的代码,我会说每件事都很好。您创建一个 sprite_p1_avatar = new Sprite(dummyText); sprite_p1_avatar.setPosition(200, 200); sprite_p1_avatar.setOrigin(100, 100); sprite_p2_avatar = new Sprite(dummyText); sprite_p2_avatar.setPosition(300, 300); sprite_p2_avatar.setOrigin(100, 100); sprite_p3_avatar = new Sprite(dummyText); sprite_p3_avatar.setPosition(400, 400); sprite_p3_avatar.setOrigin(100, 100); sprite_p4_avatar = new Sprite(dummyText); sprite_p4_avatar.setPosition(500, 500); sprite_p4_avatar.setOrigin(100, 100); sprite_p1_avatar.rotate(40 * delta); sprite_p1_avatar.draw(batch); sprite_p2_avatar.rotate(40 * delta); sprite_p2_avatar.draw(batch); sprite_p3_avatar.rotate(40 * delta); sprite_p3_avatar.draw(batch); sprite_p4_avatar.rotate(40 * delta); sprite_p4_avatar.draw(batch); 对象并添加多个Thing对象。新的CustomFieldValue对象已将CustomFieldValue设置为1.这并不意味着Rails加载custom_field对象。只有在保存对象并重新加载时才会发生这种情况。所以custom_field_id抱怨是对的。这个属性仍然是零。我认为validates_presence_of :custom_field

会发生同样的情况