2010-11-02 5 views
1

J'ai 2 modèles, Category et LineItemTypesCréation ou suppression d'associations avec accepts_nested_attributes_for

Il y a déjà beaucoup, il est à la fois existant, maintenant une exigence pour eux d'être associés. Étant plusieurs LineItemTypes pour chaque catégorie.

J'ai ajouté accepts_nested_attributes_for :line_item_types sur Category

J'ai essayé d'utiliser un hidden_field sur un formulaire pour créer une liste des associés existants LineItemTypes:

- form_for @category do |form| 
    %ul#categorised 
    - form.fields_for :line_item_types do |line_item_types| 
     -categorised.each do |l| 
     %li 
      =l.description 
      =line_item_types.hidden_field :category_id 

    =form.submit 

Si j'ajoute un élément à cette liste, je obtenir des erreurs indiquant qu'un LineItemType pour cette catégorie est introuvable. Je pensais que accept_nested_attributes_for ajouterait l'association si elle n'existe pas. Ou est-ce seulement pour «créer» de nouveaux enregistrements et modifier des relations existantes, sans créer de nouvelles relations.

a.update_attributes({:line_item_types_attributes => [{:id => 2767}, {:id => LineItemType.find(2).id}]}) 
ActiveRecord::RecordNotFound: Couldn't find LineItemType with ID=2 for Category with ID=1 

Des idées sans avoir à écrire quelque chose pour parcourir les params de forme résultants et créer les associations? Ou un moyen encore plus facile d'y parvenir?

Répondre

2

Je suis arrivé à la conclusion que accept_nested_attributes_for fonctionne un peu comme url_for ... Où la présence d'ID lui fait supposer que la relation existe. Rendering accepte_nested_attributes_for ne convient pas à ce que je veux faire.

Je travaille autour de cela avec un filtre avant:

def find_line_item_types 
    params[:category][:line_item_types] = LineItemType.find(params[:category][:line_item_types].collect { |a| a[0].to_i }) if params[:category] and params[:category][:line_item_types] 
end 
0

vous ne devriez pas être en mesure de créer line_item_types à partir d'une instance Category sans spécifier le category_id dans les attributs line_item_types!

Vous devez vérifier que vous avez l'option: inverse_of dans vos déclarations has_many et belongs_to.

# in Category 
has_many :line_item_types, :inverse_of => :category 

# In LineItemType 
belongs_to :category, :inverse_of => :line_item_types 

Dites-moi si cela aide.

+0

Désolé, obtenez toujours la même erreur. Je peux créer NEW line_item_types sur cette catégorie mais je ne peux pas associer line_item_types existant avec une catégorie existante ... – stuartc

0

Eh bien, j'eu le même problème, donc je cherchai dans la source et le singe patché accepts_nested_attributes_for pour permettre ce comportement ...

https://gist.github.com/2223565

Il ressemble beaucoup, mais je fait juste modifier quelques lignes:

module ActiveRecord::NestedAttributes::ClassMethods 
    def accepts_nested_attributes_for(*attr_names) 
    # ... 
    #options.assert_valid_keys(:allow_destroy, :reject_if, :limit, :update_only) 
    options.assert_valid_keys(:allow_destroy, :reject_if, :limit, :update_only, :allow_existing) 
    # ... 
    end 
end 

Et ...

module ActiveRecord::NestedAttributes 
    def assign_nested_attributes_for_collection_association(association_name, attributes_collection, assignment_opts = {}) 
    # ... 
    #existing_records = if association.loaded? 
    # association.target 
    #else 
    # attribute_ids = attributes_collection.map {|a| a['id'] || a[:id] }.compact 
    # attribute_ids.empty? ? [] : association.scoped.where(association.klass.primary_key => attribute_ids) 
    #end 

    existing_records = if options[:allow_existing] or not association.loaded? 
     attribute_ids = attributes_collection.map {|a| a['id'] || a[:id] }.compact 
     scope = options[:allow_existing] ? association.target_scope : association.scoped 
     scope.where(association.klass.primary_key => attribute_ids) 
    else 
     association.target 
    end 
    # ... 
    end 
end 
Questions connexes