<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