Struct

Create a class with fields come with accessors.

User = Struct.new(:name, :email)
User.new("juanito", "juanito@hi.com")

# with `keyword_init`
User = Struct.new(:name, :email, keyword_init: true)
User.new(name: "juanito", email: "juanito@hi.com")

You can freeze the input argument to avoid being changed!

BillingUser = Struct.new(:user) do
  def initialize(...)
    super
    freeze
  end

  def billing_period
    user.billig_ends_at
  end
end

juanito = BillingUser.new(juanito)
juanito.user = matz
FrozenError: can't modify frozen BillingUser: #<struct BillingUser user=nil>