active_rest_client 0.9.58

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/.simplecov +4 -0
  5. data/Gemfile +4 -0
  6. data/Guardfile +9 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +585 -0
  9. data/Rakefile +3 -0
  10. data/active_rest_client.gemspec +34 -0
  11. data/lib/active_rest_client.rb +23 -0
  12. data/lib/active_rest_client/base.rb +128 -0
  13. data/lib/active_rest_client/caching.rb +84 -0
  14. data/lib/active_rest_client/configuration.rb +69 -0
  15. data/lib/active_rest_client/connection.rb +76 -0
  16. data/lib/active_rest_client/connection_manager.rb +21 -0
  17. data/lib/active_rest_client/headers_list.rb +47 -0
  18. data/lib/active_rest_client/instrumentation.rb +62 -0
  19. data/lib/active_rest_client/lazy_association_loader.rb +95 -0
  20. data/lib/active_rest_client/lazy_loader.rb +23 -0
  21. data/lib/active_rest_client/logger.rb +67 -0
  22. data/lib/active_rest_client/mapping.rb +65 -0
  23. data/lib/active_rest_client/proxy_base.rb +143 -0
  24. data/lib/active_rest_client/recording.rb +24 -0
  25. data/lib/active_rest_client/request.rb +412 -0
  26. data/lib/active_rest_client/request_filtering.rb +52 -0
  27. data/lib/active_rest_client/result_iterator.rb +66 -0
  28. data/lib/active_rest_client/validation.rb +60 -0
  29. data/lib/active_rest_client/version.rb +3 -0
  30. data/spec/lib/base_spec.rb +245 -0
  31. data/spec/lib/caching_spec.rb +179 -0
  32. data/spec/lib/configuration_spec.rb +105 -0
  33. data/spec/lib/connection_manager_spec.rb +36 -0
  34. data/spec/lib/connection_spec.rb +73 -0
  35. data/spec/lib/headers_list_spec.rb +61 -0
  36. data/spec/lib/instrumentation_spec.rb +59 -0
  37. data/spec/lib/lazy_association_loader_spec.rb +118 -0
  38. data/spec/lib/lazy_loader_spec.rb +25 -0
  39. data/spec/lib/logger_spec.rb +63 -0
  40. data/spec/lib/mapping_spec.rb +48 -0
  41. data/spec/lib/proxy_spec.rb +154 -0
  42. data/spec/lib/recording_spec.rb +34 -0
  43. data/spec/lib/request_filtering_spec.rb +72 -0
  44. data/spec/lib/request_spec.rb +471 -0
  45. data/spec/lib/result_iterator_spec.rb +104 -0
  46. data/spec/lib/validation_spec.rb +113 -0
  47. data/spec/spec_helper.rb +22 -0
  48. metadata +265 -0
@@ -0,0 +1,105 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveRestClient::Configuration do
4
+ before :each do
5
+ Object.send(:remove_const, :ConfigurationExample) if defined?(ConfigurationExample)
6
+ ActiveRestClient::Base._reset_configuration!
7
+
8
+ class ConfigurationExample
9
+ include ActiveRestClient::Configuration
10
+ base_url "http://www.example.com"
11
+ end
12
+
13
+ class ConfigurationExampleBare
14
+ include ActiveRestClient::Configuration
15
+ end
16
+ end
17
+
18
+ it "should default to non-whiny missing methods" do
19
+ class UnusuedConfigurationExample1
20
+ include ActiveRestClient::Configuration
21
+ end
22
+ expect(UnusuedConfigurationExample1.whiny_missing).to be_false
23
+ end
24
+
25
+ it "should allow whiny missing methods to be enabled" do
26
+ ConfigurationExample.whiny_missing true
27
+ expect(ConfigurationExample.whiny_missing).to be_true
28
+ end
29
+
30
+ it "should remember the set base_url" do
31
+ expect(ConfigurationExample.base_url).to eq("http://www.example.com")
32
+ end
33
+
34
+ it "should remember the set base_url on a class, overriding a general one" do
35
+ ActiveRestClient::Base.base_url = "http://general.example.com"
36
+ expect(ConfigurationExample.base_url).to eq("http://www.example.com")
37
+ end
38
+
39
+ it "should remove a trailing slash from a globally configured base_url" do
40
+ ActiveRestClient::Base.base_url = "http://general.example.com/"
41
+ expect(ConfigurationExample.base_url).to eq("http://www.example.com")
42
+ end
43
+
44
+ it "should remember the set base_url on the base class if a more specific one hasn't been set" do
45
+ ActiveRestClient::Base.base_url = "http://general.example.com"
46
+ expect(ConfigurationExampleBare.base_url).to eq("http://general.example.com")
47
+ end
48
+
49
+ it "should remove a trailing slash from a specific class configured base_url" do
50
+ class ConfigurationExample2
51
+ include ActiveRestClient::Configuration
52
+ base_url "http://specific.example.com/"
53
+ end
54
+ expect(ConfigurationExample2.base_url).to eq("http://specific.example.com")
55
+ end
56
+
57
+ it "should default to non-lazy loading" do
58
+ class LazyLoadingConfigurationExample1
59
+ include ActiveRestClient::Configuration
60
+ end
61
+ expect(LazyLoadingConfigurationExample1.lazy_load?).to be_false
62
+ end
63
+
64
+ it "should be able to switch on lazy loading" do
65
+ class LazyLoadingConfigurationExample2
66
+ include ActiveRestClient::Configuration
67
+ lazy_load!
68
+ end
69
+ expect(LazyLoadingConfigurationExample2.lazy_load?).to be_true
70
+ end
71
+
72
+ it "should default to non-verbose loggingg" do
73
+ class VerboseConfigurationExample1
74
+ include ActiveRestClient::Configuration
75
+ end
76
+ expect(VerboseConfigurationExample1.verbose).to be_false
77
+ end
78
+
79
+ it "should be able to switch on verbose logging" do
80
+ class VerboseConfigurationExample2
81
+ include ActiveRestClient::Configuration
82
+ verbose!
83
+ end
84
+ class VerboseConfigurationExample3
85
+ include ActiveRestClient::Configuration
86
+ verbose true
87
+ end
88
+ expect(VerboseConfigurationExample2.verbose).to be_true
89
+ expect(VerboseConfigurationExample3.verbose).to be_true
90
+ end
91
+
92
+ it "should store a translator given" do
93
+ expect{ ConfigurationExample.send(:translator) }.to_not raise_error
94
+ ConfigurationExample.send(:translator, String)
95
+ expect{ ConfigurationExample.translator.respond_to?(:length) }.to be_true
96
+ end
97
+
98
+ it "should store a proxy given" do
99
+ expect{ ConfigurationExample.send(:proxy) }.to_not raise_error
100
+ ConfigurationExample.send(:proxy, String)
101
+ expect{ ConfigurationExample.proxy.respond_to?(:length) }.to be_true
102
+ end
103
+
104
+
105
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveRestClient::ConnectionManager do
4
+ before(:each) do
5
+ ActiveRestClient::ConnectionManager.reset!
6
+ end
7
+
8
+ it "should have a get_connection method" do
9
+ expect(ActiveRestClient::ConnectionManager).to respond_to("get_connection")
10
+ end
11
+
12
+ it "should return a connection for a given base url" do
13
+ connection = ActiveRestClient::ConnectionManager.get_connection("http://www.example.com")
14
+ expect(connection).to be_kind_of(ActiveRestClient::Connection)
15
+ end
16
+
17
+ it "should return the same connection for each base url when re-requested" do
18
+ connection = ActiveRestClient::ConnectionManager.get_connection("http://www.example.com")
19
+ expect(ActiveRestClient::ConnectionManager.get_connection("http://www.example.com")).to eq(connection)
20
+ end
21
+
22
+ it "should return different connections for each base url when requested" do
23
+ base_url = "http://www.example.com"
24
+ other_base_url = "http://other.example.com"
25
+ expect(ActiveRestClient::ConnectionManager.get_connection(base_url).base_url).to eq(base_url)
26
+ expect(ActiveRestClient::ConnectionManager.get_connection(other_base_url).base_url).to eq(other_base_url)
27
+ expect(ActiveRestClient::ConnectionManager.instance_variable_get(:@_connections).size).to eq(2)
28
+ end
29
+
30
+ it "should find a connection if you pass in URLs containing an existing connection's base_url" do
31
+ base_url = "http://www.example.com"
32
+ connection = ActiveRestClient::ConnectionManager.get_connection(base_url)
33
+ found_connection = ActiveRestClient::ConnectionManager.find_connection_for_url("#{base_url}:8080/people/test")
34
+ expect(found_connection).to eq(connection)
35
+ end
36
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveRestClient::Connection do
4
+ before(:each) do
5
+ @connection = ActiveRestClient::Connection.new("http://www.example.com")
6
+ end
7
+
8
+ it "should contain a patron session" do
9
+ expect(@connection.session).to be_a_kind_of(Patron::Session)
10
+ end
11
+
12
+ it "should set the Base URL for Patron to be the one passed in" do
13
+ expect(@connection.session.base_url).to eq("http://www.example.com")
14
+ end
15
+
16
+ it "should set a user agent for the Patron session" do
17
+ expect(@connection.headers["User-Agent"]).to match(/^ActiveRestClient\/[0-9.]+$/)
18
+ end
19
+
20
+ it "should try to Keep-Alive Patron session connections" do
21
+ expect(@connection.headers["Connection"]).to match(/Keep-Alive/)
22
+ end
23
+
24
+ it "should pass a GET request through to Patron" do
25
+ @connection.session = double(Patron::Session)
26
+ @connection.session.stub(:get).with("/foo", {}).and_return(OpenStruct.new(body:"{result:true}"))
27
+ result = @connection.get("/foo")
28
+ expect(result.body).to eq("{result:true}")
29
+ end
30
+
31
+ it "should pass a PUT request through to Patron" do
32
+ @connection.session = double(Patron::Session)
33
+ @connection.session.stub(:put).with("/foo", "body", {}).and_return(OpenStruct.new(body:"{result:true}"))
34
+ result = @connection.put("/foo", "body")
35
+ expect(result.body).to eq("{result:true}")
36
+ end
37
+
38
+ it "should pass a POST request through to Patron" do
39
+ @connection.session = double(Patron::Session)
40
+ @connection.session.stub(:post).with("/foo", "body", {}).and_return(OpenStruct.new(body:"{result:true}"))
41
+ result = @connection.post("/foo", "body")
42
+ expect(result.body).to eq("{result:true}")
43
+ end
44
+
45
+ it "should pass a DELETE request through to Patron" do
46
+ @connection.session = double(Patron::Session)
47
+ @connection.session.stub(:delete).with("/foo", {}).and_return(OpenStruct.new(body:"{result:true}"))
48
+ result = @connection.delete("/foo")
49
+ expect(result.body).to eq("{result:true}")
50
+ end
51
+
52
+ it "should retry once in the event of a connection failed" do
53
+ @times_called = 0
54
+ Patron::Session.any_instance.stub(:get).and_return do
55
+ raise Patron::ConnectionFailed.new("Foo") if (@times_called += 1) == 1
56
+ end
57
+ expect { @connection.get("/foo") }.to_not raise_error
58
+ end
59
+
60
+ it "should not retry more than once in the event of a connection failed" do
61
+ @times_called = 0
62
+ Patron::Session.any_instance.stub(:get).and_return do
63
+ raise Patron::ConnectionFailed.new("Foo")
64
+ end
65
+ expect { @connection.get("/foo") }.to raise_error(ActiveRestClient::ConnectionFailedException)
66
+ end
67
+
68
+ it "should raise an exception on timeout" do
69
+ Patron::Session.any_instance.stub(:get).and_raise Patron::TimeoutError.new("Foo")
70
+ expect { @connection.get("/foo") }.to raise_error(ActiveRestClient::TimeoutException)
71
+ end
72
+
73
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveRestClient::HeadersList do
4
+ let(:headers_list) { ActiveRestClient::HeadersList.new }
5
+
6
+ it "should remember stored headers" do
7
+ url = "http://www.google.com"
8
+ headers_list["X-My-Header"] = url
9
+ expect(headers_list["X-My-Header"]).to eq(url)
10
+ end
11
+
12
+ it "should remember overwrite normal headers" do
13
+ url = "http://www.google.com"
14
+ headers_list["X-My-Header"] = "SHOULD NEVER BE SEEN"
15
+ headers_list["X-My-Header"] = url
16
+ expect(headers_list["X-My-Header"]).to eq(url)
17
+ end
18
+
19
+ it "should append to specific headers, such as Set-cookie" do
20
+ headers_list["Set-Cookie"] = "first_value"
21
+ headers_list["Set-Cookie"] = "second_value"
22
+ expect(headers_list["Set-Cookie"]).to eq(%w{first_value second_value})
23
+ end
24
+
25
+ it "should not be case sensitive on header names when setting headers" do
26
+ url = "http://www.google.com"
27
+ headers_list["X-My-Header"] = "SHOULD NEVER BE SEEN"
28
+ headers_list["X-MY-HEADER"] = url
29
+ expect(headers_list["X-My-Header"]).to eq(url)
30
+ end
31
+
32
+ it "should not be case sensitive on header names when getting headers" do
33
+ url = "http://www.google.com"
34
+ headers_list["X-My-Header"] = url
35
+ expect(headers_list["X-MY-HEADER"]).to eq(url)
36
+ end
37
+
38
+ it "should allow iterating over headers set, by default with array items returned whole" do
39
+ headers_list["X-My-Header"] = "http://www.google.com"
40
+ headers_list["Set-Cookie"] = "first_value"
41
+ headers_list["SET-COOKIE"] = "second_value"
42
+ values = []
43
+ headers_list.each do |name, value|
44
+ values << "#{name}=#{value.to_s}"
45
+ end
46
+ expect(values.size).to eq(2)
47
+ expect(values).to eq(["X-My-Header=http://www.google.com", "Set-Cookie=[\"first_value\", \"second_value\"]"])
48
+ end
49
+
50
+ it "should allow iterating over headers set splitting array headers in to individual ones" do
51
+ headers_list["X-My-Header"] = "http://www.google.com"
52
+ headers_list["Set-Cookie"] = "first_value"
53
+ headers_list["SET-COOKIE"] = "second_value"
54
+ values = []
55
+ headers_list.each(true) do |name, value|
56
+ values << "#{name}=#{value.to_s}"
57
+ end
58
+ expect(values.size).to eq(3)
59
+ expect(values).to eq(["X-My-Header=http://www.google.com", "Set-Cookie=first_value", "Set-Cookie=second_value"])
60
+ end
61
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ class InstrumentationExampleClient < ActiveRestClient::Base
4
+ base_url "http://www.example.com"
5
+ get :fake, "/fake", fake:"{\"result\":true, \"list\":[1,2,3,{\"test\":true}], \"child\":{\"grandchild\":{\"test\":true}}}"
6
+ get :real, "/real"
7
+ end
8
+
9
+ describe ActiveRestClient::Instrumentation do
10
+ it "should save a load hook to include the instrumentation" do
11
+ hook_tester = double("HookTester")
12
+ hook_tester.should_receive(:include).with(ActiveRestClient::ControllerInstrumentation)
13
+ ActiveSupport.run_load_hooks(:action_controller, hook_tester)
14
+ end
15
+
16
+ it "should call ActiveSupport::Notifications.instrument when making any request" do
17
+ ActiveSupport::Notifications.should_receive(:instrument).with("request_call.active_rest_client", {:name=>"InstrumentationExampleClient#fake"})
18
+ InstrumentationExampleClient.fake
19
+ end
20
+
21
+ it "should call ActiveSupport::Notifications#request_call when making any request" do
22
+ ActiveRestClient::Instrumentation.any_instance.should_receive(:request_call).with(an_instance_of(ActiveSupport::Notifications::Event))
23
+ InstrumentationExampleClient.fake
24
+ end
25
+
26
+
27
+ it "should log time spent in each API call" do
28
+ ActiveRestClient::Connection.
29
+ any_instance.
30
+ should_receive(:get).
31
+ with("/real", an_instance_of(Hash)).
32
+ and_return(OpenStruct.new(body:"{\"first_name\":\"John\", \"id\":1234}", headers:{}, status:200))
33
+ ActiveRestClient::Logger.should_receive(:debug).with {|*args| args.first[/ActiveRestClient.*ms\)/]}
34
+ ActiveRestClient::Logger.should_receive(:debug).at_least(:once).with(any_args)
35
+ InstrumentationExampleClient.real
36
+ end
37
+
38
+
39
+ it "should report the total time spent" do
40
+ # Create a couple of classes to fake being part of ActionController (that would normally call this method)
41
+ class InstrumentationTimeSpentExampleClientParent
42
+ def append_info_to_payload(payload) ; {} ; end
43
+ def self.log_process_action(payload) ; [] ; end
44
+ end
45
+
46
+ class InstrumentationTimeSpentExampleClient < InstrumentationTimeSpentExampleClientParent
47
+ include ActiveRestClient::ControllerInstrumentation
48
+
49
+ def test
50
+ payload = {}
51
+ append_info_to_payload(payload)
52
+ self.class.log_process_action(payload)
53
+ end
54
+ end
55
+
56
+ messages = InstrumentationTimeSpentExampleClient.new.test
57
+ expect(messages.first).to match(/ActiveRestClient.*ms.*call/)
58
+ end
59
+ end
@@ -0,0 +1,118 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveRestClient::LazyAssociationLoader do
4
+ let(:url1) { "http://www.example.com/some/url" }
5
+ let(:url2) { "http://www.example.com/some/other" }
6
+ let(:calling_object) { o = double("Object").as_null_object }
7
+ let(:request) { ActiveRestClient::Request.new({:method => :get, url:"http://api.example.com/v1/foo"}, calling_object) }
8
+
9
+ it "should raise an exception if you initialize it with a value that is not a string, hash or array" do
10
+ expect do
11
+ ActiveRestClient::LazyAssociationLoader.new(:person, OpenStruct.new, nil)
12
+ end.to raise_error(ActiveRestClient::InvalidLazyAssociationContentException)
13
+ end
14
+
15
+ it "should store a URL passed as a string to the new object during creation" do
16
+ loader = ActiveRestClient::LazyAssociationLoader.new(:person, url1, nil)
17
+ expect(loader.instance_variable_get(:@url)).to eq(url1)
18
+ end
19
+
20
+ it "should store a URL from a hash passed to the new object during creation" do
21
+ loader = ActiveRestClient::LazyAssociationLoader.new(:person, {"url" => url1}, nil)
22
+ expect(loader.instance_variable_get(:@url)).to eq(url1)
23
+ end
24
+
25
+ it "should store a list of URLs from an array passed to the new object during creation" do
26
+ loader = ActiveRestClient::LazyAssociationLoader.new(:person, [url1, url2], nil)
27
+ array = loader.instance_variable_get(:@subloaders)
28
+ expect(array[0].instance_variable_get(:@url)).to eq(url1)
29
+ expect(array[1].instance_variable_get(:@url)).to eq(url2)
30
+ expect(array[2]).to be_nil
31
+ end
32
+
33
+ it "should store a hash of URLs from a hash passed to the new object during creation" do
34
+ loader = ActiveRestClient::LazyAssociationLoader.new(:person, {"main" => url1, "thumb" => url2}, request)
35
+ expect(loader.main.instance_variable_get(:@url)).to eq(url1)
36
+ expect(loader.thumb.instance_variable_get(:@url)).to eq(url2)
37
+ expect(loader.size).to eq(2)
38
+ end
39
+
40
+ it "should still be able to iterate over a hash of URLs from a hash passed to the new object during creation" do
41
+ loader = ActiveRestClient::LazyAssociationLoader.new(:person, {"main" => url1, "thumb" => url2}, request)
42
+ output = []
43
+ loader.each do |k, v|
44
+ output << v.instance_variable_get(:@url)
45
+ end
46
+ expect(output.size).to eq(2)
47
+ expect(output[0]).to eq(url1)
48
+ expect(output[1]).to eq(url2)
49
+ expect(output[2]).to be_nil
50
+ end
51
+
52
+ it "should be able to list the keys from a hash passed to the new object during creation" do
53
+ loader = ActiveRestClient::LazyAssociationLoader.new(:person, {"main" => url1, "thumb" => url2}, request)
54
+ expect(loader.keys[0]).to eq(:main)
55
+ expect(loader.keys[1]).to eq(:thumb)
56
+ expect(loader.keys.size).to eq(2)
57
+ end
58
+
59
+ it "should report the size of a list of stored URLs" do
60
+ loader = ActiveRestClient::LazyAssociationLoader.new(:person, [url1, url2], nil)
61
+ expect(loader.size).to eq(2)
62
+ end
63
+
64
+ it "should respond to each and iterate through the list of stored URLs" do
65
+ loader = ActiveRestClient::LazyAssociationLoader.new(:person, [url1, url2], nil)
66
+ output = []
67
+ loader.each do |o|
68
+ output << o.instance_variable_get(:@url)
69
+ end
70
+ expect(output.size).to eq(2)
71
+ expect(output[0]).to eq(url1)
72
+ expect(output[1]).to eq(url2)
73
+ expect(output[2]).to be_nil
74
+ end
75
+
76
+ it "should return a LazyAssociationLoader for each stored URL in a list" do
77
+ loader = ActiveRestClient::LazyAssociationLoader.new(:person, [url1, url2], nil)
78
+ output = []
79
+ loader.each do |o|
80
+ expect(o).to be_an_instance_of(ActiveRestClient::LazyAssociationLoader)
81
+ end
82
+ end
83
+
84
+ it "should make the request for a URL if it's accessed" do
85
+ method_data = {options:{url:"foo"}}
86
+ request = double("Request").as_null_object
87
+ request.stub(:method).and_return(method_data)
88
+ request.should_receive(:object).with(any_args).and_return(Array.new)
89
+ request.should_receive(:call).with(any_args).and_return("")
90
+ ActiveRestClient::Request.should_receive(:new).with(any_args).and_return(request)
91
+ loader = ActiveRestClient::LazyAssociationLoader.new(:person, url1, request)
92
+ loader.length
93
+ end
94
+
95
+ it "should proxy methods to the underlying object if the request has been made" do
96
+ loader = ActiveRestClient::LazyAssociationLoader.new(:person, url1, request)
97
+ object = double("Object")
98
+ object.should_receive(:length).and_return(1)
99
+ loader.instance_variable_set(:@object, object)
100
+ expect(loader.length).to eq(1)
101
+ end
102
+
103
+ it "should be able to iterate underlying object if it's an array" do
104
+ loader = ActiveRestClient::LazyAssociationLoader.new(:person, url1, request)
105
+ ActiveRestClient::Request.any_instance.should_receive(:call).with(any_args).and_return([1,2,3])
106
+ test = []
107
+ loader.each do |item|
108
+ test << item
109
+ end
110
+ expect(test).to eq([1,2,3])
111
+ end
112
+
113
+ it "should be able to return the size of the underlying object if it's an array" do
114
+ loader = ActiveRestClient::LazyAssociationLoader.new(:person, url1, request)
115
+ ActiveRestClient::Request.any_instance.should_receive(:call).with(any_args).and_return([1,2,3])
116
+ expect(loader.size).to eq(3)
117
+ end
118
+ end