Allow Lotus::Validations to coerce members of an Array


#1

I would like to be able to do attribute :people, type: Array[Person] and have each member of the array coerced to a Person.

Here is a fuller example:

    class Person
      attr_reader :name
    
      def initalize(attributes); 
        @name = attributes.fetch(:name)
      end
    end
    
    class MyForm
      include Lotus::Validations
    
      attribute :people, type: Array[Person]
    end
    
    form = MyForm.new(people: [{ name: 'Kris', name: 'Lindsey' }]
    form.people.first.name # => 'Kris'
    form.people.all? { |p| p.is_a?(Person) } # => true

I hacked together a very simple solution here: https://github.com/lotus/validations/pull/68

The above might be enough for now (I’d think a bit harder and add tests) or you might already have some thoughts on this already.

Another similar use case might be a Hash which has cocershed key/values, so you might want:

attribute :address, Hash(Symbol => String)

However I’m not sure this would be typical since all keys/values have be to of the same type, which would only work for simple cases and more likely you would use an object so attribute :address, Address.

Another approach might be to add a collection key to attribute so something like attribute :people, type: Person, collection: true. But I don’t see this as any better, just a different DSL.


#2

Sounds a bit like nested attributes in Rails?


#3

Yeah, kinda.

I avoid nested_attributes in ActiveRecord, never really had much success with them. I prefer, in Rails, having a form object which has “sub forms” (Array of ActiveModel). Then manually populating models using the form data within a service-like object. That way I can map between form and models as I please. I also do not need to mess about with any of that strong parameters / attr_accessable crazyness.


#4

Yes, i also try to avoid nested attributes. Just never felt right, despite the simple way complex form could be built.


#5

I like the idea, you can handle nested params with custom classes, a more OOP approach. could you update your PR with tests? so we can see it with working code


#6

@AlfonsoUceda When you say custom class do you mean in public API, such as validates :people, type: People or in the implementation?

Sure, I can update the PR :thumbsup:


#7

@krisleech a custom class created by you