2016-08-19 3 views
2

Я пытаюсь построить объект, который состоит из трех ассоциаций в глубину одного удара. У пользователя есть возможность добавить больше дочерних объектов, если они захотят.Рельсы: форма для создания глубоких ассоциаций

class Template < ActiveRecord::Base 
    has_many :stacks, dependent: :destroy 
    accepts_nested_attributes_for :stacks, allow_destroy: true 
end 

class Stack < ActiveRecord::Base 
    belongs_to :template 
    has_many :boxes, dependent: :destroy 
    accepts_nested_attributes_for :boxes, allow_destroy: true 
end 

class Box < ActiveRecord::Base 
    belongs_to :stack 
    has_many :template_variables, dependent: :destroy 
    accepts_nested_attributes_for :template_variables, allow_destroy: true 
end 

class TemplateVariable < ActiveRecord::Base 
    belongs_to :box 
end 

Теперь мой контроллер для нового шаблона выглядит так:

def new 
    @template = Template.new 
    stack = @template.stacks.build 
    box = stack.boxes.build 
    box.template_variables.build 
end 

Я ударять некоторые препятствия, которые заставляют меня думать, что есть лучший способ сделать это. Объекты под объектом Stack не сохраняются. Контроллер разрешает все правильные параметры.

params.require(:template).permit(:name, 
    stacks_attributes: [:name, :direction, :order, :x, :y, :_destroy], 
    boxes_attributes: [:name, :_destroy], 
    template_variables_attributes: [:name, :box_name, :designator, :order_index, :_destroy]) 

Это может быть мои формы только частичными оказывается, когда это необходимо, как так:

<%= f.simple_fields_for :stacks do |stack| %> 
    <%= render 'stack_fields', f: stack %> 
<% end %> 

<%= link_to_add_fields '+ stack', f, :stacks %> 

И последующие отношения вложены в них, как в stack_fields парциальное:

<div style='background: #ccc; padding: 1em;'> 
    <%= f.input :name %> 
    <%= f.input :direction %> 
    <%= f.input :order %> 
    <%= f.input :x %> 
    <%= f.input :y %> 
    <%= f.hidden_field :_destroy %> 
    <%= link_to 'x', '#', class: 'remove_fields' %> 

    <%= link_to_add_fields '+ box', f, :boxes %> 

    <%= f.simple_fields_for :boxes do |b| %> 
    <%= render 'box_fields', f: b %> 
    <% end %> 
</div> 

Так мой вопрос в самом деле: есть ли лучший способ достичь того, чего я хочу, чем сражаться в гору, как это? Как, может быть, есть стандартная практика или драгоценный камень или что-то, что помогает при создании «глубоких» объектов?

+1

Формы и объекты вложены ... но похоже, что ваше разрешение/требование не вложено таким же образом ... Были ли у вас взгляды на параметры, которые поступают в журналы вашего сервера, чтобы проверить, что они совпадают с вашим разрешением/требуется структура? –

+0

О, это хороший момент, и это имеет большой смысл. Сейчас я проведу быстрый тест. Тем не менее, это похоже на то, что я решаю что-то, что могло бы быть решено гораздо лучше в другом месте. :) –

ответ

1

Параметры не вложены достаточно правильно, каждый объект должен быть вложен в его родительский объект. В настоящее время все они вложены в шаблон. Попытка:

params.require(:template).permit(:name, 
    stacks_attributes: [ 
    :name, :direction, :order, :x, :y, :_destroy, 
    boxes_attributes: [ 
     :name, :_destroy, 
     template_variables_attributes: [ 
     :name, :box_name, :designator, :order_index, :_destroy 
     ] 
    ] 
    ] 
) 

Обычно рекомендуется, чтобы глубокая связь достигла двух уровней. Однако иногда это неизбежно. Не зная контекста вашего моделирования данных, сложно определить, возможен ли альтернативный подход.

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