web-dev-qa-db-fra.com

Validation du formulaire Rails

J'ai une application Rails qui permet à un utilisateur de créer une requête de base de données en remplissant un formulaire détaillé. Je me suis demandé quelle était la meilleure pratique pour vérifier les paramètres de formulaire dans Rails. Auparavant, ma méthode results (celle à laquelle le formulaire est soumis) s’effectue comme suit:

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, le voir répété pour chacun devenait fastidieux. Je ne pouvais pas simplement les insérer tous 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]
  • attendez-vous à ce que des champs de formulaire soient remplis si un autre champ a été défini

Etc. Cela a également été répétitif, car je mettais flash[:error] pour chaque paramètre manquant/invalide, et redirigeais vers la même URL pour chacun. Je suis passé à utiliser un before_filter qui vérifie tous les paramètres de formulaire nécessaires et ne renvoie true que si tout va bien. Ensuite, la méthode my results continue, et les variables sont simplement assignées à plat, sans vérification:

@name = params[:name]

Dans ma méthode validate_form, j'ai des sections de code comme celles-ci:

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

Je me demandais simplement si je m'y prenais de la meilleure façon ou s'il me manquait quelque chose d'évident en ce qui concerne la validation des paramètres. Je crains que ce ne soit toujours pas la technique la plus efficace, car j'ai plusieurs blocs dans lesquels j'attribue une valeur à flash[:error], puis je redirige vers la même URL, puis je renvoie false.

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

  • Je n'essaie pas de collecter des données de l'utilisateur afin de créer ou de mettre à jour une ligne dans la base de données. Aucune des données soumises par l'utilisateur n'est sauvegardée après sa déconnexion. Tout est utilisé dès leur soumission pour effectuer une recherche dans la base de données et générer des données.
  • Le formulaire de requête prend en charge des données appartenant à plusieurs modèles, ainsi que d'autres données qui ne concernent aucun modèle. Par exemple. Le type de graphique et le thème, comme indiqué ci-dessus, ne se connectent à aucun modèle, ils transmettent simplement des informations sur la manière dont l'utilisateur souhaite afficher ses résultats.

Éditer pour montrer une technique améliorée: J'utilise maintenant les exceptions spécifiques à une application, grâce à l'article de Jamis Buck - Raising the Right Exception . 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
21
Sarah Vessels

Vous pouvez essayer active_form (  http://github.com/cs/active_form/tree/master/lib/active_form.rb) - juste ActiveRecord moins les affaires de base de données. De cette façon, vous pouvez utiliser tous les éléments de validation d'AR et traiter votre formulaire comme 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
25
casey

On dirait que vous faites la validation dans le contrôleur, essayez de l'insérer dans le modèle, c'est mieux adapté à ce genre de chose.

6
Jamal Hansen

Si vous deviez vous attaquer de nouveau au problème aujourd'hui, vous pourriez créer un modèle pour le jeu de paramètres de requête et utiliser les validations intégrées de Rails. Rails 3 simplifie grandement cette opération avec ActiveModel :: Validations voir this post .

2
weston

Modèle

class Person 
    include ActiveModel::Validations
    include ActiveModel::Conversion
    extend ActiveModel::Naming

    attr_accessor :name
    attr_accessor :email


    validates_presence_of :name,:message => "Please Provide User Name"
    validates_presence_of :email,:message => "Please Provide Email"
end

Notez que vous n'avez pas nécessairement besoin de sauvegarder/conserver le modèle pour le valider.

Manette

@person.name= params["name"]
@person.email= params["email"]
@person.valid?

Un que vous avez appelé .valid? méthode sur le modèle, les erreurs seront renseignées dans l’objet @person. Par conséquent,

Vue

<%if @person.errors.any? %>
     <%@person.errors.messages.each do|msg| %>
          <div class="alert alert-danger">
            <%=msg[0][1]%>
          </div>
     <%end%>
<%end%>
0
zawhtut