7

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

Alter Lagos
  • 12,090
  • 1
  • 70
  • 92
vince
  • 2,374
  • 4
  • 23
  • 39

1 Answers1

9

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.

Alter Lagos
  • 12,090
  • 1
  • 70
  • 92
  • I forked the project to https://github.com/sthapit/ice_cube -- could you let me know what I should put in ice_cube/lib/ice_cube/i18n.rb to get this to work? This is a fairly popular gem so I assume it will be useful for many people – vince Dec 29 '20 at 00:45
  • Check the changes I put in `self.l` method and apply them in your fork – Alter Lagos Dec 29 '20 at 10:52
  • I removed the delegated localize method and added your code and it works great https://github.com/sthapit/ice_cube/blob/master/lib/ice_cube/i18n.rb -- before I send a PR does something similar also need to be done for the translate method that was being delegated together with localize? – vince Dec 30 '20 at 00:26
  • that works!! thank you so much -- I have accepted the answer and we'll also be using the master branch – vince Dec 30 '20 at 18:20
  • I wish I understood any of this. So confusing. – user24601 Feb 20 '23 at 20:44