我的应用程序中有一些belongs_to关联,其中一些是可选的(即关联可能是nil),一些是必需的(关联必须是有效的父记录。
我最初的方法是使用我自己的验证方法验证给定的id(这里是强制关联)
belongs_to :category
validates :category_id,
presence: true
validate given_category_exists
def given_category_exists
if category_id.present?
errors.add( :category_id, 'must be present' ) \
Category.exists?( category_id )
end
end
然后我发现Rails会为我做这个,如果我会在关联上使用状态检查,那么我可以省略我自己的验证方法:
belongs_to :category
validates :category,
presence: true
但是现在,生成的错误消息只会说明:Category can't be blank
。这里的问题是:(1)我能提供更有用的信息吗? (2)如何为属性插入自己的翻译? Category
是从validates方法生成的默认标签,can't be blank
是以下内容的默认错误文本:
另一个问题是:表单中的相关输入字段未标记为“field_with_errors”,因为此字段使用属性的名称标识,而不是关联名称。
使用标准的处理方式,我会在I18n翻译文件中添加一个额外的属性作为关联category
的名称,并添加标准消息的替换:
en:
activerecord:
models:
attributes:
my_model:
category_id: 'This Category'
category: 'This Category'
errors:
models:
my_model:
attributes:
category:
blank: 'must be specified.'
很多行都可能出错。而且我不喜欢添加表面属性的想法,这些属性实际上不是属性,而是关联的名称。
有更简单的方法吗?
答案 0 :(得分:2)
帖子很旧但我仍然会写我的解决方案。 Rails 5有一个required
错误密钥,您可以使用它来覆盖那些属于关联的验证消息:
class MyModel < ApplicationRecord
belongs_to :category
end
请注意,您实际上并不需要在此处指定验证规则(validates :category, presence: true
)。要自定义您的消息,只需使用required
键:
en:
activerecord:
errors:
models:
my_model:
attributes:
category:
required: "The category must be specified."
答案 1 :(得分:-1)
我的解决方案覆盖了errors.add方法,该方法被证明非常简单且非常有效。 Rails关联包含所需的所有信息,我只需要在那里找到它。我甚至可以使用对关联的class_name的引用来格式化我自己的错误消息!现在我的错误消息如下所示:
This Category must be one of the existing Categories.
添加新的标准错误消息:
en:
messages:
blank_assoc: 'must be one of the existing %{assoc}'
将以下文件添加到app / models / concerns文件夹
module ActiveModelErrorsAdd
def add( attribute, message = :invalid, options = {})
if attribute != :base # that's the only other attribute I am using
all_assocs = @base.class.reflect_on_all_associations( :belongs_to )
this_assoc = nil
all_assocs.each do |a|
if a.name == attribute
this_assoc = a
break
end
end
end
if this_assoc.nil? # just use the standard
super
elsif message == :blank # replace with my own
super( this_assoc.foreign_key, :blank_assoc,
options.merge( assoc: this_assoc.klass.model_name.human ))
else # use standard message but refer to the foreign_key!
super( this_assoc.foreign_key, message, options )
end
end
end
class ActiveModel::Errors
prepend ActiveModelErrorsAdd
end
将此文件包含在需要的模型中,您将拥有所有belongs_to关联的错误消息。享受!
注意:此方法还会将正确的输入字段标记为“field_with_errors” - 即使它具有非标准外键!