【发布时间】:2014-12-20 09:23:49
【问题描述】:
在处理 Form 对象和常规 Rails 模型时,基本的验证器在哪里?
遵循 Rails 中将表单与持久层分离的概念。我已经设置了一个表单对象Cage,它一起创建了两个对象......比如说Animal 和Plant。
以下来自http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/ 或https://github.com/solnic/virtus 或https://github.com/makandra/active_type 的表单对象示例,每个都表明表单对象本身具有验证...没问题...部分好处包括能够在一个更具上下文意识的方式。
问题:
class Animal < ActiveRecord::Base
validates :color, presence: true
validate :only_one_brown
private
def only_one_brown
if some_complex_thing
errors.add(:color, 'can not have more than one brown animal.')
end
end
end
class Plant < ActiveRecord::Base
validates :color, presence: true
end
class Cage
include Virtus.model # or ActiveType or whatever
include ActiveModel::Validations
attribute :bird_color, String
attribute :plant_color, String
validates :bird_color, presence: true
validates :plant_color, presence: true
def save
if valid?
animal.save!
plant.save!
true
else
false
end
end
def animal
@animal ||= Animal.new(color: bird_color)
end
def plant
@plant ||= Plant.new(color: plant_color)
end
end
我如何验证动物的“只有一种棕色”规则没有:
- 重复太多。
- 大量代码使 Cage 仍然像 AR 模型一样工作
如果我们不复制验证码,当“只有一个棕色”为假的时候,Cage 就没有错误了……我们会提出,这需要控制器去捕捉和处理,也就是不好。
如果我们确实复制了代码,并且如果有多个自定义验证,我们将复制大量代码,并且处理 Animal 的每个其他表单对象现在都需要重复验证。
如果我们将验证代码从 Animal 完全移到 Cage 中,类似的问题:所有与 Animal 交互的对象都需要知道“只有一个棕色”规则,这只是复制验证器并开辟了一种容易忘记的方法在某处强制执行。
如果我们将 Animal 的错误数组向上移动到 Cage 的,Animal 的错误在 :color,这对 Cage 来说是模棱两可的,并且在客户端从未发送过的属性名称上显示错误。如果要将 Animal 的错误键映射到Cage 的,现在你需要为每个 Form Object 保留一张图,感觉很臭。
有什么好的模式或方法来处理这种情况吗?当你开始使用表单对象时,我觉得这很常见,但所有示例都很琐碎。
提前致谢!
【问题讨论】:
-
您找到解决方案了吗?我正在使用 jquery 验证来对表单输入进行客户端验证,然后仍然只在 ActiveRecord 模型中进行验证,但是如果它们不允许在服务器端使用 js,我仍然想要一些东西。
标签: ruby-on-rails forms validation oop activerecord