Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for named parameters #4

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions lib/jsonrpc/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,25 @@ def self.decode_options
@decode_options = {}

class Helper
NAMED = :named
POSITIONAL = :positional

def initialize(options)
@options = options
@options[:content_type] ||= 'application/json'
@params_type = POSITIONAL
@params_type = NAMED if @options.delete(:named_params) == true
@connection = @options.delete(:connection)
end

def positional_params?
@params_type == POSITIONAL
end

def named_params?
@params_type == NAMED
end

def options(additional_options = nil)
if additional_options
additional_options.merge(@options)
Expand Down Expand Up @@ -91,7 +104,11 @@ def initialize(url, opts = {})

def method_missing(sym, *args, &block)
if @alive
request = ::JSONRPC::Request.new(sym.to_s, args)
if @helper.named_params? && args.first.is_a?(::Hash)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to check for the args.size == 1, because it can be [{foo: 'bar'}, 2]

request = ::JSONRPC::Request.new(sym.to_s, *args)
else
request = ::JSONRPC::Request.new(sym.to_s, args)
end
push_batch_request(request)
else
super
Expand Down Expand Up @@ -141,7 +158,11 @@ def send_batch

class Client < Base
def method_missing(method, *args, &block)
invoke(method, args)
if @helper.named_params? && args.first.is_a?(::Hash)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

invoke(method, *args)
else
invoke(method, args)
end
end

def invoke(method, args, options = nil)
Expand Down
146 changes: 110 additions & 36 deletions spec/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,51 +88,125 @@ module JSONRPC
client.foo(1,2,3).should == 42
end
end
context "when using named parameters" do
before(:each) do
@expected = MultiJson.encode({
'jsonrpc' => '2.0',
'method' => 'foo',
'params' => {:p1 => 1, :p2 => 2, :p3 => 3},
'id' => 1
})
end
it "sends a valid JSON-RPC request and returns the result" do
response = MultiJson.encode(BOILERPLATE.merge({'result' => 42}))
connection.should_receive(:post).with(SPEC_URL, @expected, {:content_type => 'application/json'}).and_return(@resp_mock)
@resp_mock.should_receive(:body).at_least(:once).and_return(response)
client = Client.new(SPEC_URL, :connection => connection, :named_params => true)
result = client.foo({:p1 => 1, :p2 => 2, :p3 => 3})
result.should == 42
end
end
end

describe "sending a batch request" do
it "sends a valid JSON-RPC batch request and puts the results in the response objects" do
batch = MultiJson.encode([
{"jsonrpc" => "2.0", "method" => "sum", "params" => [1,2,4], "id" => "1"},
{"jsonrpc" => "2.0", "method" => "subtract", "params" => [42,23], "id" => "2"},
{"jsonrpc" => "2.0", "method" => "foo_get", "params" => [{"name" => "myself"}], "id" => "5"},
{"jsonrpc" => "2.0", "method" => "get_data", "id" => "9"}
])

response = MultiJson.encode([
{"jsonrpc" => "2.0", "result" => 7, "id" => "1"},
{"jsonrpc" => "2.0", "result" => 19, "id" => "2"},
{"jsonrpc" => "2.0", "error" => {"code" => -32601, "message" => "Method not found."}, "id" => "5"},
{"jsonrpc" => "2.0", "result" => ["hello", 5], "id" => "9"}
])

Base.stub(:make_id).and_return('1', '2', '5', '9')
connection.should_receive(:post).with(SPEC_URL, batch, {:content_type => 'application/json'}).and_return(@resp_mock)
@resp_mock.should_receive(:body).at_least(:once).and_return(response)
client = Client.new(SPEC_URL, :connection => connection)

sum = subtract = foo = data = nil
client = BatchClient.new(SPEC_URL, :connection => connection) do |batch|
sum = batch.sum(1,2,4)
subtract = batch.subtract(42,23)
foo = batch.foo_get('name' => 'myself')
data = batch.get_data
end
context "when using positional parameters" do
it "sends a valid JSON-RPC batch request and puts the results in the response objects" do
batch = MultiJson.encode([
{"jsonrpc" => "2.0", "method" => "sum", "params" => [1,2,4], "id" => "1"},
{"jsonrpc" => "2.0", "method" => "subtract", "params" => [42,23], "id" => "2"},
{"jsonrpc" => "2.0", "method" => "foo_get", "params" => [{"name" => "myself"}], "id" => "5"},
{"jsonrpc" => "2.0", "method" => "get_data", "id" => "9"}
])

response = MultiJson.encode([
{"jsonrpc" => "2.0", "result" => 7, "id" => "1"},
{"jsonrpc" => "2.0", "result" => 19, "id" => "2"},
{"jsonrpc" => "2.0", "error" => {"code" => -32601, "message" => "Method not found."}, "id" => "5"},
{"jsonrpc" => "2.0", "result" => ["hello", 5], "id" => "9"}
])

Base.stub(:make_id).and_return('1', '2', '5', '9')
connection.should_receive(:post).with(SPEC_URL, batch, {:content_type => 'application/json'}).and_return(@resp_mock)
@resp_mock.should_receive(:body).at_least(:once).and_return(response)
client = Client.new(SPEC_URL, :connection => connection)

sum = subtract = foo = data = nil
client = BatchClient.new(SPEC_URL, :connection => connection) do |batch|
sum = batch.sum(1,2,4)
subtract = batch.subtract(42,23)
foo = batch.foo_get('name' => 'myself')
data = batch.get_data
end

sum.succeeded?.should be_true
sum.is_error?.should be_false
sum.result.should == 7
sum.succeeded?.should be_true
sum.is_error?.should be_false
sum.result.should == 7

subtract.result.should == 19
subtract.result.should == 19

foo.is_error?.should be_true
foo.succeeded?.should be_false
foo.error['code'].should == -32601
foo.is_error?.should be_true
foo.succeeded?.should be_false
foo.error['code'].should == -32601

data.result.should == ['hello', 5]
data.result.should == ['hello', 5]


expect { client.sum(1, 2) }.to raise_error(NoMethodError)
expect { client.sum(1, 2) }.to raise_error(NoMethodError)
end
context "when using named parameters" do
it "sends a valid JSON-RPC batch request and puts the results in the response objects" do
batch = MultiJson.encode([
{"jsonrpc" => "2.0", "method" => "sum", "params" => [1,2,4], "id" => "1"},
{"jsonrpc" => "2.0", "method" => "subtract", "params" => [42,23], "id" => "2"},
{"jsonrpc" => "2.0", "method" => "hello", "params" => ['world'], "id" => "3"},
{"jsonrpc" => "2.0", "method" => "foo_get", "params" => {"name" => "myself"}, "id" => "5"},
{"jsonrpc" => "2.0", "method" => "foo", "params" => [[1,2,3]], "id" => "7"},
{"jsonrpc" => "2.0", "method" => "foo", "params" => {:some => { :nested => :hash }}, "id" => "8"},
{"jsonrpc" => "2.0", "method" => "get_data", "id" => "9"}
])

response = MultiJson.encode([
{"jsonrpc" => "2.0", "result" => 7, "id" => "1"},
{"jsonrpc" => "2.0", "result" => 19, "id" => "2"},
{"jsonrpc" => "2.0", "result" => 'world', "id" => "3"},
{"jsonrpc" => "2.0", "error" => {"code" => -32601, "message" => "Method not found."}, "id" => "5"},
{"jsonrpc" => "2.0", "result" => [2,4,6], "id" => "7"},
{"jsonrpc" => "2.0", "result" => "I can handle this!", "id" => "8"},
{"jsonrpc" => "2.0", "result" => ["hello", 5], "id" => "9"}
])

Base.stub(:make_id).and_return('1', '2', '3', '5', '7', '8', '9')
connection.should_receive(:post).with(SPEC_URL, batch, {:content_type => 'application/json'}).and_return(@resp_mock)
@resp_mock.should_receive(:body).at_least(:once).and_return(response)
client = Client.new(SPEC_URL, :connection => connection)

sum = subtract = foo = data = nil
client = BatchClient.new(SPEC_URL, :connection => connection, :named_params => true) do |batch|
sum = batch.sum(1,2,4)
subtract = batch.subtract(42,23)
str = batch.hello('world')
foo = batch.foo_get('name' => 'myself')
arr = batch.foo([1,2,3])
nested = batch.foo({:some => { :nested => :hash }})
data = batch.get_data
end

sum.succeeded?.should be_true
sum.is_error?.should be_false
sum.result.should == 7

subtract.result.should == 19

foo.is_error?.should be_true
foo.succeeded?.should be_false
foo.error['code'].should == -32601

data.result.should == ['hello', 5]


expect { client.sum(1, 2) }.to raise_error(NoMethodError)
end
end
end
end

Expand Down