What is a Struct in Ruby?
Let’s say that you need to store related data together but you don’t need methods & you don’t want to create a class… A Ruby Struct solves this problem by letting you create objects with very simple syntax.
Point with two coordinates (
You wouldn’t want to create a whole class just to store these values together!
In this post:
You’ll learn how to create structs, the difference between a Ruby Struct & OpenStruct, and a few things you should watch out for!
You can create a
Struct by calling
new & passing in a list of symbols that’ll become the instance variables of this class.
They will have accessors defined by default, both for reading & writing.
Here’s an example:
person = Struct.new(:name, :age, :gender)
Now you can create an object like this:
john = person.new "john", 30, "M" puts john.age puts john.class
Structs can be compared directly, based on their attributes:
john == john # true
If this were a regular Ruby object you would have to define the
== method yourself.
There are some differences with a “normal” class that you should be aware of.
For example, you may have noticed that the class of our
john object is just “Class”…
…to change this, you can do one of the following:
# Option 1 - Assign to a constant Person = Struct.new(:name, :age, :gender) # Option 2 - Subclass class Person < Struct.new(:name, :age, :gender) end
Both of these options will cause your new objects to have the class name you want.
Another caveat with struct-generated classes... they won't enforce the correct number of arguments for the constructor.
With a proper class you would see this error:
ArgumentError: wrong number of arguments (0 for 3)
But if you are using a Struct the missing arguments will be nil:
Person.new("peter") # struct Person name="peter", age=nil, gender=nil
Keep this in mind when working with
Another weird thing:
Struct.new(:a).ancestors [#<Class:0x29b1040>, Struct, Enumerable, Object, Kernel, BasicObject]
Let's say that you're reading lines from a file & each line represents one item.
200 /login 18:00 404 /bacon 18:03 200 /books 18:04
You work more easily with this data if you create a custom class.
LogEntry = Struct.new(:status, :url, :time) LogEntry.new(200, '/books', '18:04')
But to make it extra clear what every argument represents you many want to use keyword arguments.
Ruby 2.5 added support for keywords arguments in
Here's how to use it:
LogEntry = Struct.new(:status, :url, :time, keyword_init: true) LogEntry.new(status: 200, url: '/books', time: '18:04')
Now you can parse your file & convert it into
If you just need a one-off object, then you should consider using
Here's an example:
require 'ostruct' cat = OpenStruct.new(color: 'black') puts cat.class puts cat.color
The difference between
OpenStruct is a fancy Hash object, while a
Struct is like creating a new class from a template.
You've learned about Ruby Struct & OpenStruct! As long as you are aware of the special characteristics of each of these clases you'll be fine.
Now go and start coding 🙂