Skip to content
This repository was archived by the owner on Jun 1, 2026. It is now read-only.

Repository files navigation

<img src=“https://travis-ci.org/stitchfix/immutable-struct.svg?branch=master” alt=“Build Status” />

Creates struct-like classes (that can build value objects) that do not have setters and also have better constructors than Ruby’s built-in Struct.

This is highly useful for creating presenters, non-database-related models, or other quick and dirty classes in your application. Instead of using a Hash or OpenStruct, you can create a bit more clarity around your types by using ImmutableStruct, which is almost as convienient.

Add to your Gemfile:

gem'immutable-struct'

Then install:

bundleinstall

If not using bundler, just use RubyGems:

geminstallimmutable-struct
Person = ImmutableStruct.new(:name, :age, :job, :active?, [:addresses]) dodefminor?age<18endendp = Person.new(name:"Dave", # name will be 'Dave'age:40, # age will be 40# job is omitted, so will be nilactive:true) # active and active? will be true# addresses is omitted, but since we've selected# Array coercion, it'll be []p.name# => "Dave"p.age# => 40p.active?# => truep.minor?# => falsep.addresses# => []p2 = Person.new(name:"Dave", age:40, active:true)
p==p2# => truep.eql?(p2) # => trueSimilarPerson = ImmutableStruct.new(:name, :age, :job, :active?, [:addresses])
sp = SimilarPerson.new(name:"Dave", age:40, active:true)
p==sp# => false # Different class leads to inequalitynew_person = p.merge(name:"Other Dave", age:41) # returns a new object with merged attributesnew_person.name# => "Other Dave"new_person.age# => 41new_person.active?# => true

You can coerce values into struct types by using the from method. This is similar to Ruby’s conversion functions, e.g. Integer(“1”).

dave = Person.from(p)
dave.equal?(p) # => true (object equality)daveish = Person.from(dave.to_h)
daveish.equal?(dave) # => falsedaveish==dave# => true

You can treat the interior of the block as a normal class definition with the exception of setting constants. Use const_set to scope constants as-expected.

Point = ImmutableStruct.new(:x, :y) doconst_set(:ZERO, 0)
ONE_HUNDRED = 100endPoint::ZERO# => 0::ONE_HUNDRED# => 100::ZERO# => NameError: uninitialized constant ZERO

About

Create struct-like classes that don't have setters, but have an awesome constructor.

Resources

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages