Rails表单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方法继续,并且变量只是被分配为flat-out,不涉及任何检查:

 @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 

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

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

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

编辑以显示改进的技术:由于Jamis Buck的Raising the Right Exception文章 ,我现在使用特定于应用程序的exception 。 例如:

 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 

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

 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 

看起来你正在控制器中进行validation,尝试将它放在模型中,它更适合这种事情。

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

模型

 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 

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

调节器

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

一个你叫。有效? 在模型上的方法,错误将填充在@person对象中。 因此,

视图

 <%if @person.errors.any? %> <%@person.errors.messages.each do|msg| %> 
<%=msg[0][1]%>
<%end%> <%end%>