Rails 3 UJS干客户端+服务器端表单验证

Rails 3 UJS干客户端+服务器端表单验证

问题描述:

使用jQuery进行表单验证与将字段名添加到字段一样简单。使用Rails进行表单验证与将条件添加到控制器(和/或模型)一样简单。Rails 3 UJS干客户端+服务器端表单验证

我认为应该有一种方法来写验证一次,让他们应用客户端和服务器端。我一直都很喜欢编写自己的javascript,但是使用rails3不显眼的UJS在这里可能是非常值得的。

谢谢!

不JS验证,包括一些奇妙的东西阿贾克斯验证唯一性。

https://github.com/bcardarella/client_side_validations

http://railscasts.com/episodes/263-client-side-validations

你应该看看如何创建自己的表单构建器来定制form_for的行为。你可以做一些设置类的属性上定义的验证的名称,并让jQuery自己绑定到相应的类名。让我们从表单构建器的外观开始。

class ValidationFormBuilder < ActionView::Helpers::FormBuilder 
    def text_field(object_name, method, options = {}) 
    options[:class] = object_name.class.validators_on(method).map do |k| 
     # Eg: ActiveModel::Validations::PresenceValidator -> presence 
     k.to_s.slice(/[^:]+Validator$/).chomp('Validator').downcase 
    end.join(' ') 
    super(object_name, method, options) 
    end 
end 

您需要设置form_for才能使用ValidationFormBuilder。

<%= form_for @foo, :builder => ValidationFormBuilder do |f| %> 
    <%= f.text_field :bar %> 
<% end %> 

... becomes something like 

<form action="/foo" method="post"> 
    <input type="text" class="presence" name="foo[bar]" id="foo_bar"> 
</form> 

如果您需要类名更灵活,您可能需要创建映射到所需字符串的散列。

class ValidationFormBuilder < ActionView::Helpers::FormBuilder 
    MAPPINGS = { 
    ActiveModel::Validations::PresenceValidator => 'text' 
    } 

    def text_field(object_name, method, options = {}) 
    options[:class] = object_name.class.validators_on(method).map do |k| 
     MAPPINGS[k] 
    end.join(' ') 
    super(object_name, method, options) 
    end 
end 

你可以看到Rails中验证的完整列表在Rails的源代码activemodel/lib/active_model/validations偷看。我希望这足以让你开始。

可以使用RJS使用服务器端验证(它不依赖于你正在使用UJS与否):

# create.js.haml 
= render :partial => "shared/flash_messages", :locals => { :flash => flash } 

- if @message.errors.any? 
    $('#reply_message').html('#{escape_javascript(render(:partial => "message_form"))}'); 
- else 
    $('ul.data_grid .list').append('#{escape_javascript(render "message", :message => @message)}'); 
    $('#reply_message textarea').val('');