DEV Community

Fran C. for Factorial

Posted on

10 3

A trick with Ruby anonymous classes

Since everything in Ruby is an object it is only normal that classes are objects too. Which means they just have regular constructors with initializers, as any other object would do.

Class.new do
  def hello
    puts "Hello world!"
  end
end.new.hello

# prints -> Hello world!
Enter fullscreen mode Exit fullscreen mode

What can I use it for?

Anonymous classes are an amazing candidate for testing mixings.

# callable_test.rb
# run it with:
# ruby callable_test.rb

module Callable
  def call(*args)
    new(*args).call
  end
end

require "minitest/autorun"

class TestCallable < Minitest::Test
  def setup
    @klass = Class.new do
      extend Callable

      def initialize(arg1, arg2)
        @arg1 = arg1
        @arg2 = arg2
      end

      def call
        [@arg1, @arg2]
      end
    end
  end

  def test_same_return
    assert_equal @klass.new(1, 2).call, @klass.call(1, 2)
  end
end

# Run options: --seed 3295
#
# # Running:
#
# .
#
# Finished in 0.000605s, 1651.9615 runs/s, 1651.9615 assertions/s.
# 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
Enter fullscreen mode Exit fullscreen mode

There's a caveat though... You need to be aware that anonymous classes have no name (they are anonymous after all ;) ) so any call to Class.new.name will return nil.

Classes only acquire a name when you assign them to a constant. That is:

klazz = Class.new
klazz.name
# => nil

MyClass = klazz
klazz.name
# => "MyClass"
Enter fullscreen mode Exit fullscreen mode

So, if you need to test things which depend on the class name you can't use anonymous classes, although they still have a benefit over regular declarations on tests, which is that they can be assigned to variables, while regular class...end declarations can't.

my_class = class MyClass; end
my_class
# => nil

other_class = OtherClass = Class.new
other_class
# => OtherClass
Enter fullscreen mode Exit fullscreen mode

So, if you need a class with a name on a test you can still use this, only remember to remove the constant on your test's teardown.

Object.send(:remove_const, :MyClass)
Enter fullscreen mode Exit fullscreen mode

If you're on a Rails app and use RSpec, it even has a helper to test things with anonymous controllers: https://relishapp.com/rspec/rspec-rails/v/3-9/docs/controller-specs/anonymous-controller, which is especially useful to test things like login/logout flows independently.

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (0)

Qodo Takeover

Introducing Qodo Gen 1.0: Transform Your Workflow with Agentic AI

Rather than just generating snippets, our agents understand your entire project context, can make decisions, use tools, and carry out tasks autonomously.

Read full post

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay