Skip to content

Commit 6cc7001

Browse files
MONGOID-5123 Fix methods incompatible with Ruby 3 (#5015)
1 parent dfc2be2 commit 6cc7001

File tree

13 files changed

+71
-11
lines changed

13 files changed

+71
-11
lines changed

lib/mongoid.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
require "forwardable"
77
require "time"
88
require "set"
9+
require "ruby2_keywords"
910

1011
require "active_support"
1112
require "active_support/core_ext"

lib/mongoid/association/embedded/embeds_many/proxy.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ def integrate(document)
422422
# @param [ Proc ] block Optional block to pass.
423423
#
424424
# @return [ Criteria, Object ] A Criteria or return value from the target.
425-
def method_missing(name, *args, &block)
425+
ruby2_keywords def method_missing(name, *args, &block)
426426
return super if _target.respond_to?(name)
427427
klass.send(:with_scope, criteria) do
428428
criteria.public_send(name, *args, &block)

lib/mongoid/association/proxy.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,12 +133,12 @@ def characterize_one(document)
133133
# @param [ String, Symbol ] name The name of the method.
134134
# @param [ Array ] args The arguments passed to the method.
135135
#
136-
def method_missing(name, *args, &block)
136+
ruby2_keywords def method_missing(name, *args, &block)
137137
_target.send(name, *args, &block)
138138
end
139139

140140
# @api private
141-
def respond_to_missing?(name, *args)
141+
ruby2_keywords def respond_to_missing?(name, *args)
142142
_target.respond_to?(name, *args)
143143
end
144144

lib/mongoid/association/referenced/has_many/enumerable.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ def set_base(document)
532532
end
533533
end
534534

535-
def method_missing(name, *args, &block)
535+
ruby2_keywords def method_missing(name, *args, &block)
536536
entries.send(name, *args, &block)
537537
end
538538

lib/mongoid/association/referenced/has_many/proxy.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ def cascade!(document)
443443
# @return [ Criteria, Object ] A Criteria or return value from the target.
444444
#
445445
# @since 2.0.0.beta.1
446-
def method_missing(name, *args, &block)
446+
ruby2_keywords def method_missing(name, *args, &block)
447447
if _target.respond_to?(name)
448448
_target.send(name, *args, &block)
449449
else

lib/mongoid/criteria.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ def initialize_copy(other)
567567
# @return [ Object ] The result of the method call.
568568
#
569569
# @since 1.0.0
570-
def method_missing(name, *args, &block)
570+
ruby2_keywords def method_missing(name, *args, &block)
571571
if klass.respond_to?(name)
572572
klass.send(:with_scope, self) do
573573
klass.send(name, *args, &block)

lib/mongoid/interceptable.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ def run_before_callbacks(*kinds)
125125
# @return [ Document ] The document
126126
#
127127
# @since 2.3.0
128-
def run_callbacks(kind, *args, &block)
128+
ruby2_keywords def run_callbacks(kind, *args, &block)
129129
cascadable_children(kind).each do |child|
130130
if child.run_callbacks(child_callback_type(kind, child), *args) == false
131131
return false

mongoid.gemspec

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,18 @@ Gem::Specification.new do |s|
3838
s.add_dependency("activemodel", [">=6.0", "<6.2"])
3939
end
4040
s.add_dependency("mongo", ['>=2.10.5', '<3.0.0'])
41+
# Using this gem is recommended for handling argument delegation issues,
42+
# especially if support for 2.6 or prior is required.
43+
# See https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/#delegation
44+
#
45+
# We have a bunch of complex delegation logic, including various method_missngs.
46+
# If we try to fix them "right", it will add too much logic. We will have to
47+
# handle different Ruby versions (including minor ones, Ruby 2.6 and 2.7
48+
# behave differently), hash key types (strings vs symbols), ways of passing
49+
# arguments (with curly braces vs without ones).
50+
#
51+
# Therefore, usage of this gem looks like a reasonable solution at the moment.
52+
s.add_dependency("ruby2_keywords", "~> 0.0.5")
4153

4254
s.add_development_dependency("bson", ['>=4.9.4', '<5.0.0'])
4355

spec/mongoid/association/embedded/embeds_many/proxy_spec.rb

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2449,13 +2449,26 @@ class TrackingIdValidationHistory
24492449
end
24502450

24512451
context "when providing a criteria class method" do
2452+
context "without keyword arguments" do
24522453

2453-
let(:addresses) do
2454-
person.addresses.california
2454+
let(:addresses) do
2455+
person.addresses.california
2456+
end
2457+
2458+
it "applies the criteria to the documents" do
2459+
expect(addresses).to eq([ address_one ])
2460+
end
24552461
end
24562462

2457-
it "applies the criteria to the documents" do
2458-
expect(addresses).to eq([ address_one ])
2463+
context "with keyword arguments" do
2464+
2465+
let(:addresses) do
2466+
person.addresses.city_and_state(city: "Sacramento", state: "CA")
2467+
end
2468+
2469+
it "applies the criteria to the documents" do
2470+
expect(addresses).to eq([])
2471+
end
24592472
end
24602473
end
24612474

spec/mongoid/association/referenced/belongs_to/proxy_spec.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,4 +1349,21 @@ class C
13491349
end
13501350
end
13511351
end
1352+
1353+
describe "#method_missing" do
1354+
let!(:person) do
1355+
Person.create
1356+
end
1357+
1358+
let!(:game) do
1359+
Game.create(person: person)
1360+
end
1361+
1362+
it 'handles keyword args' do
1363+
expect do
1364+
game.person.set_personal_data(ssn: '123', age: 25)
1365+
end.not_to raise_error
1366+
end
1367+
1368+
end
13521369
end

0 commit comments

Comments
 (0)