Ruby-on-rails Rails 表单验证
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/361161/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Rails form validation
提问by Sarah Vessels
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 resultsmethod (the one to which the form submits) do the following:
我有一个 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
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:
但是对于多个表单字段,看到每个字段都重复出现这种情况令人厌烦。我不能只是将它们全部放在某个循环中来检查每个字段,因为这些字段的设置不同:
- a single key:
params[:name] - a key and a sub-key:
params[:image][:font_size] - only expect some form fields to be filled out if another field was set
- 一个键:
params[:name] - 一个键和一个子键:
params[:image][:font_size] - 如果设置了另一个字段,只希望填写一些表单字段
Etc. This was also repetitive, because I was setting flash[:error]for each missing/invalid parameter, and redirecting to the same URL for each one. I switched to using a before_filterthat checks for all necessary form parameters and only returns true if everything's okay. Then the my resultsmethod continues, and variables are just assigned flat-out, with no checking involved:
等等。这也是重复的,因为我正在flash[:error]为每个丢失/无效的参数设置,并为每个参数重定向到相同的 URL。我改用 abefore_filter来检查所有必要的表单参数,只有在一切正常时才返回 true。然后我的results方法继续,变量被完全分配,不涉及检查:
@name = params[:name]
In my validate_formmethod, I have sections of code like the following:
在我的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
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 flash[:error], then redirect to the same URL, then return false.
我只是想知道我是否以最好的方式来解决这个问题,或者在参数验证方面我是否遗漏了一些明显的东西。我担心这仍然不是最有效的技术,因为我有几个块,我为 分配了一个值flash[:error],然后重定向到相同的 URL,然后返回 false。
Edit to clarify:The reason I don't have this validation in model(s) currently is for two reasons:
编辑以澄清:我目前在模型中没有此验证的原因有两个:
- 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.
- 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.
- 我不是为了在数据库中创建或更新行而试图从用户那里收集数据。退出后,用户提交的任何数据都不会保存。当他们提交它以搜索数据库并生成一些东西时,这一切都是正确的。
- 查询表单接收与多个模型相关的数据,并接收根本不与模型相关的其他数据。例如,上面显示的图形类型和主题不连接到任何模型,它们只是传达有关用户希望如何显示其结果的信息。
Edit to show improved technique:I make use of application-specific exceptions now, thanks to Jamis Buck's Raising the Right Exception article. For example:
编辑以显示改进的技术:感谢 Jamis Buck 的Raising the Right 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
回答by
You could try active_form (http://github.com/cs/active_form/tree/master/lib/active_form.rb) - just ActiveRecord minus the database stuff. This way you can use all of AR's validation stuff and treat your form like you would any other model.
你可以试试 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
回答by Jamal Hansen
Looks like you are doing the validation in the controller, try putting it in the model, it's better suited to that sort of thing.
看起来您正在控制器中进行验证,尝试将其放入模型中,它更适合那种事情。
回答by weston
If you were to tackle the problem again today, you could create a model for the query parameter set and use Rails' built in validations, Rails 3 makes this a lot easier with ActiveModel::Validations see this post.
如果您今天要再次解决这个问题,您可以为查询参数集创建一个模型并使用 Rails 的内置验证,Rails 3 使用 ActiveModel::Validations 使这变得更加容易,请参阅这篇文章。
回答by zawhtut
Model
模型
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
Note that you don't necessarily need to save/persist the model to validate.
请注意,您不一定需要保存/持久化模型以进行验证。
Controller
控制器
@person.name= params["name"]
@person.email= params["email"]
@person.valid?
One you called .valid? method on the model, the errors will be populated inside @person object. Hence,
你称之为.valid?模型上的方法,错误将填充在@person 对象中。因此,
View
看法
<%if @person.errors.any? %>
<%@person.errors.messages.each do|msg| %>
<div class="alert alert-danger">
<%=msg[0][1]%>
</div>
<%end%>
<%end%>

