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