# How to handle a dry struct with array attribute with multiple members type

**URL:** https://discourse.dry-rb.org/t/how-to-handle-a-dry-struct-with-array-attribute-with-multiple-members-type/132
**Category:** dry-types
**Created:** [October 13, 2016, 4:15am UTC](https://discourse.dry-rb.org/t/how-to-handle-a-dry-struct-with-array-attribute-with-multiple-members-type/132 "2016-10-13T04:15:17Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![bernardeli](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/bernardeli/32/60_2.png) [@bernardeli](https://discourse.dry-rb.org/u/bernardeli)
#### Post date: [October 13, 2016, 4:15am UTC](https://discourse.dry-rb.org/t/how-to-handle-a-dry-struct-with-array-attribute-with-multiple-members-type/132/1 "2016-10-13T04:15:18Z")

</div>

Hi guys! Hope you’re all well.

Playing with dry-struct and dry-types, and wanted to add an array with members of two types, where both types have same attribute BUT different type definition (one string, another a hash struct). Example below:

```ruby
require "dry-struct"
require "dry-types"

module Types
  include Dry::Types.module
end

class Answer < Dry::Struct
  attribute :question_id, Types::String

  class Select < self
    attribute :value, Types::Hash.schema(id: Types::Int)
  end

  class Text < self
    attribute :value, Types::String
  end
end

class Survey < Dry::Struct
  attribute :answers, Types::Array.member(Answer::Text | Answer::Select)
end

Survey.new(
  answers: [
    Answer::Select.new(question_id: 1, value: {id: 10}),
    Answer::Text.new(question_id: 1, value: "foo")
  ]
)

#<Survey answers=[#<Answer::Text question_id=1 value={:id=>10}>, #<Answer::Text question_id=1 value="foo">]>

```

Problem here is, both answers came back as `Answer::Text`.

If I invert the order of the members to `.member(Answer::Select | Answer::Text)`, things blow up.

The other thing I tried was to have `.member(Answer)` since Select and Text are subclasses of Answer. It doesn’t blow up but turns Answer::Select into an Answer, getting rid of attribute :value.

How can I achieve members of an array to accept subclasses of a type?  
Appreciate if someone can shed some light for me!

Thanks heaps! 🙂

---

<div class="post-metadata">

### Author: ![solnic](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/solnic/32/779_2.png) [@solnic](https://discourse.dry-rb.org/u/solnic)
#### Post date: [October 16, 2016, 8:07pm UTC](https://discourse.dry-rb.org/t/how-to-handle-a-dry-struct-with-array-attribute-with-multiple-members-type/132/2 "2016-10-16T20:07:04Z")

</div>

This is gonna work:

```ruby
require "dry-struct"
require "dry-types"
require 'byebug'

module Types
  include Dry::Types.module
end

class Answer < Dry::Struct
  attribute :question_id, Types::String

  class Select < self
    attribute :value, Types::Strict::Hash.schema(id: Types::Int)
  end

  class Text < self
    attribute :value, Types::Strict::String
  end
end

class Survey < Dry::Struct
  attribute :answers, Types::Array.member(Answer::Text | Answer::Select)
end

 Survey.new(
  answers: [
    Answer::Select.new(question_id: 1, value: {id: 10}),
    Answer::Text.new(question_id: 1, value: "foo")
  ]
)

```

Notice that I changed `value` definitions to use strict types, otherwise there’s no way to validate which input is valid for a specific type, hence it didn’t work.

---

<div class="post-metadata">

### Author: ![bernardeli](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/bernardeli/32/60_2.png) [@bernardeli](https://discourse.dry-rb.org/u/bernardeli)
#### Post date: [October 16, 2016, 9:59pm UTC](https://discourse.dry-rb.org/t/how-to-handle-a-dry-struct-with-array-attribute-with-multiple-members-type/132/3 "2016-10-16T21:59:30Z")

</div>

Sweeet! That is great!

That brings me another question I haven’t found the answer on [dry-rb.org](http://dry-rb.org). When should I use `Types::String` as opposed to `Types::Strict::String`?

From my irb session, the Strict one returns a constrained, but should Type::String fail by default if that isn’t a string?

Thanks heaps for your help and really appreciate the effort you have put into the dry libraries.

Cheers  
Ricardo

---

<div class="post-metadata">

### Author: ![solnic](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/solnic/32/779_2.png) [@solnic](https://discourse.dry-rb.org/u/solnic)
#### Post date: [October 23, 2016, 9:25pm UTC](https://discourse.dry-rb.org/t/how-to-handle-a-dry-struct-with-array-attribute-with-multiple-members-type/132/4 "2016-10-23T21:25:18Z")

</div>

`Types::String` is a plain definition that is typically used for annotation purposes. ie in rom-rb it used for relation schemas, where we define attribute types with various meta-data. You should use strict types in places where you want to enforce constraints and you’d rather see an exception than an invalid value being silently passed around in your system.
