Value Data-объекты в Руби

Я как-то пропустил, а в Руби 3.2 завезли класс Data для создания value objects:

Recipient = Data.define(:name, :email, :role)

vasyan = Recipient.new(name: "Vasyan", email: "vasyan@stark.com", role: :cc)

vasyan.email # vasyan@stark.com vasyan.role # :cc

#При этом

vasyan.email = "foo" # undefined method 'email='

Пример посложнее с кастомными методами:

Measure = Data.define(:amount, :unit) do def <=>(other) return unless other.is_a?(self.class) && other.unit == unit amount <=> other.amount end

include Comparable end

Measure[3, 'm'] < Measure[5, 'm'] #=> true Measure[3, 'm'] < Measure[5, 'kg'] # ArgumentError

Отличается от Struct двумя ключевыми моментами. Во-первых, Data не генерирует сеттеры (attr_writer) для атрибутов. Во-вторых, Data не включает Enumerable, поэтому в нем нет each, each_pair, filter и прочих. Короче, Data — это идеальный вариант для минималистичных неизменяемых value objects