嵌套属性在更新时加倍

时间:2013-11-15 23:16:49

标签: ruby-on-rails ruby

我目前的问题可以在标题中总结:我使用嵌套属性,但每次编辑整个内容时,我的嵌套模型都不会更新,它们会被克隆“#”;让我给你举个例子。让我们拥有具有字符串列的嵌套模型,现在它的值是" A"。 我们决定我们希望它是" B",然后点击更新。我们得到的是两个模型,一个用" A",另一个用" B"。然后我们改变" A"再次进入B.我们得到了" A"," B"," B"," B"。每次我尝试更新,我有2倍的模型。它很糟糕。(为了让它更清楚,我可以说双倍的字段是我想要的那个) 我已经确定它是某种assign_attributes() & save!update_attributes!()方法的错误,但我知道accepts_nested_attributes_for它不应该像那样工作。这是必要的代码:

海报控制器(海报是与之相关的模型的模型)

  def edit
    PosterCreator.new(@poster)
  end  

  def update
    respond_to do |format|
      if @poster.update_attributes(poster_params)
        format.html { redirect_to @poster }
      else
        format.html { render action: "new" }
      end 
    end 
  end

def poster_params
    params.require(:poster).permit(:content, :title, :category_id, string_fields_attributes: [:detail, :field_id], float_fields_attributes: [:float_number, :field_id], integer_fields_attributes: [:integer_number, :field_id], text_fields_attributes: [:description, :field_id], date_fields_attributes: [:date, :field_id])
end 

这是我在"编辑"中使用的PosterCreator问题。动作

class PosterCreator

  attr_accessor :poster

  def initialize(poster)
    @poster = poster
    build_fields_based_on_category
  end

  private

  def build_fields_based_on_category
    @poster.category.fields.each do |field|
      unless list_all_field_ids.include?(field.id)
        @custom_field = @poster.send("#{field.kind}_fields").build
        @custom_field.source = field
##########little explanation. Field model has kind, which can be integer, text, date etc, based on it, proper fields for poster are built
      end
    end    
  end 

  def list_all_field_ids
    @poster.list_fields.map do |field|
      field.field_id
    end  
  end

end 

最后是海报课程:

class Poster < ActiveRecord::Base
  belongs_to :user
  belongs_to :category
  has_many :text_fields
  has_many :string_fields
  has_many :integer_fields
  has_many :float_fields
  has_many :date_fields

  accepts_nested_attributes_for :float_fields
  accepts_nested_attributes_for :integer_fields
  accepts_nested_attributes_for :text_fields
  accepts_nested_attributes_for :string_fields
  accepts_nested_attributes_for :date_fields

  def list_fields
    fields = []
    self.text_fields.each { |field| fields << field }
    self.string_fields.each { |field| fields << field }
    self.integer_fields.each { |field| fields << field }
    self.date_fields.each { |field| fields << field }
    self.float_fields.each { |field| fields << field }
    fields
  end  

end

另外poster_form可能会有所帮助:

= simple_form_for @poster do |f|
    = f.input :category_id, collection: Category.all, prompt: "Choose category"
    = f.input :title
    = f.input :content
    = f.simple_fields_for :string_fields do |fsf|
        = fsf.input :detail
        = fsf.input :field_id, as: :hidden
    = f.simple_fields_for :text_fields do |ftf|
        = ftf.input :description
        = ftf.input :field_id, as: :hidden
    = f.simple_fields_for :integer_fields do |fif|
        = fif.input :integer_number 
        = fif.input :field_id, as: :hidden
    = f.simple_fields_for :float_fields do |fff|
        = fff.input :float_number
        = fff.input :field_id, as: :hidden
    = f.simple_fields_for   :date_fields do |fdf|
        = fdf.input :date
        = fdf.input :field_id, as: :hidden
    = f.submit

这是很多代码,但我希望有人能够告诉我它为什么不按照应该的方式工作

1 个答案:

答案 0 :(得分:0)

您需要在海报控制器中为每个嵌套模型添加两个内容:id和:_destroy,即:string_fields_attributes: [:id, :detail, :field_id, :_destroy]

您需要为所有嵌套模型添加这些字段。 这将允许您的控制器识别是否对已经存在的模型进行了更改(因此不会创建新模型),并且它使posters_controller能够销毁记录。

您还需要在poster.rb

中添加accepts_nested_attributes_for :string_fields, allow_destroy: true