This is part 3 in this series on Ruby's Data Class. Part 1 covered Syntax and part 2 compared Data with Struct.
Immutability Workarounds, Sort of
We can work (arguably) against the intent of Data
in some ways.
For example, when an attribute is set to a Hash
, we can update values in the hash.
ColorCounts = Data.define(:color_tally)
# => Colorcounts
screen_colors = ColorCounts.new({red: 0, blue: 0, green: 0})
# => #<data ColorCounts color_tally={:red=>0, :blue=>0, :green=>0}>
# Update a value in `color_tally`
screen_colors.color_tally[:red] += 5
# => 5
# Note that the value for `:red` has been updated
screen_colors.color_tally
# => {:red=>5, :blue=>0, :green=>0}
We can also workaround to update a (non-frozen) string.
Example:
Person = Data.define(:name)
# => Person
me = Person.new(name: +'Popko')
# => #<data Person name="Popko">
me.name.prepend 'Kelly '
# => 'Kelly Popko'
me.name
# => 'Kelly Popko'
So we are not completely without the ability to modify or create certain workarounds.
However, when we need more flexibility or mutability, for example, we would want to choose class
or something else more suited to what we need instead of trying to work around it with Data
.
Conclusion
Using a Data object communicates the intent of the object to current and future collaborators.
Data is a great choice when you want to avoid a mutated value on the object coming back to haunt you.
Top comments (0)