# Dry-struct: Dependent attributes

**URL:** <https://discourse.dry-rb.org/t/dry-struct-dependent-attributes/1191>\
**Category:** Support\
**Created:** [February 1, 2021, 5:53pm UTC](https://discourse.dry-rb.org/t/dry-struct-dependent-attributes/1191 "2021-02-01T17:53:05Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![drqCode](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/drqcode/32/223_2.png) [@drqCode](https://discourse.dry-rb.org/u/drqCode)\
**Post date:** [February 1, 2021, 5:53pm UTC](https://discourse.dry-rb.org/t/dry-struct-dependent-attributes/1191/1 "2021-02-01T17:53:05Z")

</div>

Is there any known reason for dry-struct not having the ability to define dependent attributes like [FactoryBot dependent attributes](https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md#dependent-attributes)?

```
  class NewUser < Dry::Struct
    attribute :email, Types::String

    dependent_attribute :username, Types::String do
      email.split('@').first
    end

    # or

    attribute :username, Types::String, dependent: true do
      email.split('@').first
    end

    # or
    
    attribute! :username { Types::String.default(email.split('@').first) }
  end

```

Wouldn’t it have the same reason as default values?

---

<div class="post-metadata">

**Author:** ![flash-gordon](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/flash-gordon/32/494_2.png) [@flash-gordon](https://discourse.dry-rb.org/u/flash-gordon)\
**Post date:** [February 2, 2021, 9:34am UTC](https://discourse.dry-rb.org/t/dry-struct-dependent-attributes/1191/2 "2021-02-02T09:34:24Z")

</div>

No, and there won’t be such a feature in dry-struct. Mostly because it’s not aligned with how the gem operates, there’s no simple way to implement it. This would also make the DSL more complex, both internally and externally for a small gain.

That said, in some cases, I override the constructor:

```ruby
class NewUser < Dry::Struct
  attribute :email, Types::String
  attribute :username, Types::String
 
  def self.new(values)
    super(values.merge(username: values[:email].split('@', 2).first))
  end
end

```

I don’t promise it’ll work in all cases but it does in simple ones.

---

<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:** [February 4, 2021, 5:49am UTC](https://discourse.dry-rb.org/t/dry-struct-dependent-attributes/1191/3 "2021-02-04T05:49:33Z")

</div>

If you do this, I would call it a code smell in dry-rb land. Structs are meant to be simple data capsules, they should not map data or construct values. Even coercion at a single value level is already a tiny, little code smell, but for now it’s fine since we’re not there yet with a full-stack, stand-alone data transformation solution.

---

<div class="post-metadata">

**Author:** ![drqCode](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/drqcode/32/223_2.png) [@drqCode](https://discourse.dry-rb.org/u/drqCode)\
**Post date:** [February 4, 2021, 9:43pm UTC](https://discourse.dry-rb.org/t/dry-struct-dependent-attributes/1191/4 "2021-02-04T21:43:37Z")

</div>

In that case, defaults seem to be a similar code smell too🤔. What dry do you think is more appropiate to tackle this case? For now, I defined a method for that attribute and overrode #to\_h to include it. I’m thinking also to a builder…

---

<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:** [February 5, 2021, 6:35am UTC](https://discourse.dry-rb.org/t/dry-struct-dependent-attributes/1191/5 "2021-02-05T06:35:11Z")

</div>

> [@drqCode](#):
>
> In that case, defaults seem to be a similar code smell too

Yes you are absolutely correct.

> [@drqCode](#):
>
> What dry do you think is more appropiate to tackle this case? For now, I defined a method for that attribute and overrode #to\_h to include it. I’m thinking also to a builder…

For now I recommend doing literally whatever is simpler and works in your case. We’ll provide a nice, 1st-class solution eventually.

---

<div class="post-metadata">

**Author:** ![flash-gordon](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/flash-gordon/32/494_2.png) [@flash-gordon](https://discourse.dry-rb.org/u/flash-gordon)\
**Post date:** [February 5, 2021, 7:54pm UTC](https://discourse.dry-rb.org/t/dry-struct-dependent-attributes/1191/6 "2021-02-05T19:54:24Z")

</div>

> For now I recommend doing literally whatever is simpler and works in your case. We’ll provide a nice, 1st-class solution eventually.

I think this could work. Not sure how nice but this could work 🙂
