选择验证的位置?

时间:2016-01-30 14:03:16

标签: validation hanami

请考虑the "Getting Started" guide中的此片段:

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 个答案:

答案 0 :(得分:3)

官方指南中的Validations & Coercion部分解释了为什么您应该对您的请求进行验证,而不是对您的模型进行验证。

总结一下,以下是两个主要原因:

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

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

  3. 尽管如此,如果您可以在业务逻辑中使用上述方案,那将归结为个人偏好。