如何使用户模型验证错误与其对应的表单字段内联显示

时间:2016-04-28 15:28:00

标签: ruby-on-rails ruby-on-rails-4 devise

如何让我的用户模型验证错误与其相应的表单字段(bootstrap和devise)内联显示。因为我在页面顶部出现错误"错误禁止此用户被保存: 全名不能为空 电话号码不能为空 出生日期必须至少为18岁" 我怎样才能在相应的线旁边找到它?

我的用户模型

class User < ActiveRecord::Base

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable,:confirmable

   validates :fullname, presence: true, length: {maximum: 40}  
   validates :phone_number, presence: true, length: {maximum: 12} 
   validates :password,  :format => { :with => /(?=.*\d)(?=.*[a-z])(?=.*[A-Z])/,
   :message => "Password should contain at least 6 characters, one upper case, one lower case and one numeric." }, on: :create
     validates :password,  :format => { :with => /(?=.*\d)(?=.*[a-z])(?=.*[A-Z])/,
   :message => "Password should contain at least 6 characters, one upper case, one lower case and one numeric." }, on: :update, allow_blank: true

   validates_date :date_of_birth, :before => lambda { 18.years.ago },
                               :before_message => "must be at least 18 years old"

   has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100#" }, :default_url => "/images/missing.png"
  validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/


end

我的html视图文件

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
      <%= devise_error_messages! %>

      </br>
      <div class="col-md-6 col-md-offset-3 text-left">
     <div class="row">
          <label class="col-xs-4" for="fullname">Fullname</label>
              <div class="col-xs-8">    
                  <%= f.text_field :fullname, :class => 'form-control', :placeholder => 'Full Name', autofocus: true %>
              </div></br></br></br>
     </div>
     <div class="row">
        <label class="col-xs-4" for="Email1">Email</label>
            <div class="col-xs-8">
              <%= f.email_field :email, :class => 'form-control', :placeholder => 'Email' %>
            </div>
    </div></br>
    <div class="row">
                <label class="col-xs-4" for="phone_number">Phone Number</label>
                  <div class="col-xs-8">
                    <%= f.text_field :phone_number, :class => 'form-control', :placeholder => 'Phone Number', autofocus: true %>
                  </div>
            </div></br> 
      <div class="row">
                <label class="col-xs-4" for="date_of_birth">Date of Birth</label>
                  <div class="col-xs-8">
                  <%= f.date_select :date_of_birth, order: [:day, :month, :year], :start_year=>1910 %>
                  </div>
              </div></br>


       <div class="row">
           <% if @validatable %>
                      <em>(<%= @minimum_password_length %> characters minimum)</em>
                  <% end %>
              <label class="col-xs-4" for="password">Password</label>
                <div class="col-xs-8">                 
                  <%= f.password_field :password, :class => 'form-control', :placeholder => 'Password',  autocomplete: "off" %>
                </div>
      </div>

      <div class="actions">
        <%= f.submit "Sign up", :class => "btn btn-primary" %>
      </div>
    <% end %>

1 个答案:

答案 0 :(得分:1)

您可能希望首先看一下这样做的simple_form gem,并为Bootstrap准备好包装器。

如果由于某种原因仍然想要自己滚动,则需要检查表单构建器包装的对象是否存在与该字段对应的错误:

<div class="row">
  <% if f.object.errors[:full_name] %>
    <ul>
      <% f.object.errors[:full_name].each do |msg| %>
      <li><%= msg %></li>
      <% end %>
    </ul>
  <% end %>
</div>

当然,为每一行执行此操作非常繁琐,因此您可能需要声明一个帮助器方法或创建自己的表单构建器类。

class MyFormBuilder < ActionView::Helpers::FormBuilder
  def row_for_field(field, options = {})
    errors = @object.errors[field]
    row_classes = ['row']
    row_classes << 'invalid' if errors.any?
    @tempate.content_tag(:div, class: row_classes) do
      if errors.any?
        @tempate.content_tag(:ul, class: 'errors') do
          errors.each do |msg|
            @tempate.content_tag(:li, msg)
          end
        end
      end
      yield
    end
  end
end

然后你会这样做:

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)), form_builder: MyFormBuilder do |f| %>
  <%= f.row_for_field :fullname do  %>
    <%= f.text_field :fullname %> 
  <% end %>
<% end %>

但话又说回来 - 使用simple_form。使用bootstrap的全部理由是将时间花在除前端之外的其他事情上。