Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow codependent Dash attributes to initialize #437

Merged
merged 1 commit into from
Feb 7, 2018

Conversation

michaelherold
Copy link
Member

Definition: Codependent properties
A set of two or more properties who have "required" validations that are based
on each other.

Example:

class OneOrMore < Hashie::Dash
  property :a, required: -> { b.nil? }
  property :b, required: -> { a.nil? }
end

When constructing a Dash via the merge initializer, codependent properties have
their "required" validation run too early when their values are set to nil,
which causes an ArgumentError to be raised in the case that the first property
is set to nil.

This is an order-dependence bug that is fixed by this commit. By pruning off
nil values only during initialization via the merge initializer, we can
prevent this problem from occurring for the case of nil values.

However, this is an indication of a larger problem with the architecture of
Dash. We should be setting all the properties before running the validations.
Rearchitecting this will be quite an undertaking.

Fixes #431

def initialize_attributes(attributes, options = {})
return unless attributes

set_nils = options.delete(:set_nils)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This modifies the calling hash, so probably not a great idea?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's an internal function so it's unused data, but I see your point.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we're purists here, never make assumptions about the caller, things change fast ;)

self[att] = value
end if attributes
end
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should break up this function instead in two and kill the option, since it's used very differently in different places.

Definition: Codependent properties
A set of two or more properties who have "required" validations that are based
on each other.

Example:

```ruby
class OneOrMore < Hashie::Dash
  property :a, required: -> { b.nil? }
  property :b, required: -> { a.nil? }
end
```

When constructing a Dash via the merge initializer, codependent properties have
their "required" validation run too early when their values are set to `nil`,
which causes an `ArgumentError` to be raised in the case that the first property
is set to `nil`.

This is an order-dependence bug that is fixed by this commit. By pruning off
`nil` values only during initialization via the merge initializer, we can
prevent this problem from occurring for the case of `nil` values.

However, this is an indication of a larger problem with the architecture of
Dash. We should be setting all the properties before running the validations.
Rearchitecting this will be quite an undertaking.
@michaelherold michaelherold force-pushed the codependent-properties branch from 76e81e0 to 0bd18ee Compare February 7, 2018 00:42
@michaelherold
Copy link
Member Author

Refreshed! What do you think?

@dblock
Copy link
Member

dblock commented Feb 7, 2018

👏 very very nice solution, naming things really clearly, love it

@dblock dblock merged commit 1117208 into hashie:master Feb 7, 2018
@michaelherold michaelherold deleted the codependent-properties branch August 11, 2018 17:04
netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this pull request Sep 23, 2018
## [3.6.0] - 2018-08-13

[3.6.0]: hashie/hashie@v3.5.7...v3.6.0

### Added

* [#455](hashie/hashie#455): Allow overriding methods when passing in a hash - [@lnestor](https://github.com/lnestor).

### Fixed

* [#435](hashie/hashie#435): Mash `default_proc`s are now propagated down to nested sub-Hashes - [@michaelherold](https://github.com/michaelherold).
* [#436](hashie/hashie#436): Ensure that `Hashie::Extensions::IndifferentAccess` injects itself after a non-destructive merge - [@michaelherold](https://github.com/michaelherold).
* [#437](hashie/hashie#437): Allow codependent properties to be set on Dash - [@michaelherold](https://github.com/michaelherold).
* [#438](hashie/hashie#438): Fix: `NameError (uninitialized constant Hashie::Extensions::Parsers::YamlErbParser::Pathname)` in `Hashie::Mash.load` - [@onk](https://github.com/onk).
* [#457](hashie/hashie#457): Fix `Trash` to allow it to copy properties from other properties - [@michaelherold](https://github.com/michaelherold).

### Miscellaneous

* [#433](hashie/hashie#433): Update Rubocop to the most recent version - [@michaelherold](https://github.com/michaelherold).
* [#434](hashie/hashie#434): Add documentation around Mash sub-Hashes - [@michaelherold](https://github.com/michaelherold).
* [#439](hashie/hashie#439): Add an integration spec for Elasticsearch - [@michaelherold](https://github.com/michaelherold).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Co-dependent Dash attributes break requirement validation
2 participants