我目前有一个模型,其中我想使用点表示法来添加错误,以更具体地说明哈希属性中的哪个键有错误:
class MyFormObject
include ActiveModel::Validations
include ActiveModel::AttributeAssignment
attr_accessor :name, :metadata
validates :name, presence: true
validate address_is_present_in_metadata
def initialize(**attributes)
assign_attributes(attributes)
end
def validate_address_is_present_in_metadata
errors.add("metadata.address", "can't be blank") if metadata[:address].blank?
end
end
这样可行,但如果我决定使用符号而不是如下消息:
errors.add("metadata.address", :blank) if metadata[:address].blank?
然后Rails抱怨,因为metadata.address
不是属性。抛出错误的ActiveModel::Errors
代码检查属性是否为:base
,如果属性为value = attribute != :base ? @base.send(:read_attribute_for_validation, attribute) : nil)
,则会尝试从模型中读取属性以生成错误消息...并且繁荣。
read_attribute_for_validation
作为解决方法,我决定覆盖def read_attribute_for_validation(key)
key_str = key.to_s
return public_send(key) unless key_str.include?(".")
key_path = key_str.split(".").map(&:to_sym)
public_send(key_path.first).dig(*key_path[1, key_path.size])
end
。
{{1}}
是否有更好/支持的方法来验证我不知道的哈希中的嵌套密钥?
答案 0 :(得分:0)
默认情况下,这被认为是以。之后命名的实例 属性。如果需要,可以在子类中重写此方法 以不同方式检索给定属性的值。
所以你的策略似乎是有效的。
但有些建议:
public_send
代替send
Array#[a,b]
从b
开始采用a
个元素,因此b
不应大于Array#size
。你可以使用array.drop(1)
。您可能一直在寻找array[a..b]
,其中包含索引a
和b
之间的元素。