accepts_nested_attributes_for и ассоциации второго порядка, вложенные формы - PullRequest
2 голосов
/ 11 апреля 2011

У меня есть следующие модели с ассоциациями:

class Order < ActiveRecord::Base
  has_many :guests
  has_many :customers, :through => :guests
  accepts_nested_attributes_for :customers
end

class Customer < ActiveRecord::Base
   has_many :guests
   has_many :orders, :through => :guests
   has_many :slips
   accepts_nested_attributes_for :slips
end

class Slip < ActiveRecord::Base
   belongs_to :order
   belongs_to :customer
end

class Guest < ActiveRecord::Base
  belongs_to :order
  belongs_to :customer
end

Моя вложенная форма выглядит следующим образом:

<!-- general form -->
<%= form_for(@order) do |f| %>
    <% f.fields_for :customers do |builder| %>
        <%= render "customer_fields", :f => builder %>
    <% end %>
    <%= f.submit %>
<% end %>

<!-- partial customer_fields -->
<p>
    <%= f.label :name%><%= f.text_field :name %>
    <% f.fields_for :slips do |builder| %>
        <%= render "slip_fields", :f => builder %>
    <% end %>
</p>

<!-- partial slip_fields -->
<p><%= f.label :quantity%><%= f.text_field :quantity %></p>

При этой настройке сохранение заказа работает, как и ожидалось, но мне нужен order_idчтобы быть сохраненным с промахом, поэтому у меня есть ссылка между ордером <-> промах.С этой настройкой я теряю ссылку.Я могу получить всех связанных клиентов, но я получу все связанные с клиентом квитанции, связанные с заказом или нет.


Вот поля моих моделей: Заказ -> id
Клиент -> id
Гость -> id, идентификатор_порядка, customer_id
Slip -> id, идентификатор_порядка, customer_id


Результат заказа должен выглядеть следующим образом

  • Заказ
    1. Клиент A
      • Слип 1
      • Слип 2
    2. Клиент B
      • Слип1
      • Слип 2
    3. Клиент A
      • Слип 1
      • Слип 2
      • Слип 3

Я понятия не имею, как этого добиться.

1 Ответ

1 голос
/ 11 апреля 2011

Поскольку вы не можете вернуть order_id для заказа, который не существует, вы можете сделать этот хук (я не проверял его, поэтому вам, возможно, придется его исправить)

def create
  customers = params[:order].delete :customers_attributes
  @order = Order.new params[:order]
  if @order.save
    customers.each{|c| c[:slips_attributes].each{|s| s[:order_id] = @order.id} }
    @order.customers_attributes = customers
    @order.save
  end
end

def update
  @order = Order.find params[:id]
  params[:order][:customers_attributes].each{|c| c[:slips_attributes].each{|s| s[:order_id] = @order.id} }
  @order = Order.update_attributes params[:order]
  @order.save
end

Также вам лучше удалить всю эту логику в вашей модели, и вы можете dry это немного.Это только о понимании подхода.

UPD для ваших коллизий ID.Это снова эскиз

def create
  customers = params[:order].delete :customers_attributes
  @order = Order.new params[:order]
  @order.customer_ids = customers.inject([]){|a,h| a << h[:b] if h[:b]; a}
  if @order.save
    customers.each{|c| c[:slips_attributes].each{|s| s[:order_id] = @order.id} }
    @order.customers_attributes = customers
    @order.save
  end
end

def update
  @order = Order.find params[:id]
  @order.customer_ids = params[:order][:customers_attributes].inject([]){|a,h| a << h[:b] if h[:b]; a}
  params[:order][:customers_attributes].each{|c| c[:slips_attributes].each{|s| s[:order_id] = @order.id} }
  @order = Order.update_attributes params[:order]
  @order.save
end
...