2010-03-26 5 views
2

J'ai mise en œuvre STI comme suit:Comment remplacer le attr_protected?

class Automobile < ActiveRecord::Base 
end 

class Car < Automobile 
end 

class Truck < Automobile 
end 

class User < ActiveRecord::Base 
    has_many :automobiles 
    accepts_nested_attributes_for :automobiles 
end 

Je crée une liste d'automobiles pour un utilisateur. Pour chaque automobile, l'interface utilisateur définit le champ type et les propriétés associées à l'automobile. Pendant la soumission du formulaire, le champ type est ignoré car il s'agit d'un attribut protégé.

Comment puis-je contourner ce problème? Existe-t-il un moyen déclaratif d'attribuer un attribut protégé à unprotect?

Edit: Ceci est ma solution actuelle pour le problème: je remplacer la méthode privée attributes_protected_by_default dans ma classe de modèle.

class Automobile < ActiveRecord::Base 
private 
    def attributes_protected_by_default 
    super - [self.class.inheritance_column] 
    end 
end 

Cela supprime le champ type de la liste protégée.

J'espère qu'il y a un meilleur moyen que cela.

Répondre

1

Je fini par faire ceci:

class Automobile < ActiveRecord::Base 
private 
    def attributes_protected_by_default 
    super - [self.class.inheritance_column] 
    end 
end 
+0

J'ai essayé ceci mais apparemment Automobile.new (params [: automobile]) ne fonctionne pas dans mon action controller-create. –

0

Je voudrais ajouter une méthode d'assistance sur l'utilisateur qui instancie la sous-classe appropriée:

class User < ActiveRecord::Base 
    def self.automobile_from_type(type) 
    self.automobiles << case type 
    when "Car" 
     Car.new 
    when "Truck" 
     Truck.new 
    else 
     raise ArgumentError, "Unknown automobile type: #{type.inspect}" 
    end 
    end 
end 

utiliser comme ceci:

class AutomobilesController < ApplicationController 
    def create 
    @automobile = current_user.automobile_from_type(params[:automobile][:type]) 
    if @automobile.update_attributes(params[:automobile]) then 
     redirect_to @automobile 
    else 
     render :action => :new 
    end 
    end 
end 

Le code ci-dessus est « sûr »: un attaquant ne peut pas injectez du texte arbitraire dans votre colonne automobiles.type. Votre solution, même si elle fonctionne, présente l'inconvénient de permettre des attaques.

+0

Mon scénario est un peu plus compliqué. J'ai trois couches de nidification dans ma soumission. Je dois recréer toute la structure pour effectuer cette validation. J'ai eu recours à l'ajout d'une validation de format pour le champ 'type' dans la classe Automobile. –

Questions connexes