Keeping it classy with Struct

You can use Struct to bundle attributes together using accessor methods without having to write an explicit class. It’s easy and almost fun.

Contents

The original class

I was recently writing a DSL to handle attributes on the fly. My attribute class originally looked something like this:

module CoolThing
  class Builder
    class Attribute
      def initialize(name, options, block)
        @name = name 
        @options = options
        @block = block 
         
        do_some_checks!
      end 
  
      def value(klass)
        klass.instance_exec(&block)
      end
  
      private 

      attr_reader :name, :options, :block 

      def do_some_checks!
        # do something
      end
    end
  end 
end 

But for some reason I didn’t like that explicit class Attribute. It felt icky in the way that I was writing it.

The class, but with Struct

module CoolThing
  class Builder 
    Attribute = Struct.new(:name, :options, :block) do 
      def initialize(*)
        super(*)
        
        do_some_checks!
      end

      def value(klass)
        klass.instance_exec(&block)
      end

      private 
      
      def do_some_checks!
        # do something
      end
    end 
  end 
end

This gave me the same ability to create a new instance of Attribute while not having a class definition within a class definition.