English 中文(简体)
Rails checkout form with multiple models
原标题:

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!

问题回答

I recommend moving the Order and LineItems creation to a separate "service object" or "form object." Inside the service/form object, wrap the Order and Line Items creation in a single transaction. The code will be easier to read and your models will not be polluted with cross-model. From the checkout controller, pass the @cart object to the service object instead of calling the Order object directly.

Look at #2 and #3 of this post for more info about service objects: http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/





相关问题
rails collection_select vs. select

collection_select and select Rails helpers: Which one should I use? I can t see a difference in both ways. Both helpers take a collection and generates options tags inside a select tag. Is there a ...

SSL slowness in EC2

We ve deployed our rails app to EC2. In our setup, we have two proxies on small instances behind round-robin DNS. These run nginx load balancers for a dynamically growing and shrinking farm of web ...

Auth-code with A-Za-z0-9 to use in an URL parameter

As part of a web application I need an auth-code to pass as a URL parameter. I am currently using (in Rails) : Digest::SHA1.hexdigest((object_id + rand(255)).to_s) Which provides long strings like : ...

RubyCAS-Client question: Rails

I ve installed RubyCAS-Client version 2.1.0 as a plugin within a rails app. It s working, but I d like to remove the ?ticket= in the url. Is this possible?

activerecord has_many :through find with one sql call

I have a these 3 models: class User < ActiveRecord::Base has_many :permissions, :dependent => :destroy has_many :roles, :through => :permissions end class Permission < ActiveRecord::...

Ordering a hash to xml: Rails

I m building an xml document from a hash. The xml attributes need to be in order. How can this be accomplished? hash.to_xml

Text Editor for Ruby-on-Rails

guys which text editor is good for Rubyonrails? i m using Windows and i was using E-Texteditor but its not free n its expired now can anyone plese tell me any free texteditor? n which one is best an ...

How to get SQL queries for each user where env is production

I’m developing an application dedicated to generate statistical reports, I would like that user after saving their stat report they save sql queries too. To do that I wrote the following module: ...

热门标签