Implementing Form Objects in Hanami

483 Views Asked by At

In Uncle Bob's clean architecture, which Hanami is inspired by, Form Objects guard the boundary between Interactors and our delivery mechanism (typically an http endpoint).

In the Hanami docs, bounary guarding is done using params blocks in Actions (see here). This seems to couple validation to the http delivery mechanism. It seems more natural to me that Form Objects (or params black which accomplish the same thing) would live in delivery-mechanism-agnostic Interactors.

Unfortunately, I cannot figure out if Hanami supports such a design. I found a similar question on the Hanami forum, but it has no answer.

To clarify, below is a snippet of code demonstrating the kind of thing I want to do, but using Virtus and ActiveModel::Validations rather than Hanami facilities. For those familiar with Trailblazer, its contract block within its operations (its term for Interactor) is another example.

Finally, am I misunderstanding something about the intended use of Hanami? Hanami supports Interactors, so it seems like this should be possible...

require 'hanami/model'
require 'active_model'
require 'virtus'

class PersonForm
  include Virtus.model
  include ActiveModel::Validations

  attribute :name, String
  attribute :age, Integer

  validates :name, :age, presence: true

  def each
    attributes.each {|a| yield a}
  end
end

class Person
  include Hanami::Entity
  attributes :name, :age
end

# Code like this would then live inside of an Interactor, which
# can accept a params hash.

jonah_form = PersonForm.new({name: 'Jonah', age: '99'})
jonah = Person.new(jonah_form) if jonah_form.valid?
p jonah #=> <Person:0x007fbdde1edcc0 @id=nil @name="Jonah" @age=99>
# do stuff with our jonah entity
1

There are 1 best solutions below

0
On

sorry for missing this question.

The params act as validator to save developers to create and instantiate another class. In Ruby Community this is a problem.

DSL to the rescue for this compromise.

If you prefer to have a concrete form object, instead of using Virtus and ActiveModel, you can just include Hanami::Validations and have the same behavior.