Ruby 3.2 introduces a new Data
class to define immutable value objects that contain a simple set of values. Similar to the Struct
class in Ruby, it provides a simpler and more restricted API. In this article, we’ll explore what the Data
class is and how it can be useful from a practical perspective.
You may find this concept familiar because it resembles Struct.new
, which also defines similar classes. However, there is a fundamental difference. Data
classes are immutable, meaning they lack setters for the attributes.
Creating a Data Class
To create a Data
class, you must define a class name and a list of attributes. You can do this using the Data.define
method
1
Country = Data.define(:name, :currency)
With that, you can create a new instance of the Country class by passing values to the attributes:
1
country = Country.new("Peru", "Sol")
You can access the attributes of a Data
class instance using the accessor methods.
1
2
country.name # => "Peru"
country.currency # => "Sol"
Immutability
Immutability refers to the property of an object that cannot be modified once created. This characteristic brings several benefits, including easier reasoning about code behavior and avoiding unexpected side effects. If you try to do so, an exception will be raised.
1
country.name = "Argentina" # => RuntimeError: can't modify frozen Data
Composition
You can use the Data
class to create new classes that represent more complex objects. For example, you can compose multiple Data
classes together to create a new class with a combination of attributes.
1
2
3
4
5
6
7
8
9
10
11
Food = Data.define(:name, :main_ingredient, :vegetarian)
# => Food
food = Food.new("Ceviche", "Fish", false)
# => #<data Food name="Ceviche", main_ingredient="Fish", vegetarian=false>
Country = Data.define(:name, :currency, :food)
# => Country
country = Country.new("Peru", "Sol", food)
# => #<data Country name="Peru", currency="Sol", food=#<data Food name="Ceviche", main_ingredient="Fish", vegetarian=false>
For details, check the merge here: https://github.com/ruby/ruby/pull/6353