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.

Comments

comments powered by Disqus