2008-12-11 9 views
20

J'ai une application Rails qui permet à un utilisateur de construire une requête de base de données en remplissant un formulaire complet. Je me demandais la meilleure pratique pour vérifier les paramètres de formulaire dans Rails. Auparavant, j'ai eu ma méthode results (celle à laquelle la forme présente), procédez comme suit:Validation de formulaire Rails

if params[:name] && !params[:name].blank? 
    @name = params[:name] 
else 
    flash[:error] = 'You must give a name' 
    redirect_to :action => 'index' 
    return 
end 

Mais pour plusieurs champs de formulaire, voir cette répété pour chacun obtenu fastidieux. Je ne pouvais pas les coller tout dans une boucle pour vérifier chaque champ, car les champs sont configurés différemment:

  • une seule clé: params[:name]
  • une clé et une sous-clé: params[:image][:font_size]
  • attendent que des champs de formulaire à remplir si un autre domaine a été mis

Etc. Ce fut aussi répétitif, parce que je mettais flash[:error] pour chaque manquant/paramètre non valide, et la redirection vers la même URL pour chacun. Je suis passé à l'aide d'un before_filter qui vérifie tous les paramètres de formulaire nécessaires et renvoie uniquement vrai si tout va bien. Ensuite, la ma méthode results continue, et les variables sont tout simplement attribué à plat, sans vérification impliqué:

@name = params[:name] 

Dans ma méthode validate_form, j'ai des sections de code comme le suivant:

if (
    params[:analysis_type][:to_s] == 'development' || 
    params[:results_to_generate].include?('graph') 
) 
    {:graph_type => :to_s, :graph_width => :to_s, 
    :theme => :to_s}.each do |key, sub_key| 
    unless params[key] && params[key][sub_key] 
     flash[:error] = "Cannot leave '#{Inflector.humanize(key)}' blank" 
     redirect_to(url) 
     return false 
    end 
    end 
end 

I Je me demandais juste si je m'y prenais de la meilleure façon, ou si je manquais quelque chose d'évident quand il s'agit de la validation des paramètres. Je m'inquiète que ce n'est pas encore la technique la plus efficace, car j'ai plusieurs blocs où j'affecte une valeur à flash[:error], puis redirige vers la même URL, puis retourne false.

Modifier pour clarifier: La raison pour laquelle je n'ai pas cette validation dans le modèle (s) est actuellement pour deux raisons:

  • Je ne cherche pas à recueillir des données de l'utilisateur afin de créer ou mettre à jour une ligne dans la base de données. Aucune des données que l'utilisateur soumet n'est enregistrée après sa déconnexion. Tout est utilisé quand ils le soumettent à une recherche dans la base de données et génèrent des choses.
  • La forme de requête prend en charge des données appartenant à plusieurs modèles et prend en charge d'autres données qui ne se rapportent à aucun modèle. Par exemple. Le type de graphique et le thème montrés ci-dessus ne se connectent à aucun modèle, ils transmettent simplement des informations sur la façon dont l'utilisateur veut afficher ses résultats.

Modifier pour afficher la technique améliorée: Je utilise des exceptions spécifiques à l'application maintenant, grâce à Jamis Buck Raising the Right Exception article. Par exemple:

def results 
    if params[:name] && !params[:name].blank? 
    @name = params[:name] 
    else 
    raise MyApp::MissingFieldError 
    end 

    if params[:age] && !params[:age].blank? && params[:age].numeric? 
    @age = params[:age].to_i 
    else 
    raise MyApp::MissingFieldError 
    end 
rescue MyApp::MissingFieldError => err 
    flash[:error] = "Invalid form submission: #{err.clean_message}" 
    redirect_to :action => 'index' 
end 
+0

Je pense que vous n'avez pas besoin d'utiliser params [: name] et! Params [: name] .blank? dans vos conditions. ! params [: nom] .blank? est assez. params [: nom] renvoie false s'il est nul (il n'y a pas de tel paramètre) et params [: name] .blank? retourne vrai s'il est nul ou vide. – klew

+0

Vous obtenez un NoMethodError. Je pourrais remplacer NilClass pour ajouter #blank? à cela, je suppose. irb (principal): 002: 0> params = {: a => 1,: b => 2,: c => 3} => {: c => 3,: a => 1,: b => 2} irb (principal): 003: 0>! Params [: nom] .blank? NoMethodError: méthode non définie 'blank? ' pour néant: NilClass from (irb): 3 –

+0

Non Ruby ici, seulement Rails. * tag supprimé * – Nakilon

Répondre

25

Vous pouvez essayer active_form (http://github.com/cs/active_form/tree/master/lib/active_form.rb) - juste ActiveRecord moins la base de données. De cette façon, vous pouvez utiliser tous les éléments de validation d'AR et traiter votre formulaire comme vous le feriez pour n'importe quel autre modèle.

class MyForm < ActiveForm 
    validates_presence_of :name 
    validates_presence_of :graph_size, :if => # ...blah blah 
end 

form = MyForm.new(params[:form]) 
form.validate 
form.errors 
+0

Est-ce que 'validates_presence_of: name' est un alias pour' validates: name, presence: true'? Je n'ai vu ce dernier que dans les guides Rails. – Dennis

+1

Pour répondre à ma propre question, la dernière manière est une nouvelle façon de faire des validations introduites dans Rails 3. http://thelucid.com/2010/01/08/sexy-validation-in-edge-rails-rails-3/ – Dennis

6

On dirait que vous faites la validation dans le contrôleur, essayez de le mettre dans le modèle, il est mieux adapté à ce genre de chose.

+4

Comme recommandé dans le [guide] (http://guides.rubyonrails.org/active_record_validations_callbacks.html): «Les validations au niveau du contrôleur peuvent être tentantes à utiliser, mais deviennent souvent difficiles à manier et difficiles à tester et Dans la mesure du possible, c'est une bonne idée de [garder vos contrôleurs skinny] (http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model), car cela rendra votre application un plaisir travailler avec à long terme. " –

2

Si vous deviez attaquer à nouveau le problème d'aujourd'hui, vous pouvez créer un modèle pour l'ensemble des paramètres de la requête et utilisez Rails' construit en validation, Rails 3 rend ce beaucoup plus facile avec ActiveModel :: Validations voir this post.

Questions connexes