Skip to content

Commit

Permalink
support Ruby class method as handler
Browse files Browse the repository at this point in the history
  • Loading branch information
dholdren committed Dec 4, 2018
1 parent d147db9 commit 4cb9a45
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 9 deletions.
8 changes: 8 additions & 0 deletions lib/plugins/aws/invokeLocal/fixture/handler.rb
Expand Up @@ -5,3 +5,11 @@ def withRemainingTime(event:, context:)

{"start" => start, "stop" => stop}
end

module MyModule
class MyClass
def self.my_class_method(event:, context:)
{"foo" => "bar"}
end
end
end
4 changes: 2 additions & 2 deletions lib/plugins/aws/invokeLocal/index.js
Expand Up @@ -160,8 +160,8 @@ class AwsInvokeLocal {

if (runtime === 'ruby2.5') {
const handlerComponents = handler.split(/\./);
const handlerPath = handlerComponents.slice(0, -1).join('.');
const handlerName = handlerComponents.pop();
const handlerPath = handlerComponents[0];
const handlerName = handlerComponents.slice(1).join('.');
return this.invokeLocalRuby(
process.platform === 'win32' ? 'ruby.exe' : 'ruby',
handlerPath,
Expand Down
38 changes: 38 additions & 0 deletions lib/plugins/aws/invokeLocal/index.test.js
Expand Up @@ -431,6 +431,30 @@ describe('AwsInvokeLocal', () => {
});
});

it('should call invokeLocalRuby with "Module::Class.method" when using a class method in ruby', () => {
awsInvokeLocal.options.functionObj.runtime = 'ruby2.5';
awsInvokeLocal.options = {
function: 'first',
functionObj: {
handler: 'handler.MyModule::MyClass.hello',
name: 'hello',
},
data: {},
};
return awsInvokeLocal.invokeLocal().then(() => {
// NOTE: this is important so that tests on Windows won't fail
const runtime = process.platform === 'win32' ? 'ruby.exe' : 'ruby';
expect(invokeLocalRubyStub.calledOnce).to.be.equal(true);
expect(invokeLocalRubyStub.calledWithExactly(
runtime,
'handler',
'MyModule::MyClass.hello',
{},
undefined
)).to.be.equal(true);
});
});

it('throw error when using runtime other than Node.js, Python, Java or Ruby', () => {
awsInvokeLocal.options.functionObj.runtime = 'invalid-runtime';
expect(() => awsInvokeLocal.invokeLocal()).to.throw(Error);
Expand Down Expand Up @@ -1028,5 +1052,19 @@ describe('AwsInvokeLocal', () => {
});
});
});

describe('calling a class method', () => {
it('should execute', () => {
awsInvokeLocal.serverless.config.servicePath = __dirname;

return awsInvokeLocal.invokeLocalRuby(
'ruby',
'fixture/handler',
'MyModule::MyClass.my_class_method').then(() => {
const result = JSON.parse(serverless.cli.consoleLog.lastCall.args[0]);
expect(result.foo).to.eq('bar');
});
});
});
});
});
16 changes: 9 additions & 7 deletions lib/plugins/aws/invokeLocal/invoke.rb
Expand Up @@ -48,19 +48,21 @@ def log(message)
exit 1
end

handler_path = "#{ARGV[0]}.rb"
handler_path = ARGV[0]
handler_name = ARGV[1]

# handler name is either a global method or a static method in a class
# my_method or MyModule::MyClass.my_method
input = JSON.load($stdin) || {}

$LOAD_PATH << "."
$LOAD_PATH << "lib"
load(handler_path)
handler = method(handler_name)
require(handler_path)

# handler name is either a global method or a static method in a class
# my_method or MyModule::MyClass.my_method
handler_method, handler_class = handler_name.split(".").reverse
handler_class ||= "Kernel"

context = FakeLambdaContext.new(**input.fetch('context', {}))
result = handler.call(event: input['event'], context: context)
result = Object.const_get(handler_class).send(handler_method, event: input['event'], context: context)

puts result.to_json
end

0 comments on commit 4cb9a45

Please sign in to comment.