Consider this snippet from 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
Notice the validations on title
and author
, which live here in the controller action. My question is: Why are these validations on the action params rather than on the Book
entity? That is, assuming the validations were on Book
, you could write something like:
def call(params)
book = Book.new(params)
if book.valid?
@book = BookRepository.create(Book.new(params[:book]))
redirect_to '/books'
end
end
and just get rid of the params
block altogether. This seems more natural to me, and would promote easier re-use of the validations across different actions.
Are there advantages to the params
method that I'm not seeing? Are there drawbacks to placing the validations on the Book
entity?
The Validations & Coercion section in the official guide explains why you should have validations on your requests, and not on your models.
To summarize it, here are the two major reasons:
From an architectural point of view, invalid inputs should never be allowed to enter your system so it is better to completely skip them at the controller level rather than creating a model just for validation as this is a pretty expensive operation.
It is possible to have multiple requests that work on the same model. If you have validations at the model level, you will also need to take into account the different scenarios for these requests which again is the controller's responsibility, not the model's.
Still, if you can do with the above scenarios in your business logic, it would come down to the matter of personal preference.