Skip to main content

Command Palette

Search for a command to run...

Exploring `it` default block param warning in Ruby 3.3

Understanding the `it` default block parameter warning in Ruby 3.3 RC1

Updated
5 min read
Exploring `it` default block param warning in Ruby 3.3

In the last Ruby Developer Meeting it was accepted that it will be added to Ruby 3.4.

In preparation for this, Ruby 3.3 will show a warning when it is used without a receiver, argument, or block.

I made a quick video about this if you want to watch it or if you prefer the written version continue reading on:

Deprecation warning

For this, let's define some simple code where I will name a method it and then call it from a block:

puts RUBY_VERSION

def it = "works"

def run(&block) = yield

puts run { it }

If you run this with Ruby 3.2.2 then you will get the following result:

3.2.2
works

But if you run this with Ruby 3.3.0.rc1 you will get the following result:

example_deprecation_warning.rb:7: warning: `it` calls without 
arguments will refer to the first block param in Ruby 3.4; 
use it() or self.it
3.3.0
works

How to fix the warning

In case you have a method named it and still want to call it inside a block without a receiver, arguments or params you should either add paranthesis:

- puts run { it }
+ puts run { it() }

or add the receiver:

- puts run { it }
+ puts run { self.it }

When using it as local variable name

There will be no problem when you defined it as local variable name.

Here is an example where I created:

puts RUBY_VERSION

def log(&block) = puts yield

def run
  it = 2

  log { it }
end

run

If you run this it on Ruby 3.3.0.rc1 will not display an error. The output will be:

3.3.0
2

Now if you will extract the local variable to a method with the same name:

puts RUBY_VERSION

def log(&block) = puts yield
+
+ def it = 2
+
def run
-  it = 2

  log { it }
end

run

It will show a warning:

it_as_local_variable.rb:8: warning: `it` calls without arguments 
will refer to the first block param in Ruby 3.4; use it() or self.it
3.3.0
2

RSpec

RSpec uses a lot it. But in most cases (I would argue majority of them) this will not be a problem. Because usually it is called with a string argument:

require "rspec"

describe Galaxy do
  context "when created with a name and number of stars" do
    it "should hold the correct name and star count" do
      galaxy = Galaxy.new("Milky Way", 100_000_000_000)
      expect(galaxy.name).to eq("Milky Way")
      expect(galaxy.number_of_stars).to eq(100_000_000_000)
    end
  end
end

The code above will NOT display a warning.

But if you will try to write something like this:

require "rspec"

describe Galaxy do
  subject { Galaxy.new("Milky Way", 100_000_000_000).stars }

  context "When there are no known stars" do
    it
  end
end

If you run this with Ruby 3.3.0.rc.1 you will get the warning:

explore-it/rspec_example/spec/more_galaxy_spec.rb:8: warning: `it` 
calls without arguments will refer to the first block param in 
Ruby 3.4; use it() or self.it
*

Pending: (Failures listed here are expected and do not affect your suite's status)

  1) Galaxy When there are no known stars 
     # Not yet implemented
     # ./spec/more_galaxy_spec.rb:8


Finished in 0.0074 seconds (files took 0.06474 seconds to load)
1 example, 0 failures, 1 pending

You can fix this by using one of the other alias for it from RSpec:

Here is the complete list of methods defined in RSpec core:

# Defines an example within a group.
define_example_method :example
# Defines an example within a group.
# This is the primary API to define a code example.
define_example_method :it
# Defines an example within a group.
# Useful for when your docstring does not read well off of `it`.
# @example
#  RSpec.describe MyClass do
#    specify "#do_something is deprecated" do
#      # ...
#    end
#  end
define_example_method :specify

# Shortcut to define an example with `:focus => true`.
# @see example
define_example_method :focus,    :focus => true
# Shortcut to define an example with `:focus => true`.
# @see example
define_example_method :fexample, :focus => true
# Shortcut to define an example with `:focus => true`.
# @see example
define_example_method :fit,      :focus => true
# Shortcut to define an example with `:focus => true`.
# @see example
define_example_method :fspecify, :focus => true
# Shortcut to define an example with `:skip => 'Temporarily skipped with xexample'`.
# @see example
define_example_method :xexample, :skip => 'Temporarily skipped with xexample'
# Shortcut to define an example with `:skip => 'Temporarily skipped with xit'`.
# @see example
define_example_method :xit,      :skip => 'Temporarily skipped with xit'
# Shortcut to define an example with `:skip => 'Temporarily skipped with xspecify'`.
# @see example
define_example_method :xspecify, :skip => 'Temporarily skipped with xspecify'
# Shortcut to define an example with `:skip => true`
# @see example
define_example_method :skip,     :skip => true
# Shortcut to define an example with `:pending => true`
# @see example
define_example_method :pending,  :pending => true

Conclusion

I really like that it was accepted as a default block parameter. Looking forward to Ruby 3.4 (next year) to write code using it.

The warning feature in Ruby 3.3 serves as a useful heads-up for potential conflicts with its usage, although these are expected to occur infrequently.

The transition should be smooth for most developers. RSpec tests should not require any changes, as it largely uses it with a string argument and is not likely to trigger the warning. In the instances where it does, alternatives like specify and example can be used to fix the warning.


Enjoyed this article?

👉 Join my Short Ruby News newsletter for weekly Ruby updates from the community and visit rubyandrails.info, a directory with learning content about Ruby.

👐 Subscribe to my Ruby and Ruby on rails courses over email at learn.shortruby.com - effortless learning anytime, anywhere

🤝 Let's connect on Ruby.social or Linkedin or Twitter where I post mainly about Ruby and Rails.

🎥 Follow me on my YouTube channel for short videos about Ruby

Modern Ruby

Part 7 of 11

Learn how to use the new Ruby syntax and write beautiful code. You will discover the new syntax added from Ruby 2.7 to Ruby 3.3 and practical examples of using them in a Ruby on Rails application.

Up next

An Endless Method Use Case

An example of where I think the endless method helps with making the code concise and easy to read

More from this blog

All about code - Ruby and Rails technical content written by Lucian Ghinda

101 posts

I write here quick thoughts, ideas, tips, and learnings about programming, programmers, and building software. Most of my focus is on Ruby, Rails, Hotwire, and everything about web applications.