RubyA trick with Ruby anonymous classes

Fran C.

Fran C.

2 minutes read

Originally published here

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.

1 2 3 4 5 6 7 Class.new do def hello puts "Hello world!" end end.new.hello # prints -> Hello world!

What can I use it for?

Anonymous classes are an amazing candidate for testing mixings.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 # 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

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:

1 2 3 4 5 6 7 klazz = Class.new klazz.name # => nil MyClass = klazz klazz.name # => "MyClass"

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.

1 2 3 4 5 6 7 my_class = class MyClass; end my_class # => nil other_class = OtherClass = Class.new other_class # => OtherClass

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.

1 Object.send(:remove_const, :MyClass)

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.

Fran C.
Staff Software Engineer

I break code for a living... wait no, I fix it, most of the times. Well, sometimes.Yeah, I break code for a living.

Liked this read?Join our team of lovely humans

We're looking for outstanding people like you to become part of our team. Do you like shipping code that adds value on a daily basis while working closely with an amazing bunch of people?

Made with ❤️ by Factorial's Team