请考虑"入门"指南中的以下代码片段:
module Web::Controllers::Books
class Create
include Web::Action
expose :book
params do
param :book do
param :title, presence: true
param :author, presence: true
end
end
def call(params)
if params.valid?
@book = BookRepository.create(Book.new(params[:book]))
redirect_to '/books'
end
end
end
end
请注意 title
和 author
上的验证,它们位于控制器操作中。 我的问题是:为什么这些验证是在操作参数上而不是在Book
实体上? 也就是说,假设验证在 Book
上,您可以编写如下内容:
def call(params)
book = Book.new(params)
if book.valid?
@book = BookRepository.create(Book.new(params[:book]))
redirect_to '/books'
end
end
并完全摆脱params
块。 这对我来说似乎更自然,并且可以促进在不同操作中更轻松地重用验证。
params
方法是否有我没有看到的优势? 将验证放在Book
实体上是否有缺点?
官方指南中的验证和强制部分解释了为什么你应该对你的请求进行验证,而不是对你的模型进行验证。
总结一下,这里有两个主要原因:
-
从架构的角度来看,永远不应该允许无效的输入进入您的系统,因此最好在控制器级别完全跳过它们,而不是仅仅为了验证而创建模型,因为这是一项非常昂贵的操作。
-
可以有多个请求在同一模型上工作。如果在模型级别进行了验证,则还需要考虑这些请求的不同方案,这同样是控制器的责任,而不是模型的责任。
不过,如果您可以在业务逻辑中使用上述方案,那么这将归结为个人偏好问题。