Вложенная форма Rails Formtastic - форма для атрибутов из модели соединения - PullRequest
2 голосов
/ 07 января 2012

Проблема, с которой я сталкиваюсь при Formtastic, заключается в том, что у меня есть форма для создания новой Order.В этой форме я хочу выбрать из списка несколько существующих Food элементов.Они должны быть добавлены в новый заказ, который я отправляю.В то же время я также хочу установить атрибуты в модели соединения FoodOrder.Эта модель имеет целочисленный атрибут количества, для которого я хотел бы иметь поле в моей форме.

Что я в основном ищу, так это форму, в которой перечислены все продукты питания и помещено поле для quantity в той же строке, что и элемент питания, к которому он принадлежит.

Модели

class Order < ActiveRecord::Base
  belongs_to :user
  belongs_to :restaurant
  has_many :food_orders
  has_many :foods, :through => :food_orders
end

class FoodOrder < ActiveRecord::Base
  belongs_to :food
  belongs_to :order
end

class Food < ActiveRecord::Base
  has_many :food_orders
  has_many :orders, :through => :food_orders
  belongs_to :category
end

Это одна из версий формы, которую я пробовал до сих пор.Но я просто сбит с толку и не знаю, как получить поля для модели FoodOrder.

<%= semantic_form_for [@restaurant, @order] do |f| %>
  <%= f.inputs do %>
    <%= f.input :comment %><br />
    <%= f.input :table_id %><br />
    <%# <%= f.input :foods, :as => :check_boxes %>
    <%= f.inputs :for => :foods do |food| %>
      <%= food %>
      <%= food.inputs :quantity %>
    <% end %>
  <% end %>
  <%= f.buttons do %>
    <%= f.commit_button %>
  <% end %>
<% end %>

У моих моделей есть эти атрибуты

create_table "food_orders", :force => true do |t|
  t.integer  "quantity",   :null => false
  t.decimal  "price",      :null => false
  t.integer  "food_id",    :null => false
  t.integer  "order_id",   :null => false
  t.text     "comment"
  t.datetime "created_at", :null => false
  t.datetime "updated_at", :null => false
end

create_table "foods", :force => true do |t|
  t.integer  "category_id",                     :null => false
  t.string   "name",                            :null => false
  t.string   "description"
  t.string   "image"
  t.decimal  "default_price",                   :null => false
  t.boolean  "active",        :default => true, :null => false
  t.datetime "created_at",                      :null => false
  t.datetime "updated_at",                      :null => false
end

create_table "orders", :force => true do |t|
  t.integer  "restaurant_id",                    :null => false
  t.integer  "user_id",                          :null => false
  t.integer  "table_id",                         :null => false
  t.decimal  "total",                            :null => false
  t.datetime "finished_at"
  t.datetime "created_at",                       :null => false
  t.datetime "updated_at",                       :null => false
end

1 Ответ

0 голосов
/ 07 января 2012

По сути, я бы в итоге создал объект FoodOrder для каждого Food, а затем сохранил только те, которые имеют значение выше 0.

Вы можете сделать это за reject_if для accepts_nested_attributes_for, но это не удалит старые FoodOrder, которые кто-то может изменить с 3 на 0. Поэтому вместо этого вам придется переопределить метод quantity= для FoodOrder.

Я никогда раньше не использовал formtastic, но собираюсь сделать предположение и сказать, что это должно сработать.

<%= semantic_form_for [@restaurant, @order] do |f| %>
  <%= f.inputs do %>
    <%= f.input :comment %><br />
    <%= f.input :table_id %><br />
    <% @foods.each do |food|
      <%= f.semantic_fields_for :food_orders, 
                            @order.food_orders.detect_or_build_by_food(food)
                            do |food_order| %>
        <%= food %>
        <%= food_order.inputs :quantity %>
      <% end %>
    <% end %>
  <% end %>
  <%= f.buttons do %>
    <%= f.commit_button %>
  <% end %>
<% end %>

order.rb:

class Order < ActiveRecord::Base
  belongs_to :user
  belongs_to :restaurant
  has_many :foods, :through => :food_orders
  has_many :food_orders do
    def detect_or_build_by_food(food)
      record = self.detect{ |food_order| food_order.food_id == food.id }
      if record.nil?
        record = self.build(:food => food)
      end
      record
    end
  end

  accepts_nested_attributes_for :food_orders
end

food_order.rb:

class FoodOrder < ActiveRecord::Base
  belongs_to :food
  belongs_to :order

  def quantity=(quantity)
    if quantity <= 0
      self.destroy
    else
      self[:quantity] = quantity
    end
  end
end

Я надеюсь, что это сработает, но это непроверенный код, так что да ... Удачи!

...