2010-07-24 3 views
10

Dans une application Ruby on Rails, j'essaie d'utiliser des informations provenant de champs qui ne sont pas associés au modèle dans la validation.Rails: Utilisation de champs de formulaire non associés à un modèle dans les validations

Voici une partie du modèle à titre d'exemple (le modèle entier a obtenu un peu grand):

class Scorecard < ActiveRecord::Base 
    belongs_to :course 
    belongs_to :user 

    validate :attributes_consistency 

    def attributes_consistency 
    # Executed for all scorecards. Checks if the user completed the hole attributes correctly 
    if (params[:no_fairways] and any_fairways? and !only_nine?) or (params[:no_fairways] and !any_h1_to_h9_score_blank and any_h1_to_h9_fairway? and only_nine?) or (params[:no_fairways] and !any_h10_to_h18_score_blank and any_h10_to_h18_fairway? and only_nine?) 
     errors.add_to_base("You inidicated that you missed all the fairways, but you also marked one or more fairways in the scorecard. Either uncheck the fairways mistakenly marked or uncheck the 'No fairways' checkbox.") 
    end 
    if (params[:no_girs] and any_girs? and !only_nine?) or (params[:no_girs] and !any_h1_to_h9_score_blank and any_h1_to_h9_gir? and only_nine?) or (params[:no_girs] and !any_h10_to_h18_score_blank and any_h10_to_h18_gir? and only_nine?) 
     errors.add_to_base("You inidicated that you missed all the greens, but you also marked one or more greens in the scorecard. Either uncheck the marked greens on the scorecard or uncheck the 'No GIRs' checkbox.") 
    end 
    end # attributes_consistency 


    def any_h1_to_h9_score_blank? 
    h1_score.blank? or h2_score.blank? or h3_score.blank? or h4_score.blank? or h5_score.blank? or h6_score.blank? or h7_score.blank? or h8_score.blank? or h9_score.blank? 
    end 
    def any_h10_to_h18_score_blank? 
    h10_score.blank? or h11_score.blank? or h12_score.blank? or h13_score.blank? or h14_score.blank? or h15_score.blank? or h16_score.blank? or h17_score.blank? or h18_score.blank? 
    end 

    def any_h1_to_h9_fairway? 
    h1_fairway? or h2_fairway? or h3_fairway? or h4_fairway? or h5_fairway? or h6_fairway? or h7_fairway? or h8_fairway? or h9_fairway? 
    end 
    def any_h10_to_h18_fairway? 
    h10_fairway? or h11_fairway? or h12_fairway? or h13_fairway? or h14_fairway? or h15_fairway? or h16_fairway? or h17_fairway? or h18_fairway? 
    end 

    def any_h1_to_h9_gir? 
    h1_gir? or h2_gir? or h3_gir? or h4_gir? or h5_gir? or h6_gir? or h7_gir? or h8_gir? or h9_gir? 
    end 
    def any_h10_to_h18_gir? 
    h10_gir? or h11_gir? or h12_gir? or h13_gir? or h14_gir? or h15_gir? or h16_gir? or h17_gir? or h18_gir? 
    end 

Alors, comment puis-je accéder params du modèle?

Répondre

15

Ne laissez pas les paramètres se faufiler jusqu'au modèle. Il ne sert à rien d'avoir un contrôleur dans ce cas. Au lieu de cela, vérifiez cet épisode de Railscasts qui parle d'attributs virtuels qui ne vont pas dans la base de données, mais peuvent encore être utilisés pour les validations.

Vous n'avez pas besoin d'un attribut de modèle correspondant pour les attributs virtuels. Définissez les attributs locaux de la classe tels que @no_fairways qui contiennent l'état.

class ScoreCard < ActiveRecord::Base 
    # define attributes and accessors for both fields 
    attr_accessor :no_fairways, :no_girs 

    .. 
end 

maintenant à l'intérieur que vous formez, vous pouvez simplement écrire:

<% form_for @scorecard %> 
    <%= f.check_box :no_fairways %> 
<% end %> 
+0

Ce serait une excellente solution, mais pourriez-vous donner un exemple de la façon dont je pourrais implémenter cela? Dans ce Railscast particulier, les "attributs virtuels" sont en réalité des méthodes qui manipulent des attributs réels. Je n'ai pas d'attributs auxquels 'no_fairways' ou' no_girs' peuvent être associés. – Jay

+0

@James - l'attribut virtuel n'a pas besoin d'être associé à un attribut de base de données. Vous pouvez définir des attributs d'instance qui fonctionneront aussi bien. Réponse mise à jour – Anurag

+0

Notez que attr associé à la case à cocher n'aura pas de valeur trythy ou falsy. Par défaut 'check_box' génère un balisage qui a pour résultat' '0" 'chaîne si non cochée et' "1" 'lorsqu'elle est cochée. Même «0» .présent? »Est véridique. – kolen

3

trouvé la solution, merci pour le lingo cependant, ont aidé à Google searchin "attribut virtuel".

La manière la plus simple d'y parvenir consiste à créer des attributs qui ne font pas partie de la base de données mais font partie du modèle. Dans mon cas, j'ai mis cela dans le modèle:

attr_accessor :no_fairways 
attr_accessor :no_girs 

C'est facile! Maintenant, @scorecard.no_fairways et @scorecard.no_girs agissent comme n'importe quel autre attribut mais ne font pas partie de la base de données.

Questions connexes