2013-11-15 4 views
0

Мои текущие проблемы можно суммировать в заголовке: я использую вложенные атрибуты, но каждый раз, когда я редактирую все это, мои вложенные модели не обновляются, они «клонируются». Позвольте привести пример. позволяет нам иметь вложенные модели, у которых есть строковый столбец, и сейчас его значение равно «A». мы решили, что хотим, чтобы он был «B», и нажмите «Обновить». мы получаем две модели: одну с «А», а другую с «В». Затем мы снова меняем «A» на B. мы получаем «A», «B», «B», «B». Каждый раз, когда я пытаюсь обновить, у меня есть еще 2 модели. это отстой. (чтобы сделать его более понятным, я могу сказать, что удвоенные поля - это то, что я хочу) Я определил, что это как-то ошибка assign_attributes() & save! или update_attributes!() методов, но я знаю, что с accepts_nested_attributes_for он не должен так работать. Вот необходимый код:Вложенные атрибуты удваиваются при обновлении

Плакаты контроллер (Poster является модель, которая имеет те связанные модели с ним)

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

Попробуйте удалить все скрытые: FIELD_ID входы в форме. – jaeheung

+0

Ditto - я не думаю, что вам нужно 'field_id' для каждого' fields_for', Rails должен вводить это автоматически –

ответ

0

Вам нужно добавить две вещи: Удостоверение личности и: _destroy каждому вложенной модели в ваш контроллер плакатов, то есть: string_fields_attributes: [:id, :detail, :field_id, :_destroy].

Вам нужно будет добавить эти поля для всех вложенных моделей. Это позволит вашему контроллеру определить, были ли внесены изменения в уже существующую модель (таким образом, она не создала новую), и дает плакату возможность уничтожать записи.

Вы также должны добавить accepts_nested_attributes_for :string_fields, allow_destroy: true в вашем poster.rb

Смежные вопросы