title: Rails form validation
body: <p>I have a Rails app that lets a user construct a database query by filling out an extensive form.  I wondered the best practice for checking form parameters in Rails.  Previously, I have had my <code>results</code> method (the one to which the form submits) do the following:</p>
  
  <pre><code>if params[:name] &amp;&amp; !params[:name].blank?
    @name = params[:name]
  else
    flash[:error] = 'You must give a name'
    redirect_to :action =&gt; 'index'
    return
  end
  </code></pre>
  
  <p>But for several form fields, seeing this repeated for each one got tiresome.  I couldn't just stick them all in some loop to check for each field, because the fields are set up differently:</p>
  
  <ul>
  <li>a single key:  <code>params[:name]</code></li>
  <li>a key and a sub-key:  <code>params[:image][:font_size]</code></li>
  <li>only expect some form fields to be filled out if another field was set</li>
  </ul>
  
  <p>Etc.  This was also repetitive, because I was setting <code>flash[:error]</code> for each missing/invalid parameter, and redirecting to the same URL for each one.  I switched to using a <code>before_filter</code> that checks for all necessary form parameters and only returns true if everything's okay.  Then the my <code>results</code> method continues, and variables are just assigned flat-out, with no checking involved:</p>
  
  <pre><code>@name = params[:name]
  </code></pre>
  
  <p>In my <code>validate_form</code> method, I have sections of code like the following:</p>
  
  <pre><code>if (
    params[:analysis_type][:to_s] == 'development' ||
    params[:results_to_generate].include?('graph')
  )
    {:graph_type =&gt; :to_s, :graph_width =&gt; :to_s,
     :theme =&gt; :to_s}.each do |key, sub_key|
      unless params[key] &amp;&amp; params[key][sub_key]
        flash[:error] = "Cannot leave '#{Inflector.humanize(key)}' blank"
        redirect_to(url)
        return false
      end
    end
  end
  </code></pre>
  
  <p>I was just wondering if I'm going about this in the best way, or if I'm missing something obvious when it comes to parameter validation.  I worry this is still not the most efficient technique, because I have several blocks where I assign a value to <code>flash[:error]</code>, then redirect to the same URL, then return false.</p>
  
  <p><em>Edit to clarify:</em>  The reason I don't have this validation in model(s) currently is for two reasons:</p>
  
  <ul>
  <li>I'm not trying to gather data from the user in order to create or update a row in the database.  None of the data the user submits is saved after they log out.  It's all used right when they submit it to search the database and generate some stuff.</li>
  <li>The query form takes in data pertaining to several models, and it takes in other data that doesn't pertain to a model at all.  E.g. graph type and theme as shown above do not connect to any model, they just convey information about how the user wants to display his results.</li>
  </ul>
  
  <p><em>Edit to show improved technique:</em>  I make use of application-specific exceptions now, thanks to Jamis Buck's <a href="http://weblog.jamisbuck.org/2007/3/7/raising-the-right-exception" rel="noreferrer">Raising the Right Exception article</a>.  For example:</p>
  
  <pre><code>def results
    if params[:name] &amp;&amp; !params[:name].blank?
      @name = params[:name]
    else
      raise MyApp::MissingFieldError
    end
  
    if params[:age] &amp;&amp; !params[:age].blank? &amp;&amp; params[:age].numeric?
      @age = params[:age].to_i
    else
      raise MyApp::MissingFieldError
    end
  rescue MyApp::MissingFieldError =&gt; err
    flash[:error] = "Invalid form submission: #{err.clean_message}"
    redirect_to :action =&gt; 'index'
  end
  </code></pre>