Rails表单验证

时间:2008-12-11 22:05:00

标签: ruby-on-rails forms validation

我有一个Rails应用程序,允许用户通过填写​​一个扩展的表单来构建数据库查询。我想知道在Rails中检查表单参数的最佳实践。以前,我使用results方法(表单提交的方法)执行以下操作:

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

但是对于几个表格领域,看到每个表格都重复这一点令人厌烦。我不能只是将它们全部放在某个循环中以检查每个字段,因为字段设置不同:

  • 一键:params[:name]
  • 一个键和一个子键:params[:image][:font_size]
  • 只希望在设置了另一个字段时填写一些表单字段

等。这也是重复的,因为我为每个缺失/无效参数设置flash[:error],并为每个参数重定向到相同的URL。我切换到使用before_filter来检查所有必要的表单参数,只有在一切正常时才返回true。然后我的results方法继续进行,变量只是被分配出来,没有检查:

@name = params[:name]

在我的validate_form方法中,我有以下代码部分:

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

我只是想知道我是否以最好的方式解决这个问题,或者在参数验证方面我是否遗漏了一些明显的东西。我担心这仍然不是最有效的技术,因为我有几个块,我将值分配给flash[:error],然后重定向到相同的URL,然后返回false。

编辑以澄清:我目前没有在模型中进行此验证的原因有两个:

  • 我不是要从用户那里收集数据,以便在数据库中创建或更新一行。用户提交的数据在注销后都不会保存。当它们提交它以搜索数据库并生成一些东西时,它们都被正确使用。
  • 查询表单接收与多个模型有关的数据,并且它接收与模型完全无关的其他数据。例如。如上所示的图表类型和主题不会连接到任何模型,它们只传达有关用户如何显示其结果的信息。

编辑以显示改进的技术:我现在使用特定于应用程序的异常,感谢Jamis Buck的Raising the Right Exception article。例如:

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

4 个答案:

答案 0 :(得分:25)

您可以尝试使用active_form( http://github.com/cs/active_form/tree/master/lib/active_form.rb) - 只需要ActiveRecord减去数据库内容。通过这种方式,您可以使用所有AR的验证内容,并像对待任何其他模型一样对待您的表单。

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

答案 1 :(得分:6)

看起来你正在控制器中进行验证,试着把它放在模型中,它更适合那种东西。

答案 2 :(得分:2)

如果你今天要再次解决这个问题,你可以为查询参数集创建一个模型并使用Rails内置的验证,Rails 3使用ActiveModel :: Validations更容易看到this post

答案 3 :(得分:0)

型号

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

请注意,您不一定需要保存/保留模型以进行验证。

控制器

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

您叫一个有效的吗?方法上的错误,错误将填充在@person对象内。因此,

查看

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