views:

117

answers:

0

I'm creating a shopping cart based on the one in Agile Web Development With Rails (version 3). I have it set up where "items" are added to a "cart", then upon starting the checkout process, they are added to an "order" object as "line_items". "line_items" represent one "item" in any quantity. Up to this point, I'm not deviating from the examples in the book. However, here is where it gets complicated for me. Every "item" in my store is customizable with text, and I need to be able to store the custom text with the "line_items" in the "orders".

As mentioned above, the "line_items" hold any quantity of an "item", but customers need to be able to customize every item, so each "line_item" will have to hold the different customizations for each individual "item". So, there cannot be just one column for the customization in the "line_items" table. The way I decided to organize it was to create a new model/table "line_item_attributes". For every individual "item" in a "line_item" there is a new "line_item_attributes".

I'm still pretty new to Rails, and I'm having some trouble getting this to work. I'm not convinced I'm even doing this the "Right Way". What I've run into is a sort of chicken/egg problem. When I create an "order", I add the "items" from the cart to it as "line_items". Now in order to customize the products they are ordering, I have to also add "line_item_attributes" to each "line_item" so that the customization form will have something to work with.

Here is what I don't know: I don't know how to "fill in" the blank "line_item_attributes" after the customer submits the form. I can't create "dummy" line_item_attributes for the form, and then upon submitting create new ones (the ones that will actually be saved) from the submitted data. The reason for this is that they must be tied into the "line_items" they belong to. I had hoped that Rails would just fill them in when I called "@order.save", but it doesn't. I hope this isn't to hard to understand.

I've included pertinent code below:

buy.rb (controller)

-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 (model)

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 (model)

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 (model)

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

Thanks for any help!