2009-12-07 5 views
2

Nous avons un véhicule modèle parent qui est hérité pour faire des classes voiture, camion, SUV. Dans notre formulaire, nous permettons à l'utilisateur de modifier les données pour un groupe de véhicules, et l'un des attributs de chaque véhicule est un menu de sélection pour "type". L'attribut HTML est nommé VEHICLE_TYPE et met à jour l'attribut de type polymorphes réelle dans le modèle du véhicule:Rails changeant type polymorphique d'un objet

# Get/Set Type bc rails doesnt allow :type to be set in mass 
    def vehicle_type 
    self.type 
    end 
    def vehicle_type=(type) 
    self.type = type 
    end 

Le problème que nous avons est que lorsque nous appelons update_attributes sur les données de formulaire et le type d'un véhicule existant a été modifié , rails appelle la validation de l'ancienne classe (pas un nouveau type) qui entraîne des erreurs. Ce que nous devons faire, c'est quand vehicle_type est changé, que le modèle est également changé en ce nouveau type.

Existe-t-il un moyen de le faire?


Voici l'action de mise à jour (flotte de véhicules has_many):

# PUT /fleet/1 
    # PUT /fleet/1.xml 
    def update 
    @fleet = Fleet.find(params[:id]) 

    respond_to do |format| 
     if @fleet.update_attributes(params[:fleet]) 
     flash[:notice] = 'Fleet of vehicles was successfully updated.' 
     format.html { render :action => "edit" } 
     format.xml { head :ok } 
     else 
     format.html { render :action => "edit" } 
     format.xml { render :xml => @fleet.errors, :status => :unprocessable_entity } 
     end 
    end 
    end 

Voici la flotte:

class Fleet < ActiveRecord::Base 
    has_many :vehicles, :dependent => :destroy, :order => 'position ASC' 
    accepts_nested_attributes_for :vehicles, 
    :reject_if => proc { |attrs| attrs['name'].blank? }, 
    :allow_destroy => true 
+0

Les modèles utilisent-ils un héritage de table unique? Pourriez-vous publier l'action de mise à jour pour les contrôleurs en question? – EmFi

+0

Hey EmFi, oui, ils utilisent l'héritage Table unique. Question mise à jour ci-dessus avec le code pour la mise à jour. – LMH

Répondre

0

Lorsque vous appelez @vehicle.save, vous pouvez ajouter false comme premier paramètre à Ignorer la validation (@vehicle.save(false)). Une autre option consiste à utiliser ActiveRecord::Base#update_attribute - qui ignore la validation.

Vous pouvez donc enregistrer votre modèle sans changer de colonne, puis ajouter un @vehicle.update_attribute(:type, "Truck") dans la même action. Deux requêtes SQL, mais peuvent être nécessaires pour votre situation.

+0

Si je fais cela même si nous n'avons plus aucune validation pour le véhicule? J'espérais qu'il pourrait y avoir un moyen de garder la validation pour le véhicule (juste le bon véhicule) et ne pas avoir à parcourir manuellement chaque véhicule pour ce faire (c'est-à-dire toujours utiliser update_attributes). – LMH

2

Vous pouvez utiliser une méthode d'usine pour créer le bon type de véhicule, puis affecter les attributs.

def Vehicle.factory(type) 
    type.constantize.new 
end 
+0

Cela nécessiterait d'abandonner la méthode update_attributes tout ensemble et d'effectuer une itération manuelle à travers chaque véhicule. J'espérais qu'il pourrait y avoir une façon de quitter le code update_attribute (j'ai ajouté le code du contrôleur à la question). – LMH

+0

Oui, je n'ai pas beaucoup fait avec accept_nested_attributes_for, donc je ne sais pas comment modifier les méthodes qu'il crée. (J'utilise toujours l'ancienne méthode "ryanb" pour les formes imbriquées.) C'est une toute nouvelle fonctionnalité dans Rails et je ne vois pas de ticket dans le phare. Je vais voir si je peux le dupliquer localement et ensuite ajouter un ticket. – MattMcKnight