Proper way to use the Struct

We use Structs in Ruby to create simple classes with constructor and some instance variables.

Look at this simple User class:

class User
  attr_accessor :first_name, :last_name, :age
  
  def initialize(first_name, last_name, age)
    @first_name = first_name
    @last_name = last_name
    @age = age
  end
end

Using Struct, you can simply use a single line instead of declaring attr_accessors and constructor and the class will have exactly the same API:

User = Struct.new(:first_name, :last_name, :age)

But when it comes to a class with internal resources like constants, you may get a warning:

User = Struct.new(:first_name, :last_name, :age) do
  MIN_AGE = 18

  # some methods dealing with user
end

Admin = Struct.new(:first_name, :last_name, :age) do
  MIN_AGE = 21
end

# => warning: already initialized constant MIN_AGE
# => warning: previous definition of MIN_AGE was here

What happends here? We assumed that MIN_AGE was declared inside User and Admin, but actually it was declared on the top level:

> Object::MIN_AGE
=> 18

And warnings were printed.

But wait, there is actually a proper way to subclass from Struct:

class User < Struct.new(:first_name, :last_name, :age)
  LIMIT = 1
end

class Admin < Struct.new(:first_name, :last_name, :age)
  MIN_AGE = 21
end

No warnings here!

I also recommend you to check it the post by Steve Klabnik, where he describes all power of Struct.

About the author

Kir Shatrov Kir Shatrov helps businesses to grow by scaling the infrastructure. He likes to write about software, scalability and interesting stories that he runs into at work. Follow him on Twitter to get the latest updates: @kirshatrov.

Comments

comments powered by Disqus