2

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

В основном я ищу форму, в которой перечислены все элементы питания и помещается поле для 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 

ответ

0

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

Вы можете сделать это в reject_if для accepts_nested_attributes_for, но это не приведет к удалению старого FoodOrder с тем, что кто-то может измениться с 3 на 0. Поэтому вместо этого вам придется переопределить t he 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 

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

+0

Спасибо за ваш ответ! Теперь форма выглядит красиво, как и то, что я искал. К сожалению, я получаю ошибку «Невозможно модифицировать замороженную хэш-ошибку Rails Runtime». Возможно ли, что изменение количества в «FoodOrder» не разрешено? Любая идея, где еще может возникнуть эта ошибка? – patrickdet

+0

Хм, его, вероятно, уничтожить в методе, который я буду на моем телефоне до конца дня, но вместо этого вы можете попробовать «mark_for_destruction». Но если это не сработает, полностью уничтожить уничтожение и посмотреть, что произойдет. – Azolo

+0

Спасибо за быстрый ответ. Ни '.mark_for_destruction', ни комментирование не работают. оба ведут к 'SQLite3 :: ConstraintException: ограничение не удалось: INSERT INTO« food_orders »' – patrickdet