2010-01-27 21 views
0

Je crée un panier basé sur celui de Agile Web Development With Rails (version 3). Je l'ai mis en place où "articles" sont ajoutés à un "panier", puis au démarrage du processus de commande, ils sont ajoutés à un objet "commande" comme "line_items". "line_items" représente un "item" dans n'importe quelle quantité. Jusqu'à présent, je ne m'écarte pas des exemples du livre. Cependant, voici où cela devient compliqué pour moi. Chaque "article" dans mon magasin est personnalisable avec le texte, et je dois pouvoir stocker le texte fait sur commande avec le "line_items" dans les "ordres". Comme mentionné ci-dessus, les "éléments_ligne" contiennent n'importe quelle quantité d'un "élément", mais les clients doivent pouvoir personnaliser chaque élément, de sorte que chaque "élément_ligne" doit contenir les différentes personnalisations pour chaque "élément" individuel. . Ainsi, il ne peut y avoir qu'une seule colonne pour la personnalisation dans la table "line_items". La façon dont j'ai décidé de l'organiser était de créer un nouveau modèle/table "line_item_attributes". Pour chaque "item" individuel dans un "line_item" il y a un nouveau "line_item_attributes". Je suis encore assez nouveau pour Rails, et j'ai du mal à le faire fonctionner. Je ne suis pas convaincu que je suis même en train de faire ça la "bonne manière". Ce que j'ai rencontré est une sorte de problème poulet/oeuf. Lorsque je crée une "commande", j'ajoute les "articles" du panier comme "éléments_ligne". Maintenant, afin de personnaliser les produits qu'ils commandent, je dois aussi ajouter "line_item_attributes" à chaque "line_item" afin que le formulaire de personnalisation puisse fonctionner.Rails formulaire de paiement avec plusieurs modèles

Voici ce que je ne sais pas: Je ne sais pas comment "remplir" le vide "line_item_attributes" après que le client soumet le formulaire. Je ne peux pas créer de "doublet" line_item_attributes pour le formulaire, et lors de la soumission, j'en créerai de nouveaux (ceux qui seront effectivement sauvegardés) à partir des données soumises. La raison en est qu'ils doivent être liés aux «éléments de ligne» auxquels ils appartiennent. J'avais espéré que Rails les remplirait quand j'appellerais "@ order.save", mais ce n'est pas le cas. J'espère que ce n'est pas difficile à comprendre.

J'ai inclus le code pertinent ci-dessous:

buy.rb (contrôleur)

-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 (modèle)

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 (modèle)

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 (modèle)

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

Merci pour toute aide!

+1

Cette question est décourageante énorme, et il peut y avoir plusieurs problèmes avec la conception.Je pense que vous devriez revenir à une question plus simple qui utilise les mêmes concepts sans essayer de répondre à toute la question en une fois. Une question pour vous: je pense qu'il peut être déroutant (mais pourrait être pratique) que LineItemAttributes appartienne à orders et line_items. Pour simplifier pour le moment, n'est-ce pas juste qu'une commande a LineItems et qu'un LineItem a des attributs LineItem? En tout cas, vous aurez besoin de simplifier votre question pour obtenir une réponse ici, à mon humble avis. –

+0

Vous avez raison, à la fois que la question est longue, et comment vous l'avez simplifié. Je vais essayer à nouveau et le rendre plus court et plus simple. Merci. – John

Répondre

1

Je recommande de déplacer la création Order et LineItems vers un "objet de service" ou un "objet de formulaire" séparé. Dans l'objet service/formulaire, encapsulez la commande et la création d'éléments de campagne en une seule transaction. Le code sera plus facile à lire et vos modèles ne seront pas pollués avec le modèle croisé. À partir du contrôleur de caisse, passez l'objet @cart à l'objet service au lieu d'appeler directement l'objet Order.

Regardez # 2 et # 3 de cet article pour plus d'informations sur les objets de service: http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/