Sandip Mane
by Sandip Mane
2 min read

Categories

  • Ruby

Tags

  • class
  • ruby

Struct is a collection of attributes with accessor methods, without having to write the class explicitly.

A Struct class generates a new subclass that contains a set of members and their values. For each member, a reader and writer method is created similar to #attr_accessor.

> Vehicle = Struct.new(:make, :model)
> Vehicle.superclass
=> Struct

> Vehicle.ancestors
=> [Vehicle, Struct, Enumerable, Object, Kernel, BasicObject]

Since Struct is bundled with Enumerable module, we can take advantage of methods like #filter, #count, #include?, #uniq, #tally etc.

Example

> Vehicle = Struct.new(:make, :model)

> Vehicle["Dodge", "Hellcat"]
=> #<struct Vehicle make="Dodge", model="Hellcat">

> bike = Vehicle.new("Triumph", "Daytona")
> bike
=> #<struct Vehicle make="Triumph", model="Daytona">

> bike.make = "Yamaha"
> bike["model"] = "R1"
> bike
=> #<struct Vehicle make="Yamaha", model="R1">

Structure with name under Struct

We can pass in a class_name argument, which then will be scoped under Struct to define the class.

> Struct.new("Vehicle", :make, :model)
=> Struct::Vehicle
> Struct::Vehicle.new("BMW", "S1000RR")
=> #<struct Struct::Vehicle make="BMW", model="S1000RR">

Structure with name of it’s Constant

When the class_name argument is not passed, if it’s assigned to a constant then a class with the name of the constant is created otherwise an anonymous class is created.

> Vehicle = Struct.new(:make, :model)
> Vehicle.new("BMW", "S1000RR")
=> #<struct Vehicle make="BMW", model="S1000RR">

> Struct.new(:make, :model)
=> #<Class:0x00007fb4e8ab45b0>

keyword_init argument

If this is given while defining the Struct, the #new method will accept keyword arguments instead of normal arguments.

> Vehicle = Struct.new(:make, :model, keyword_init: true)
> Vehicle.new(make: "BMW", model: "S1000RR")
=> #<struct Vehicle make="BMW", model="S1000RR">

Customize

> Vehicle = Struct.new(:make, :model, :number_of_wheels) do
>  def bike?
>    number_of_wheels == 2
>  end
> end

> hellcat = Vehicle.new("Dodge", "Hellcat", 4)
> hellcat.bike?
=> false

Equality

Returns true if other has the same class and values for it’s members. Object#== is used for comparison.

> Customer  = Struct.new(:name, :address, :zip)
> joe       = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
> smith     = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
> joe == smith   #=> true

#values method

Returns values of it’s members as an array.

> Customer  = Struct.new(:name, :address, :zip)
> joe       = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
> joe.values
=> ["Joe Smith", "123 Maple, Anytown NC", 12345]

#members method

Returns it’s members as an array.

> Customer  = Struct.new(:name, :address, :zip)
> joe       = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
> joe.members
=> [:name, :address, :zip]

#dig method

Extracts the nested value. Check out my previous post on #dig for more details.

> Address   = Struct.new(:lane, :city, :location_data)
> Customer  = Struct.new(:name, :address)

> address   = Address.new("123 Maple", "Anytown NC", { lane: { street: "123 Watson Street" }, zip: 12345 })
> joe       = Customer.new("Joe Smith", address)
> joe.dig(:address, :location_data, :lane, :street)
=> "123 Watson Street"

Finally,

In this post, we have checked all the details about ruby’s Struct class and some of it’s useful methods.

And as always, thanks for reading!😃