Ich habe eine Rails-App, mit der ein Benutzer eine Datenbankabfrage erstellen kann, indem er ein umfangreiches Formular ausfüllt. Ich fragte mich, die beste Praxis für die Überprüfung der Formularparameter in Rails. Zuvor habe ich meine results
Methode (diejenige, an die das Formular gesendet wird), tun Sie Folgendes:
if params[:name] && !params[:name].blank?
@name = params[:name]
else
flash[:error] = 'You must give a name'
redirect_to :action => 'index'
return
end
Aber bei mehreren Formularfeldern wurde es lästig, dies für jedes einzelne Feld zu wiederholen. Ich konnte sie nicht einfach alle in eine Schleife stecken, um jedes Feld zu überprüfen, weil die Felder unterschiedlich eingerichtet sind:
- eine einzige Taste:
params[:name]
- einen Schlüssel und einen Unterschlüssel:
params[:image][:font_size]
- nur erwarten, dass einige Formularfelder ausgefüllt werden, wenn ein anderes Feld gesetzt wurde
Etc. Dies war auch wiederholend, weil ich die flash[:error]
für jeden fehlenden/ungültigen Parameter und die Weiterleitung an dieselbe URL für jeden einzelnen. Ich bin zur Verwendung einer before_filter
die alle erforderlichen Formularparameter überprüft und nur dann true zurückgibt, wenn alles in Ordnung ist. Dann wird die my results
Methode wird fortgesetzt, und die Variablen werden einfach zugewiesen, ohne dass eine Überprüfung stattfindet:
@name = params[:name]
In meinem validate_form
Methode, habe ich Codeabschnitte wie den folgenden:
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 frage mich nur, ob ich dies am besten angehe oder ob ich etwas Offensichtliches übersehe, wenn es um die Parametervalidierung geht. Ich befürchte, dass dies immer noch nicht die effizienteste Technik ist, denn ich habe mehrere Blöcke, in denen ich einen Wert zuweisen flash[:error]
, dann auf dieselbe URL umleiten und dann false zurückgeben.
Edit zur Klarstellung: Der Grund, warum ich diese Validierung derzeit nicht in den Modellen vornehme, ist zweierlei:
- 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 eingibt, wird nach der Abmeldung gespeichert. Sie werden direkt bei der Übermittlung verwendet, um die Datenbank zu durchsuchen und einige Daten zu generieren.
- Das Abfrageformular nimmt Daten auf, die sich auf mehrere Modelle beziehen, und es nimmt andere Daten auf, die sich überhaupt nicht auf ein Modell beziehen. So sind z. B. der Diagrammtyp und das Thema, wie oben gezeigt, nicht mit einem Modell verbunden, sondern vermitteln lediglich Informationen darüber, wie der Benutzer seine Ergebnisse anzeigen möchte.
Bearbeiten, um eine verbesserte Technik zu zeigen: Ich verwende jetzt anwendungsspezifische Ausnahmen, dank Jamis Buck's Den richtigen Ausnahmeartikel aufziehen . 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
0 Stimmen
Ich denke, Sie müssen params[:name] und !params[:name].blank? nicht in Ihren Bedingungen verwenden. !params[:name].blank? reicht aus. params[:name] gibt false zurück, wenn er nil ist (es gibt keinen solchen Parameter) und params[:name].blank? gibt true zurück, wenn er nil oder leer ist.
0 Stimmen
Sie erhalten einen NoMethodError. Ich könnte NilClass überschreiben und #blank? hinzufügen, nehme ich an. irb(main):002:0> params = {:a => 1, :b => 2, :c => 3} => {:c=>3, :a=>1, :b=>2} irb(main):003:0> !params[:name].blank? NoMethodError: undefinierte Methode `blank?' für nil:NilClass von (irb):3
0 Stimmen
Hier gibt es kein Ruby, nur Rails. gelöschtes Tag