Форма оформления Rails с несколькими моделями - PullRequest
0 голосов
/ 27 января 2010

Я создаю корзину для покупок на основе корзины в Agile Web Development With Rails (версия 3). Я установил, где «элементы» добавляются в «корзину», а затем, при запуске процесса оформления заказа, они добавляются в объект «заказ» как «line_items». «line_items» представляет один «элемент» в любом количестве. До этого момента я не отклонялся от примеров в книге. Однако, вот где это становится сложным для меня. Каждый «товар» в моем магазине настраивается с помощью текста, и мне нужно иметь возможность хранить пользовательский текст с «line_items» в «заказах».

Как упоминалось выше, «line_items» содержит любое количество «элемента», но клиенты должны иметь возможность настраивать каждый элемент, поэтому каждый «line_item» должен содержать различные настройки для каждого отдельного «элемента». Таким образом, в таблице "line_items" не может быть только одного столбца для настройки. Я решил организовать это, создав новую модель / таблицу "line_item_attributes". Для каждого отдельного «элемента» в «line_item» есть новый «line_item_attributes».

Я все еще довольно новичок в Rails, и у меня возникли некоторые проблемы с этим. Я не уверен, что я даже делаю это "Правильный путь". То, с чем я столкнулся, является своего рода проблемой курицы / яйца. Когда я создаю «заказ», я добавляю «товары» из корзины как «line_items». Теперь, чтобы настроить продукты, которые они заказывают, я также должен добавить «line_item_attributes» к каждому «line_item», чтобы в форме настройки было что работать.

Вот что я не знаю: я не знаю, как «заполнить» пустое поле «line_item_attributes» после того, как клиент отправит форму. Я не могу создать «фиктивные» line_item_attributes для формы, а затем при отправке создать новые (те, которые будут фактически сохранены) из отправленных данных. Причина этого заключается в том, что они должны быть привязаны к элементам "line_items", к которым они принадлежат. Я надеялся, что Rails просто заполнит их, когда я позвоню "@ order.save", но это не так. Надеюсь, это не так сложно понять.

Я включил соответствующий код ниже:

buy.rb (контроллер)

-SNIP-
def purchase
  @cart  = find_cart

  if @cart.items.empty?
   redirect_to_index("Your order is empty")
  end
end

def customize
  @renderable_partials = [1, 2, 3]
  @order = find_order

  if @order.nil?
   redirect_to_index("Your order is empty")
   end
end

def save_purchase
 @cart  = find_cart
 @order = find_order(params[:cart_owner])
 @order.add_line_items_from_cart(@cart)

 redirect_to :action => 'customize'
end

def save_customize
 @order = find_order

 if @order.save
  redirect_to :action => 'purchase'
 else
  flash[:error] = "Your information could not be saved"
  redirect_to :action => 'customize'
 end
end
-SNIP-

order.rb (модель)

class Order < ActiveRecord::Base
 has_many :line_items
 has_many :line_item_attributes
 accepts_nested_attributes_for :line_items
 accepts_nested_attributes_for :line_item_attributes

 def add_line_items_from_cart(cart)
  cart.items.each do |item|
   li = LineItem.from_cart_item(item)
   line_items << li
  end
 end
end

line_item.rb (модель)

class LineItem < ActiveRecord::Base
 belongs_to :order
 belongs_to :item
 has_many :line_item_attributes
 accepts_nested_attributes_for :line_item_attributes

 def self.from_cart_item(cart_item)
  li = self.new
  li.item = cart_item.item
  li.quantity = cart_item.quantity
  li.total_price = cart_item.price

  li.quantity.times do |single_item|
   lia = LineItemAttribute.new
   li.line_item_attributes << lia
  end

  li
 end
end

line_item_attributes.rb (модель)

class LineItemAttribute < ActiveRecord::Base
 belongs_to :order
 belongs_to :line_item
end

Спасибо за любую помощь!

1 Ответ

1 голос
/ 17 апреля 2014

Я рекомендую перенести создание Order и LineItems в отдельный «объект службы» или «объект формы». Внутри объекта службы / формы оберните создание заказов и позиций в одну транзакцию. Код будет легче читать, и ваши модели не будут загрязнены перекрестной моделью. От контроллера проверки передайте объект @cart объекту службы вместо непосредственного вызова объекта Order.

Посмотрите на # 2 и # 3 этого сообщения для получения дополнительной информации об объектах обслуживания: http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/

...