2009-04-01 5 views
4

Quelqu'un peut-il me dire pourquoi le formulaire à la fin de cette question ne fonctionne pas comme il le devrait?Rails: Création d'un formulaire de modèle multiple sur n niveaux d'association

  • Enregistrer ne fonctionne pas
  • La sélection auxiliaire ne sélectionne pas la valeur selon l'objet @kid

L'ensemble est basé sur Rails 2.2.2 et non, la mise à niveau Rails 2.3 pour résoudre ce problème n'est pas une option. J'ai utilisé this recipe pour créer le formulaire de modèle multiple.

# CLASS GRANDPARENT 
class Grandparent < ActiveRecord::Base 
    has_many :parents 
end 

# CLASS PARENT 
class Parent < ActiveRecord::Base 
    belongs_to :grandparent, :class_name => "Grandparent", :foreign_key => "grandparent_id" 
    has_many :kids 
end 

# CLASS KID 
class Kid < ActiveRecord::Base 
    belongs_to :parent, :class_name => "Parent", :foreign_key => "parent_id" 

    # Virtual attribute setter for new self.parent.grandparent (Grandparent) attributes 
    def new_grandparent_attributes=(_gp_attributes) 
    self.parent.build_grandparent(_gp_attributes) 
    end 

    # Virtual attribute setter for existing self.parent.grandparent (Grandparent) attributes 
    def existing_grandparent_attributes=(_gp_attributes) 
    unless self.parent.grandparent.new_record? 
     attributes = _gp_attributes[self.parent.grandparent.id.to_s] 
     if attributes 
     self.parent.grandparent.attributes = attributes 
     else 
     self.parent.grandparent.delete(grandparent) 
     end 
    end 
    end 

end 

# CONTROLLER KIDS 
class KidsController < ApplicationController 
    def new 
    @kid = Kid.new 
    end 

    def edit 
    @kid = Kid.find(params[:id]) 
    end 

    def create 
    params[:kid][:new_grandparent_attributes] ||= {} 
    @kid = Kid.new(params[:kid]) 
    end 

    def update 
    params[:kid][:existing_grandparent_attributes] ||= {} 
    @kid = Kid.find(params[:id]) 
    end 

end 


# THIS IS THE MULTI-MODEL FORM USED IN THE VIEW 

<% form_for(@kid) do |f| %> 
    <p> 
     <% new_or_existing = @kid.parent.grandparent.new_record? ? 'new' : 'existing' %> 
     <% prefix = "kid[#{new_or_existing}_grandparent_attributes][]" %> 

     <% fields_for prefix, @kid.parent.grandparent do |g_f| -%> 
      <p> 
       <%= g_f.label :, 'Grandparent Name' %><br /> 
       <!-- THE FOLLOWING FORM DOESN'T CHANGE ACCORDING TO EXISTING @child --> 
       <%= @grandparents = Entity.find(:all, :order => :name) 
       g_f.collection_select(:name ,@grandparents, :id, :name) 
       %> 
      </p> 
     <% end %> 
    </p> 
    <p> 
     <%= f.label :name, "Kid Name" %><br /> 
     <%= f.text_field :name %> 
    </p> 
    <%= submit_tag 'Go' %> 
<% end %> 

Répondre

1

Correctement, corrigez-moi si je me trompe mais il ne semble pas que vous sauvegardiez réellement l'objet n'importe où. Dans vos actions de création et de mise à jour, vous appelez new et ne l'enregistrez pas.

Pour corriger cela, vous pouvez faire:

def create 
    params[:kid][:new_grandparent_attributes] ||= {} 
    @kid = Kid.new(params[:kid]) 
    if @kid.save 
    # successful save logic here 
    else 
    #failed save logic here 
    end 
end 

def update 
    params[:kid][:existing_grandparent_attributes] ||= {} 
    @kid = Kid.find(params[:id]) 
    if @kid.update_attributes(params[:kid]) 
    #successful save logic here 
    else 
    #failed save logic here 
    end 
end 

Puis dans votre boîte de sélection que vous essayez de trouver tous les records de Entity, pas les champs de Entity qui sont liés à @kid. Pour ce faire, vous devrez établir une relation entre l'enfant et les grands-parents.

# CLASS GRANDPARENT 
class Grandparent < ActiveRecord::Base 
    has_many :parents 
    has_many :grand_kids, :through => :parents 
end 

# CLASS PARENT 
class Parent < ActiveRecord::Base 
    belongs_to :grandparent, :class_name => "Grandparent", :foreign_key => "grandparent_id" 
    has_many :kids 
end 

# CLASS KID 
class Kid < ActiveRecord::Base 
    belongs_to :parent, :class_name => "Parent", :foreign_key => "parent_id" 
    belongs_to :grandparent 

    # ... 

De cette façon, vous pouvez accéder aux grands-parents d'un enfant à travers par @kid.grandparents. Ensuite, vous pouvez générer le champ de sélection:

<%= g_f.collection_select(:name ,@kid.grandparents, :id, :name) %> 
Questions connexes