使用Rails完全自定义validation错误消息
使用Rails我试图得到一个错误消息,如“歌曲字段不能为空”保存。 执行以下操作:
validates_presence_of :song_rep_xyz, :message => "can't be empty"
…只显示“歌词XYW不能空”,这是不好的,因为该字段的标题不是用户友好的。 我怎样才能改变领域本身的标题? 我可以更改数据库中字段的实际名称,但是我有多个“歌曲”字段,我需要具有特定的字段名称。
我不想绕过铁轨的validation过程,我觉得应该有办法解决这个问题。
现在,可接受的设置人性化名称和自定义错误消息的方法是使用语言环境 。
# config/locales/en.yml en: activerecord: attributes: user: email: "E-mail address" errors: models: user: attributes: email: blank: "is required"
现在,“email”属性的人性化名称和存在validation消息已被更改。
可以为特定模型+属性,模型,属性或全局设置validation消息。
尝试这个。
class User < ActiveRecord::Base validate do |user| user.errors.add_to_base("Country can't be blank") if user.country_iso.blank? end end
我在这里find了 。
这是另一种方式来做到这一点。 你所做的是在模型类上定义一个human_attribute_name方法。 该方法将字段名称作为string传递,并返回用于validation消息的string。
class User < ActiveRecord::Base HUMANIZED_ATTRIBUTES = { :email => "E-mail address" } def self.human_attribute_name(attr) HUMANIZED_ATTRIBUTES[attr.to_sym] || super end end
上面的代码是从这里
在你的模型中:
validates_presence_of :address1, :message => "Put some address please"
在你看来
<% m.errors.each do |attr,msg| %> <%=msg%> <% end %>
如果你这样做
<%=attr %> <%=msg %>
您会收到此属性名称的错误消息
address1 Put some address please
如果你想获得一个属性的错误信息
<%= @model.errors[:address1] %>
是的,没有插件就有办法做到这一点! 但是我不像使用上面提到的插件那样干净优雅。 这里是。
假设它是Rails 3(我不知道在以前的版本中是否有所不同),
保持你的模型:
validates_presence_of :song_rep_xyz, :message => "can't be empty"
并且认为,而不是离开
@instance.errors.full_messages
就像我们使用脚手架发电机时一样,把:
@instance.errors.first[1]
你将得到你在模型中指定的消息,没有属性名称。
说明:
#returns an hash of messages, one element foreach field error, in this particular case would be just one element in the hash: @instance.errors # => {:song_rep_xyz=>"can't be empty"} #this returns the first element of the hash as an array like [:key,"value"] @instance.errors.first # => [:song_rep_xyz, "can't be empty"] #by doing the following, you are telleing ruby to take just the second element of that array, wich is the message. @instance.errors.first[1]
到目前为止,我们只是只显示一条消息,总是针对第一个错误。 如果你想显示所有的错误,你可以在哈希中循环显示值。
希望有所帮助。
Rails3完全本地化的消息代码:
在模型user.rb中定义validation
validates :email, :presence => true
在config / locales / en.yml中
en: activerecord: models: user: "Customer" attributes: user: email: "Email address" errors: models: user: attributes: email: blank: "cannot be empty"
我build议安装David Easley最初编写的custom_error_message gem (或作为一个插件 )
它可以让你做这样的东西:
validates_presence_of :non_friendly_field_name, :message => "^Friendly field name is blank"
在自定义validation方法中使用:
errors.add(:base, "Custom error message")
因为add_to_base已被弃用。
errors.add_to_base("Custom error message")
相关的接受答案和列表中的另一个答案 :
我确认nanamkim的custom-err-msg的分支可以在Rails 5和区域设置中使用。
您只需要用插入符号启动语言环境消息,并且不应该在消息中显示属性名称。
模型定义为:
class Item < ApplicationRecord validates :name, presence: true end
使用以下en.yml
:
en: activerecord: errors: models: item: attributes: name: blank: "^You can't create an item without a name."
item.errors.full_messages
将显示:
You can't create an item without a name
而不是通常的Name You can't create an item without a name
正常的做法就是这样做:
validates_presence_of :email, :message => "Email is required."
但是像这样显示它
<% if @user.errors.any? %> <% @user.errors.messages.each do |message| %> <div class="message"><%= message.last.last.html_safe %></div> <% end %> <% end %>
返回
"Email is required."
本地化方法绝对是这样做的“正确”方法,但是如果您正在做一个非全局项目,并希望快速进行 – 这肯定比文件跳转更容易。
我喜欢将字段名称放在除string开头以外的地方:
validates_uniqueness_of :email, :message => "There is already an account with that email."
这是另一种方式:
如果你使用这个模板:
<% if @thing.errors.any? %> <ul> <% @thing.errors.full_messages.each do |message| %> <li><%= message %></li> <% end %> </ul> <% end %>
你可以写下你自己的自定义消息:
class Thing < ActiveRecord::Base validate :custom_validation_method_with_message def custom_validation_method_with_message if some_model_attribute.blank? errors.add(:_, "My custom message") end end
这样,由于下划线,完整的消息变成了“我的自定义消息”,但是一开始的额外空间是不明显的。 如果你真的不想在开始时多余的空间,只需添加.lstrip
方法。
<% if @thing.errors.any? %> <ul> <% @thing.errors.full_messages.each do |message| %> <li><%= message.lstrip %></li> <% end %> </ul> <% end %>
String.lstrip方法将摆脱由':_'创build的额外空间,并保持其他任何错误消息不变。
或者甚至更好,将自定义消息的第一个单词用作关键字:
def custom_validation_method_with_message if some_model_attribute.blank? errors.add(:my, "custom message") end end
现在完整的消息将是“我的自定义消息”,没有额外的空间。
如果您希望完整的信息以大写字母“URL不能为空”开头,则无法完成。 请尝试添加一些其他字作为关键字:
def custom_validation_method_with_message if some_model_attribute.blank? errors.add(:the, "URL can't be blank") end end
现在完整的信息将是“URL不能为空”
一个解决scheme可能是更改国际化的默认错误格式:
en: errors: format: "%{message}"
默认format: %{attribute} %{message}
如果你想把它们列在一个不错的列表中,但是不使用非人性化的名字,你可以这样做…
object.errors.each do |attr,message| puts "<li>"+message+"</li>" end
在你看来
object.errors.each do |attr,msg| if msg.is_a? String if attr == :base content_tag :li, msg elsif msg[0] == "^" content_tag :li, msg[1..-1] else content_tag :li, "#{object.class.human_attribute_name(attr)} #{msg}" end end end
当你想覆盖没有属性名称的错误消息时,只需在^之前加上消息就好:
validates :last_name, uniqueness: { scope: [:first_name, :course_id, :user_id], case_sensitive: false, message: "^This student has already been registered." }
我试过下面,为我工作:)
1 job.rb
class Job < ApplicationRecord validates :description, presence: true validates :title, :presence => true, :length => { :minimum => 5, :message => "Must be at least 5 characters"} end
2个jobs_controller.rb
def create @job = Job.create(job_params) if @job.valid? redirect_to jobs_path else render new_job_path end end
3 _form.html.erb
<%= form_for @job do |f| %> <% if @job.errors.any? %> <h2>Errors</h2> <ul> <% @job.errors.full_messages.each do |message|%> <li><%= message %></li> <% end %> </ul> <% end %> <div> <%= f.label :title %> <%= f.text_field :title %> </div> <div> <%= f.label :description %> <%= f.text_area :description, size: '60x6' %> </div> <div> <%= f.submit %> </div> <% end %>
这里是我的代码,可以帮助你,如果你仍然需要它:我的模型:
validates :director, acceptance: {message: "^Please confirm that you are a director of the company."}, on: :create, if: :is_director?
然后我创build了一个帮手来显示消息:
module ErrorHelper def error_messages! return "" unless error_messages? messages = resource.errors.full_messages.map { |msg| if msg.present? && !msg.index("^").nil? content_tag(:p, msg.slice((msg.index("^")+1)..-1)) else content_tag(:p, msg) end }.join html = <<-HTML <div class="general-error alert show"> #{messages} </div> HTML html.html_safe end def error_messages? !resource.errors.empty? end end