vince
vince

Reputation: 2848

ArgumentError (wrong number of arguments (given 2, expected 1)) after updating to Ruby 3.0

When I try to update our site to Ruby 3.0.0 I get this error:

ArgumentError (wrong number of arguments (given 2, expected 1))

 % rails console
Loading development environment (Rails 6.1.0)
irb(main):001:0> puts RUBY_VERSION
3.0.0
irb(main):002:0> puts IceCube::VERSION
0.16.3
irb(main):003:0> schedule = IceCube::Schedule.new
=> #<IceCube::Schedule:0x00007fccfe19cfa8 @start_time=2020-12-27 11:14:30 -0800, @all_recurrence_rules=[], @all_exception_rules=[]>
irb(main):004:0> puts schedule.to_ical
Traceback (most recent call last):
        1: from (irb):4:in `<main>'
ArgumentError (wrong number of arguments (given 2, expected 1))

Here are the same commands with Ruby 2.7.2 which work

% rails console
Loading development environment (Rails 6.1.0)
irb(main):001:0> puts RUBY_VERSION
2.7.2
irb(main):002:0> puts IceCube::VERSION
0.16.3
irb(main):003:0> schedule = IceCube::Schedule.new
=> #<IceCube::Schedule:0x00007f9da3128fe8 @start_time=2020-12-27 11:12:50 -0800, @all_recurrence_rules=[], @all_exception_rules=[]>
irb(main):004:0> puts schedule.to_ical
DTSTART;TZID=PST:20201227T111250

What's confusing is that it also works with a plain ruby script with the same gem versions as the first example

% irb
irb(main):001:0> puts RUBY_VERSION
3.0.0
irb(main):002:0> gem 'ice_cube'
irb(main):003:0> require 'ice_cube'
irb(main):004:0> puts IceCube::VERSION
0.16.3
irb(main):005:0> schedule = IceCube::Schedule.new
=> #<IceCube::Schedule:0x00007ff2fb0d5b88 @start_time=2020-12-27 11:11:02 -0800, @all_recurrence_rules=[], @all_exception_rules=[]>
irb(main):006:0> puts schedule.to_ical
DTSTART;TZID=PST:20201227T111102

Does anyone know where I can start to fix this? We're just starting the project and I am hoping to use Ruby 3

Upvotes: 8

Views: 17513

Answers (1)

Alter Lagos
Alter Lagos

Reputation: 12550

TL;DR: ice_cube 0.16.4 has already sorted out these compatibility problems with ruby 3.x, so just upgrade.


The issue has to do with how keyword arguments are handled in ruby 3.0 and how ice_cube is passing its arguments to I18n.localize.
So, extracting and simplifying the buggy code, this worked on ruby < 3

RUBY_VERSION # "2.7.2"

def foo(*args)
  bar(*args)
end

def bar(object, locale: nil, format: nil, **options)
  puts "object:#{object}"
  puts "locale:#{locale}"
  puts "format:#{format}"
  puts "options:#{options}"
end

foo('date', format: 'whatever')
# object:date
# locale:
# format:whatever
# options:{}

And from ruby >= 3

RUBY_VERSION # "3.0.0"

def foo(*args)
  bar(*args)
end

def bar(object, locale: nil, format: nil, **options)
  puts "object:#{object}"
  puts "locale:#{locale}"
  puts "format:#{format}"
  puts "options:#{options}"
end

foo('date', format: 'whatever')
# Traceback (most recent call last):
#        16: from /Users/alter/.rbenv/versions/3.0.0/lib/ruby/3.0.0/bundler/cli.rb:24:in `start'
#        15: from /Users/alter/.rbenv/versions/3.0.0/lib/ruby/3.0.0/bundler/vendor/thor/lib/thor/base.rb:485:in `start'
#        14: from /Users/alter/.rbenv/versions/3.0.0/lib/ruby/3.0.0/bundler/cli.rb:30:in `dispatch'
#        13: from /Users/alter/.rbenv/versions/3.0.0/lib/ruby/3.0.0/bundler/vendor/thor/lib/thor.rb:392:in `dispatch'
#        12: from /Users/alter/.rbenv/versions/3.0.0/lib/ruby/3.0.0/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
#        11: from /Users/alter/.rbenv/versions/3.0.0/lib/ruby/3.0.0/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
#        10: from /Users/alter/.rbenv/versions/3.0.0/lib/ruby/3.0.0/bundler/cli.rb:497:in `exec'
#         9: from /Users/alter/.rbenv/versions/3.0.0/lib/ruby/3.0.0/bundler/cli/exec.rb:28:in `run'
#         8: from /Users/alter/.rbenv/versions/3.0.0/lib/ruby/3.0.0/bundler/cli/exec.rb:63:in `kernel_load'
#         7: from /Users/alter/.rbenv/versions/3.0.0/lib/ruby/3.0.0/bundler/cli/exec.rb:63:in `load'
#         6: from /Users/alter/.rbenv/versions/3.0.0/bin/irb:23:in `<top (required)>'
#         5: from /Users/alter/.rbenv/versions/3.0.0/bin/irb:23:in `load'
#         4: from /Users/alter/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/irb-1.3.0/exe/irb:11:in `<top (required)>'
#         3: from (irb):11:in `<main>'
#         2: from (irb):3:in `foo'
#         1: from (irb):5:in `bar'
# ArgumentError (wrong number of arguments (given 2, expected 1))

So, the fix I can see is to explicitely passing the parameters to the method:

def foo2(object, **options)
  bar(object, **options)
end

foo2('date', format: 'whatever')
# object:date
# locale:
# format:whatever
# options:{}

Or in terms of the involved module:

module IceCube
  module I18n
    def self.l(object, **options)
      backend.l(object, **options)
    end
  end
end

and send a PR, use your own fork, monkey-patch, whatever works best for you.
But most important, brace yourself to find this issue in a lot of other gems, as the first stable ruby 3 version was just released 2 days ago, so probably you'll have these type of issues with other gems, specially the unmaintained ones. Good luck.

Upvotes: 9

Related Questions