Skip to content

adamhooper/ruby-immutable-struct

Repository files navigation

Yet Another Immutable Struct Implementation

Usage

First, add this to your Gemfile:

gem 'ruby-immutable-struct'

Then use it like this:

Person = RubyImmutableStruct.new(:name, :email) do
  def rfc5322_email
    "\"#{name}\" <#{email}>"
  end
end

# Constructor accepts ordered arguments
person = Person.new('Adam Hooper', 'adam@adamhooper.com')

# Constructor also accepts a Hash. This produces the same thing (though it's
# a few microseconds slower):
person = Person.new(name: 'Adam Hooper', email: 'adam@adamhooper.com')

# However it's constructed, Methods work as you'd expect
person.name # 'Adam Hooper'
person.email # 'adam@adamhooper.com
person.rfc5322_email # '"Adam Hooper" <adam@adamhooper.com>

# You'll get a few free helpers:
person.to_h    # { name: 'Adam Hooper', email: 'adam@adamhooper.com' }
person.to_a    # [ 'Adam Hooper', 'adam@adamhooper.com' ]
person.inspect # '#<Person:"Adam Hooper","adam@adamhooper.com")'

# Instances are immutable. That means you can't write code like
# person.email = 'adam+nospam@adamhooper.com'
# You never change an instance; you only create a new one, like this:
person2 = person.merge(email: 'adam+nospam@adamhooper.com')

# When two immutable structs have the same values, they are equal
person3 = person2.merge(email: 'adam@adamhooper.com')
person == person3    # true
person.eql?(person3) # true
# And that means you can use them in a hash
hash = { person => 'yay' }
hash[person3] # 'yay'

Here's a bit of a hack for when you want to run calculations just once:

Person = RubyImmutableStruct.new(:name, :email) do
  def after_initialize
    if @email.nil?
      @email = "#{name.gsub(/[^a-zA-Z0-9]+/, '-')}@gmail.com"
    end
  end
end

Similar projects

Here are projects that are slightly different:

License

MIT

About

Like Structs, but you can't edit them once you construct them

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages