diff options
| author | Michael Herold <michael.j.herold@gmail.com> | 2018-02-05 20:10:23 -0600 |
|---|---|---|
| committer | Michael Herold <michael.j.herold@gmail.com> | 2018-02-06 18:42:02 -0600 |
| commit | 0bd18eeb5bcbbc17d476573ae8a311fc339b6c82 (patch) | |
| tree | 3d5201c99fa176c2be635cf9c2b3fa1a02a3019e /lib | |
| parent | 3c6149cdd72ab8cc87cf008cc222514e30ef7470 (diff) | |
| download | hashie-0bd18eeb5bcbbc17d476573ae8a311fc339b6c82.tar.gz | |
Allow codependent Dash attributes to initialize
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.
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/hashie/dash.rb | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/lib/hashie/dash.rb b/lib/hashie/dash.rb index 4ac7676..a111e4b 100644 --- a/lib/hashie/dash.rb +++ b/lib/hashie/dash.rb @@ -160,7 +160,7 @@ module Hashie end def update_attributes!(attributes) - initialize_attributes(attributes) + update_attributes(attributes) self.class.defaults.each_pair do |prop, value| self[prop] = begin @@ -175,9 +175,18 @@ module Hashie private def initialize_attributes(attributes) + return unless attributes + + cleaned_attributes = attributes.reject { |_attr, value| value.nil? } + update_attributes(cleaned_attributes) + end + + def update_attributes(attributes) + return unless attributes + attributes.each_pair do |att, value| self[att] = value - end if attributes + end end def assert_property_exists!(property) |
