it-swarm.com.de

Rails-Formularprüfung

Ich habe eine Rails-App, mit der ein Benutzer eine Datenbankabfrage erstellen kann, indem er ein umfangreiches Formular ausfüllt. Ich wunderte mich über die bewährte Methode zum Überprüfen von Formularparametern in Rails. Zuvor hatte ich mit meiner results-Methode (der Methode, an die das Formular übermittelt wird) Folgendes ausgeführt:

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

Aber für mehrere Formularfelder wurde es langweilig, wenn man dies für jedes Formular wiederholt sah. Ich konnte sie nicht einfach in eine Schleife stecken, um jedes Feld zu überprüfen, da die Felder unterschiedlich eingerichtet sind:

  • ein einzelner Schlüssel: params[:name]
  • einen Schlüssel und einen Unterschlüssel: params[:image][:font_size]
  • erwarten Sie nur, dass einige Formularfelder ausgefüllt werden, wenn ein anderes Feld festgelegt wurde

Dies wiederholte sich auch, da ich flash[:error] für jeden fehlenden/ungültigen Parameter einrichtete und für jeden Parameter die gleiche URL umleitete. Ich wechselte zu einem before_filter, der alle notwendigen Formularparameter prüft und nur dann true zurückgibt, wenn alles in Ordnung ist. Dann fährt die my results-Methode fort, und die Variablen werden einfach platt zugewiesen, ohne dass eine Überprüfung erforderlich ist:

@name = params[:name]

In meiner validate_form-Methode habe ich folgende Codeabschnitte:

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

Ich habe mich nur gefragt, ob ich das am besten mache oder ob mir bei der Validierung von Parametern etwas offensichtliches fehlt. Ich mache mir Sorgen, dass dies immer noch nicht die effizienteste Technik ist, da ich mehrere Blöcke habe, in denen ich flash[:error] einen Wert zuweise, dann auf dieselbe URL umleite und dann false zurückgibt.

Bearbeiten, um zu klären: Der Grund, warum ich diese Validierung in Modellen derzeit nicht habe, hat zwei Gründe:

  • Ich versuche nicht, Daten vom Benutzer zu sammeln, um eine Zeile in der Datenbank zu erstellen oder zu aktualisieren. Keine der Daten, die der Benutzer übermittelt, wird nach dem Abmelden gespeichert. Es wird alles richtig verwendet, wenn sie es einreichen, um die Datenbank zu durchsuchen und etwas zu generieren.
  • Das Abfrageformular enthält Daten, die sich auf mehrere Modelle beziehen, und andere Daten, die sich überhaupt nicht auf ein Modell beziehen. Z.B. Diagrammtyp und Design wie oben gezeigt stellen keine Verbindung zu einem Modell her, sie vermitteln lediglich Informationen darüber, wie der Benutzer seine Ergebnisse anzeigen möchte.

Bearbeiten, um die verbesserte Technik anzuzeigen: Ich verwende jetzt anwendungsspezifische Ausnahmen, dank Jamis Buck's Raising the Right Exception-Artikel . Zum Beispiel:

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

Sie könnten active_form versuchen (  http://github.com/cs/active_form/tree/master/lib/active_form.rb) - Nur ActiveRecord minus Datenbankmaterial. Auf diese Weise können Sie das gesamte Validierungsmaterial von AR verwenden und Ihr Formular wie jedes andere Modell behandeln.

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

Sieht so aus, als würden Sie die Validierung im Controller durchführen, versuchen Sie es in das Modell einzufügen, es ist besser für solche Dinge geeignet.

6
Jamal Hansen

Wenn Sie das Problem heute noch einmal angehen würden, könnten Sie ein Modell für den Abfrageparametersatz erstellen und die integrierten Validierungen von Rails verwenden. Rails 3 macht dies mit ActiveModel :: Validations viel einfacher - siehe this post .

2
weston

Modell

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

Beachten Sie, dass Sie das Modell zur Validierung nicht unbedingt speichern oder beibehalten müssen.

Regler

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

Eine, die Sie angerufen haben. Wenn Sie die Methode des Modells verwenden, werden die Fehler in einem @person-Objekt angezeigt. Daher,

Aussicht

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