Lub*_*rko 9 arrays validation ruby-on-rails jsonb
如何使用Rails验证对象数组中的每个对象?
我正在我们的Rails应用程序中构建用户配置文件表单.在用户模型内部,我们有基本的字符串属性,但也有一些jsonb字段.JSONb字段默认为[]因为我们想要在该属性中存储对象数组.以下是简化用户模型属性的示例:
name: stringemail: stringeducation: jsonb, default: []教育是一系列对象,例如:
[{
school: 'Harvard university',
degree: 'Computer Science',
from_date: 'Tue, 11 Jul 2017 16:22:12 +0200`,
to_date: 'Tue, 11 Jul 2017 16:22:12 +0200'
},{
school: 'High school',
degree: 'Whatever',
from_date: 'Tue, 11 Jul 2017 16:22:12 +0200`,
to_date: 'Tue, 11 Jul 2017 16:22:12 +0200'
}]
Run Code Online (Sandbox Code Playgroud)
用户应该能够单击Add school按钮,通过jquery添加更多字段.那个jquery部分对于这个问题并不重要 - 可能只是解释了为什么我们使用了一个对象数组.
你如何验证教育数组中的每个项目,所以我可以用红色标记包含验证错误的文本字段?我被告知使用FormObject模式可能会有所帮助.我也尝试编写继承自ActiveModel::Validator类的自定义验证器,但主要问题仍然在于,我正在处理数组,而不是实际对象.
感谢任何建设性的帮助.
Mát*_*osi 10
您可以通过ActiveModel为它们引入非数据库支持的模型类,将教育记录视为Rails模型层中的一等公民:
class Education
include ActiveModel::Model
attr_accessor :school, :degree, :from_date, :to_date
validates :school, presence: true
validates :degree, presence: true
def initialize(**attrs)
attrs.each do |attr, value|
send("#{attr}=", value)
end
end
def attributes
[:school, :degree, :from_date, :to_date].inject({}) do |hash, attr|
hash[attr] = send(attr)
hash
end
end
class ArraySerializer
class << self
def load(arr)
arr.map do |item|
Education.new(item)
end
end
def dump(arr)
arr.map(&:attributes)
end
end
end
end
Run Code Online (Sandbox Code Playgroud)
然后,您可以透明地序列化和反序列化模型中的education数组User:
class User
# ...
serialize :education, Education::ArraySerializer
# ...
end
Run Code Online (Sandbox Code Playgroud)
此解决方案应允许您Education使用内置Rails验证器验证对象的各个属性 ,将它们嵌套在嵌套形式中,等等.
重要提示:我在没有测试的情况下编写了上面的代码,因此可能需要进行一些修改.