wasabigeek

TIL: Extending a Ruby Struct

November 07, 2021

Last week I had a head-scratching moment looking at the following code (from the google-api-ruby-client):

ClientOptions = Struct.new(
    :application_name,
    :application_version,
    :proxy_url,
    :open_timeout_sec,
    :read_timeout_sec,
    :send_timeout_sec,
    :log_http_requests,
    :transparent_gzip_decompression)

# ...

class ClientOptions
    # ...
    def self.default
    @options ||= ClientOptions.new
    end
end

My initial confusion stemmed from the assumption that the first ClientOptions declaration returned a regular object. A helpful colleague explained to me that Struct.new actually returns a subclass of Struct. That meant the second class ClientOptions declaration was actually re-opening the class to add a method, not to declare a new class.

Why would one want to do this? Well, one would get all the methods of a regular Struct (e.g. accessors, iterators) for free at the cost of the inheritance hierarchy. This could be useful for ValueObjects.

Comments


Written by Nick who is a indie-hacker wannabe, living in sunny Singapore. Twitter | GitHub