Ruby 2.7 - Singleton class yield syntax throws a warning

1 minute read

Singleton classes are classes which can be instantiated only once.

There are various ways to create a singleton class or methods in Ruby as below:

class Logger def self . log ( msg ) @@log ||= File . open ( "log.txt" , "a" ) @@log . puts ( msg ) end end Logger . log ( 'message 5' ) module Logger def self . log ( msg ) @@log ||= File . open ( "log.txt" , "a" ) @@log . puts ( msg ) end end

Singleton class can also contain yield , which when called with a block will execute the block. As shown below

def foo class << Object . new yield end end foo { puts "Hello Ruby!" } => "Hello Ruby!"

Before Ruby 2.7 this function gets executed without any warnings or errors.

In Ruby 2.7

In Ruby 2.7 a warning will be issued when the above function is executed.

def foo class << Object . new yield end end warning: `yield' in class syntax will not be supported from Ruby 3.0. [Feature #15575] foo { puts "Hello Ruby!" } => "Hello Ruby!"

This will be deprecated since yield in singleton class syntax was inconsistent with local variables accessibility.

Consider below example

def foo x = 1 class << Object . new p x # NameError (undefined local variable or method) -- enclosing scope NOT accessible yield # calls block passed to foo, implying enclosing scope IS accessible # In Ruby 2.7: warning: `yield' in class syntax will not be supported from Ruby 3.0. end end foo { p "Hello Ruby!" }

The above code raises error as shown below

NameError (undefined local variable or method `x' for #<Class...>

NOTE: The variables declared in the block are accessible in the enclosing scope of the singleton class.