Skip to content

Commit

Permalink
Deal with kwargs
Browse files Browse the repository at this point in the history
Ruby 3 has started to separate args and kwargs.
  • Loading branch information
ekohl committed Oct 13, 2022
1 parent 6ff8f94 commit fa062f4
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 10 deletions.
4 changes: 2 additions & 2 deletions lib/safemode/jail.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def to_s
@source.to_s
end

def method_missing(method, *args, &block)
def method_missing(method, *args, **kwargs, &block)
if @source.is_a?(Class)
unless self.class.allowed_class_method?(method)
raise Safemode::NoMethodError.new(".#{method}", self.class.name, @source.name)
Expand All @@ -28,7 +28,7 @@ def method_missing(method, *args, &block)
# don't need to jail objects returned from a jail. Doing so would provide
# "double" protection, but it also would break using a return value in an if
# statement, passing them to a Rails helper etc.
@source.send(method, *args, &block)
@source.send(method, *args, **kwargs, &block)
end

def respond_to_missing?(method_name, include_private = false)
Expand Down
16 changes: 11 additions & 5 deletions lib/safemode/scope.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ def output
@_safemode_output
end

def method_missing(method, *args, &block)
def method_missing(method, *args, **kwargs, &block)
if @locals.has_key?(method)
@locals[method]
elsif @delegate_methods.include?(method)
@delegate.send method, *unjail_args(args), &block
@delegate.send method, *unjail_args(args), **unjail_kwargs(kwargs), &block
else
raise Safemode::SecurityError.new(method, "#<Safemode::ScopeObject>")
end
Expand All @@ -49,10 +49,16 @@ def symbolize_keys(hash)
end
end

def unjail(arg)
arg.class.name.end_with?('::Jail') ? arg.instance_variable_get(:@source) : arg
end

def unjail_args(args)
args.collect do |arg|
arg.class.name =~ /::Jail$/ ? arg.instance_variable_get(:@source) : arg
end
args.collect { |arg| unjail(arg) }
end

def unjail_kwargs(kwargs)
kwargs.map { |key, value| [unjail(key), unjail(value)] }.to_h
end
end
end
10 changes: 7 additions & 3 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,12 @@ def comment_class
Comment
end

def method_missing(method, *args, &block)
super(method, *args, &block)
def method_with_kwargs(a_keyword: false)
a_keyword
end

def method_missing(method, *args, **kwargs, &block)
super
end
end

Expand Down Expand Up @@ -144,7 +148,7 @@ def self.destroy_all
end

class Article::Jail < Safemode::Jail
allow :title, :comments, :is_article?, :comment_class
allow :title, :comments, :is_article?, :comment_class, :method_with_kwargs

def author_name
"this article's author name"
Expand Down
10 changes: 10 additions & 0 deletions test/test_jail.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ def test_sending_to_jail_to_an_object_should_return_a_jail
assert_equal "Article::Jail", @article.class.name
end

def test_sending_of_kwargs_works
assert @article.method_with_kwargs(a_keyword: true)
end

def test_sending_to_method_missing
assert_raise_with_message(Safemode::NoMethodError, /#no_such_method/) do
@article.no_such_method('arg', key: 'value')
end
end

def test_jail_instances_should_have_limited_methods
expected = ["class", "method_missing", "methods", "respond_to?", "to_jail", "to_s", "instance_variable_get"]
objects.each do |object|
Expand Down

0 comments on commit fa062f4

Please sign in to comment.