如何使用foreign_key而不是ID使用accepts_nested_attributes_for来同步has_many关联?

时间:2014-10-15 18:30:42

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

我想通过外键同步has_many关联。看来我必须编写自定义代码才能执行此操作。是否有任何Rails / Active Record魔法/宝石来实现这一目标?具体来说,我想同步一个连接表,其中外键对应该是唯一的。

class Food < ActiveRecord::Base
  has_many :food_tags, :dependent=>:destroy, :inverse_of => :food
  accepts_nested_attributes_for :food_tags, :allow_destroy => true
end

class FoodTag < ActiveRecord::Base
  belongs_to :tag, :inverse_of=>:food_tags
  belongs_to :food, :inverse_of=>:food_tags
end

class Tag < ActiveRecord::Base
  has_many :food_tags, :dependent=>:destroy, :inverse_of=>:tag
  has_many :foods, :through=>:food_tags
end

对于具有嵌套属性(或我的JSON API)的表单,我真的想省略FoodTag id并在更新食物时使用tag_id进行同步。

我想在更新时提交此内容以显示标记已设置或已清除

# this one is set
food[food_tag_attributes][0][tag_id]   = 2114
food[food_tag_attributes][0][_destroy] = false

# this one is cleared
food[food_tag_attributes][1][tag_id]   = 2116
food[food_tag_attributes][1][_destroy] = true

相反,我必须提交此更新:

# this one is set
food[food_tag_attributes][0][id]       = 109293
food[food_tag_attributes][0][tag_id]   = 2114
food[food_tag_attributes][0][_destroy] = false

# this one is cleared
food[food_tag_attributes][0][id]       = 109294
food[food_tag_attributes][1][tag_id]   = 2116
food[food_tag_attributes][1][_destroy] = true

这会给客户带来负担,让他们知道食品标签记录的ID,而不仅仅是能够根据标签ID设置或清除标签。

这可以轻松完成吗?我确信我可以在Food上编写一个before_save过滤器,但似乎应该有一个相当通用的解决方案。

1 个答案:

答案 0 :(得分:0)

视图助手中有一个名为index:for fields_for的选项。您可以将索引设置为foreign_key。然后,您的foreign_key将被用作引用您的对象的键,而不是顺序或某些任意数字。

修改

<%= form_for @person do |person_form| %> <%= person_form.text_field :name %> <% @person.addresses.each do |address| %> <%= person_form.fields_for address, **index**: address.id do |address_form|%> <%= address_form.text_field :city %> <% end %> <% end %> <% end %>