2009-12-11 7 views
0

J'ai une recherche maintenant partielle comme ceci:Rails: construire assoc est dans: objet tout en rendant une partie

<%= render(:partial => 'order', :object => Order.new %> 

Comment puis-je construire quelques objet LineItem vide dans le Order.new comme dans: objet => Commander.new?

Notez que Order has_many: line_items. Et comme un commentateur mentionné, cela pourrait sembler à première vue enfreindre la conception MVC, mais j'ai oublié de mentionner que ce rendu est vraiment dans une aide link_to_function qui sert à insérer dynamiquement plus de champs de l'attribut élément de campagne.

L'aide réelle ressemble à ceci:

#orders_helper.rb 
    def add_line_item_link(name, form_scope) 
    link_to_function name, :class => "add_line_item_link" do |page| 
     line_item_html = render(:partial => 'line_item', :object => @order.line_items.new, :locals => {:f => form_scope}) 
     page << %{ 
     var time_index = new Date().getTime(); 
     var line_item_html = #{line_item_html.to_json}; 
     line_item_html = line_item_html.replace(/_\\d+/g, "_"+time_index); 
     line_item_html = line_item_html.replace(/\\[\\d+\\]/g, "\\["+time_index+"\\]"); 
     $('line_items').insert({bottom: line_item_html}); 
     } 
    end 
    end 

@ order.line_items.new est ce que j'aime travailler sur:

premier: Je veux au lieu d'un seul Line_Item à construire dans la @order objet, je veux trois. deuxième: l'élément de campagne a un attribut nommé 'title', et chaque fois que nous recevons une commande, à peu près chaque fois que la commande contient exactement trois éléments, un éditeur de titres, un photographe de titre et un éditeur de vidéo .

, peut-être que je peux donc je pensais que si quelque chose comme:

#orders_controller.rb 
@titles = %w(editor photographer video-editor) 

#orders_helper.rb 
...#same as above 
:partial => 'line_items', :collection => lambda { @titles.each {|t| @order.line_items.build(:title => t) } return @order.line_items} 
... 

des suggestions? Merci

Répondre

0

En réponse à votre question-- changé

#order.rb 
def default_line_items 
    self.line_items.build(:title => "editor") 
    self.line_items.build(:title => "photographer") 
    self.line_items.build(:title => "video_editor") 
    return self.line_items 
end 
#call to partial 
render (:partial => "line_item", :collection => order.default_line_items) 
+0

Merci Matt, ça a marché! C'est très propre par rapport à la façon dont je pensais que je pourrais même aborder le problème. –

+0

Cette méthode pourrait être une doublure, pas DRY. De même, le mot-clé return et les récepteurs explicites sont inutiles. –

+0

Pas besoin de faire un doublure et ne pas utiliser un mot-clé explicite lorsque vous essayez d'expliquer quelque chose et de le rendre clair. – MattMcKnight

0

Je suis désolé, mais c'est une odeur grave de code pour moi. Violation des principes MVC. Le calque Vue ne doit avoir aucune interaction directe avec le calque Modèle.

+0

Ce n'est pas vrai du tout et c'est un grave malentendu de MVC. Si vous appelez @ model.property, vous interagissez avec le modèle. – MattMcKnight

+0

_Reductio ad absurdum_. Je pense que vous êtes hypocrite ici. Je fais référence à Object.new dans la couche View. Le contrôleur régit l'interaction entre les couches Vue et Modèle.L'appel d'une méthode getter sur une instance construite par la couche Controller est très différent de l'instanciation depuis la couche View. À aucun moment, la couche Vue ne doit modifier l'état de la couche Modèle ou les méthodes de classe d'appel. Ce n'est certainement pas un malentendu, même la personne qui a posé la question a concédé mon point de vue et clarifié davantage sa question. Je comprends très bien MVC merci! :) –

+0

J'essaie de minimiser les instances où j'appelle des méthodes sur l'objet classe de modèle dans les vues afin de suivre la conception MVC. - Dans ce cas, parce que c'est un peu comme l'une de ces applications 'liste de choses à faire' où vous pouvez dynamiquement ajouter plus de 'tâches', donc j'ai besoin d'un modèle contenant tous les champs et boutons, etc. en place pour être inséré dans le HTML en changeant seulement les parties id et name des champs d'entrée avec un horodatage afin de les différencier lors de l'enregistrement. À cause de tout cela, dans la méthode auxiliaire, j'ai besoin d'une sorte d'objet vide pour fournir le nom et l'identifiant corrects dans les entrées. –

1

Refactor de la réponse de Matt:

def default_line_items 
    line_items.build %w(editor photographer video_editor).collect { |i| {:title => i } } 
end 

ligne One. Fait la même chose.

+0

Je dois admettre que l'approche ligne par ligne illustrative de Matt ici dans la section réponse n'est pas du tout mauvaise; mais votre version raccourcie est aussi très curieuse et attrayante à utiliser. Mais je ne vois pas comment cela génère trois lignes et si c'est un code valide? Je veux dire, si ça marche, c'est probablement valide, c'est assez facile à vérifier. J'ai demandé parce que je pensais que chaque model.build crée un seul objet dans la mémoire. Je peux voir que la boucle est là, mais c'est après le model.build, le model.build sera "aspiré" dans la boucle, aussi –

+0

Base # create et la méthode de construction d'une collection peut prendre un tableau d'objets à construire ou créer. '% w (éditeur photographe video_editor) .collect {| i | {: title => i}} 'retournera [{: title =>" editor "}, {: title =>" photographer "}, {: title =>" video_editor "}]' faisant ainsi le code 'line_items .build [{: title => "editor"}, {: title => "photographer"}, {: title => "video_editor"}] 'ceci va ajouter trois objets line_item à la collection. Ils seront conservés à la db SI vous appelez enregistrer sur eux ou le modèle parent. La méthode fonctionne définitivement, je l'ai moi-même utilisée! :) –