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
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 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
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