选择在哪里进行验证



请考虑"入门"指南中的以下代码片段:

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

请注意 titleauthor 上的验证,它们位于控制器操作中。 我的问题是:为什么这些验证是在操作参数上而不是在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实体上是否有缺点?

官方指南中的验证和强制部分解释了为什么你应该对你的请求进行验证,而不是对你的模型进行验证。

总结一下,这里有两个主要原因:

  1. 从架构的角度来看,永远不应该允许无效的输入进入您的系统,因此最好在控制器级别完全跳过它们,而不是仅仅为了验证而创建模型,因为这是一项非常昂贵的操作。

  2. 可以有多个请求在同一模型上工作。如果在模型级别进行了验证,则还需要考虑这些请求的不同方案,这同样是控制器的责任,而不是模型的责任。

不过,如果您可以在业务逻辑中使用上述方案,那么这将归结为个人偏好问题。

最新更新