2010-01-27 45 views
0

我正在基于敏捷Web开发使用Rails(版本3)创建购物车。我已经设置了将“商品”添加到“购物车”的位置,然后在开始结帐流程时,它们将作为“line_items”添加到“订单”对象中。 “line_items”代表任何数量的一个“项目”。到目前为止,我没有偏离书中的例子。但是,这里是对我而言变得复杂的地方。我商店中的每个“商品”都可以使用文字进行自定义,并且我需要能够在“订单”中使用“line_items”来存储自定义文字。多个模型的导轨结帐形式

如上所述,“line_items”包含任何数量的“item”,但客户需要能够自定义每个项目,因此每个“line_item”必须为每个“item”项目保留不同的自定义设置。 。因此,“line_items”表中不能只有一列用于自定义。我决定组织它的方式是创建一个新的模型/表“line_item_attributes”。对于“line_item”中的每个“item”,都有一个新的“line_item_attributes”。

我对Rails还很新,而且在解决这个问题上遇到了一些麻烦。我不相信我甚至是这样做的“正确的方式”。我碰到的是一种鸡/鸡蛋问题。当我创建“订单”时,我将购物车中的“商品”添加为“line_items”。现在为了自定义他们订购的产品,我还需要为每个“line_item”添加“line_item_attributes”,以便定制表单可以使用。

以下是我不知道的:我不知道如何在客户提交表单后“填写”空白的“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

这个问题是令人生畏巨大的,可能有多个问题与设计。我认为你应该回到一个更简单的问题,它使用相同的概念,而不是试图一次性解答整个问题。有一个问题需要注意:我认为LineItemAttributes属于订单和line_items可能会造成混淆(但可能很方便)。为了现在简化,是不是只有一个订单有LineItems,LineItem是否有LineItem属性?在任何情况下,您都需要简化您的问题以便在此处进行回答,恕我直言。 – 2010-01-27 18:41:43

+0

你说得对,这个问题都很长,以及你如何简化它。我会再试一次,让它更短,更简单。谢谢。 – John 2010-01-27 21:59:45

回答

1

我建议将Order和LineItems创建移动到单独的“服务对象”或“表单对象”。在服务/表单对象中,将订单和行项目创建包装在单个事务中。代码将更容易阅读,并且您的模型不会受到交叉模型的污染。从checkout控制器中,将@cart对象传递给服务对象,而不是直接调用Order对象。

看#2和有关服务对象更多信息这篇文章的#3:http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/