sucker 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. data/CHANGELOG.md +9 -18
  2. data/README.md +9 -5
  3. data/lib/sucker.rb +0 -3
  4. data/lib/sucker/request.rb +96 -18
  5. data/lib/sucker/response.rb +20 -14
  6. data/lib/sucker/version.rb +1 -1
  7. data/spec/integration/multiple_locales_spec.rb +28 -3
  8. data/spec/support/vcr.rb +3 -2
  9. data/spec/unit/sucker/request_spec.rb +109 -29
  10. data/spec/unit/sucker/response_spec.rb +26 -23
  11. metadata +23 -137
  12. data/lib/sucker.rbc +0 -341
  13. data/lib/sucker/request.rbc +0 -2481
  14. data/lib/sucker/response.rbc +0 -1554
  15. data/lib/sucker/version.rbc +0 -130
  16. data/spec/fixtures/cassette_library/integration/alternate_versions.yml +0 -27
  17. data/spec/fixtures/cassette_library/integration/errors.yml +0 -27
  18. data/spec/fixtures/cassette_library/integration/france.yml +0 -27
  19. data/spec/fixtures/cassette_library/integration/images.yml +0 -27
  20. data/spec/fixtures/cassette_library/integration/item_lookup/multiple.yml +0 -27
  21. data/spec/fixtures/cassette_library/integration/item_lookup/single.yml +0 -27
  22. data/spec/fixtures/cassette_library/integration/item_search.yml +0 -27
  23. data/spec/fixtures/cassette_library/integration/japan.yml +0 -27
  24. data/spec/fixtures/cassette_library/integration/keyword_search.yml +0 -27
  25. data/spec/fixtures/cassette_library/integration/kindle.yml +0 -27
  26. data/spec/fixtures/cassette_library/integration/kindle_2.yml +0 -27
  27. data/spec/fixtures/cassette_library/integration/multiple_locales.yml +0 -157
  28. data/spec/fixtures/cassette_library/integration/power_search.yml +0 -27
  29. data/spec/fixtures/cassette_library/integration/related_items/child.yml +0 -27
  30. data/spec/fixtures/cassette_library/integration/related_items/parent.yml +0 -27
  31. data/spec/fixtures/cassette_library/integration/seller_listings_search.yml +0 -27
  32. data/spec/fixtures/cassette_library/integration/twenty_items.yml +0 -27
  33. data/spec/fixtures/cassette_library/unit/sucker/request.yml +0 -29
  34. data/spec/fixtures/cassette_library/unit/sucker/response.yml +0 -27
  35. data/spec/integration/alternate_versions_spec.rbc +0 -843
  36. data/spec/integration/errors_spec.rbc +0 -964
  37. data/spec/integration/france_spec.rbc +0 -1012
  38. data/spec/integration/images_spec.rbc +0 -1047
  39. data/spec/integration/item_lookup_spec.rbc +0 -1723
  40. data/spec/integration/item_search_spec.rbc +0 -926
  41. data/spec/integration/japan_spec.rbc +0 -849
  42. data/spec/integration/keyword_search_spec.rbc +0 -838
  43. data/spec/integration/kindle_spec.rbc +0 -1425
  44. data/spec/integration/multiple_locales_spec.rbc +0 -1090
  45. data/spec/integration/power_search_spec.rbc +0 -838
  46. data/spec/integration/related_items_spec.rbc +0 -1228
  47. data/spec/integration/seller_listing_search_spec.rbc +0 -852
  48. data/spec/integration/twenty_items_spec.rbc +0 -1166
  49. data/spec/spec_helper.rbc +0 -231
  50. data/spec/support/amazon.yml +0 -3
  51. data/spec/support/amazon_credentials.rbc +0 -154
  52. data/spec/support/asins.rbc +0 -335
  53. data/spec/support/vcr.rbc +0 -360
  54. data/spec/unit/sucker/request_spec.rbc +0 -4031
  55. data/spec/unit/sucker/response_spec.rbc +0 -3787
  56. data/spec/unit/sucker_spec.rbc +0 -299
data/CHANGELOG.md CHANGED
@@ -1,34 +1,25 @@
1
- Version 1.0.0
1
+ Version 1.1.0
2
2
  =============
3
3
 
4
- Release date: 2010-11-04
4
+ * Removed Request#get!. Bloat.
5
+ * Added Request#get_all to fetch responses from all venues
6
+ simultaneously.
7
+ * Added Request#associate_tags= to set associate tags for all locales.
8
+ * Added Request#keys= to set distinct keys for locales.
9
+ * Request#get validates presence of key and locale.
5
10
 
6
- Added
7
- -----
11
+ Version 1.0.0
12
+ =============
8
13
 
9
14
  * Added #each and #map to Response. #find no longer yields.
10
15
 
11
16
  Version 1.0.0.beta4
12
17
  ===================
13
18
 
14
- Release date: 2010-10-28
15
-
16
- Added
17
- -----
18
-
19
19
  * Sucker::Request#get! raises an error if response is not valid.
20
20
 
21
21
  Version 1.0.0.beta3
22
22
  ===================
23
23
 
24
- Release date: 2010-10-25
25
-
26
- Added
27
- -----
28
-
29
24
  * Sucker::Response#find yields to a block if given one.
30
-
31
- Deprecated
32
- ----------
33
-
34
25
  * Renamed #node to #find
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  Sucker
2
2
  ======
3
3
 
4
- Sucker is a Ruby wrapper to the [Amazon Product Advertising API](https://affiliate-program.amazon.co.uk/gp/advertising/api/detail/main.html). It runs on [curb](http://github.com/taf2/curb) and [the Nokogiri implementation of the XML Mini module](http://github.com/rails/rails/blob/master/activesupport/lib/active_support/xml_mini/nokogiri.rb) in Active Support. It's fast and supports __the entire API__.
4
+ Sucker is a minimal Ruby wrapper to the [Amazon Product Advertising API](https://affiliate-program.amazon.co.uk/gp/advertising/api/detail/main.html). It runs on [curb](http://github.com/taf2/curb) and [the Nokogiri implementation of the XML Mini module](http://github.com/rails/rails/blob/master/activesupport/lib/active_support/xml_mini/nokogiri.rb) in Active Support. It's fast and supports __the entire API__.
5
5
 
6
- ![Sucker](http://upload.wikimedia.org/wikipedia/commons/thumb/f/f8/FEMA_-_32011_-_FEMA_Joint_Field_Office_%28JFO%29_preparation_in_Ohio.jpg/480px-FEMA_-_32011_-_FEMA_Joint_Field_Office_%28JFO%29_preparation_in_Ohio.jpg)
6
+ ![Electrolux](http://github.com/papercavalier/sucker/raw/master/electrolux.jpg)
7
7
 
8
8
  Examples
9
9
  --------
@@ -43,10 +43,14 @@ Iterate over items in your item lookup.
43
43
 
44
44
  response.each("Item") { |item| ... }
45
45
 
46
- Iterate over errors.
46
+ Map errors to a block.
47
47
 
48
48
  errors = response.map("Error") { |error| ... }
49
49
 
50
+ Or simply get a hash of matching items.
51
+
52
+ items = response.find("Item")
53
+
50
54
  Repeat ad infinitum.
51
55
 
52
56
  Check my [integration specs](http://github.com/papercavalier/sucker/tree/master/spec/integration/) for more examples. See [twenty items](http://github.com/papercavalier/sucker/tree/master/spec/integration/twenty_items_spec.rb) and [multiple locales](http://github.com/papercavalier/sucker/tree/master/spec/integration/multiple_locales_spec.rb) for relatively advanced usage.
@@ -58,12 +62,12 @@ Stubbing
58
62
 
59
63
  Use [VCR](http://github.com/myronmarston/vcr) to stub your requests.
60
64
 
61
- Caveat: Match URIs on host only and create a new cassette for each query. [This is how I do it](http://github.com/papercavalier/sucker/blob/master/spec/support/vcr.rb).
65
+ Caveat: Match URIs on host only and create a new cassette for each query. [This is how my VCR helper looks like.](http://github.com/papercavalier/sucker/blob/master/spec/support/vcr.rb).
62
66
 
63
67
  Compatibility
64
68
  -------------
65
69
 
66
- Specs pass against Ruby 1.8.7, Ruby 1.9.2, and Rubinius 1.1.
70
+ Specs pass against Ruby 1.8.7 and Ruby 1.9.2.
67
71
 
68
72
  Sucker works seamlessly with or without Rails.
69
73
 
data/lib/sucker.rb CHANGED
@@ -1,8 +1,5 @@
1
- require "active_support/xml_mini/nokogiri"
2
- require "curb"
3
1
  require "sucker/request"
4
2
  require "sucker/response"
5
- require "uri"
6
3
 
7
4
  # = Sucker
8
5
  #
@@ -1,3 +1,7 @@
1
+ require "curb"
2
+ require "ostruct"
3
+ require "uri"
4
+
1
5
  module Sucker #:nodoc:
2
6
 
3
7
  # A wrapper around the API request
@@ -49,56 +53,125 @@ module Sucker #:nodoc:
49
53
  self.parameters.merge!(hash)
50
54
  end
51
55
 
52
- # Sets the associate tag
56
+ # Returns the associate tag for the current locale
57
+ def associate_tag
58
+ @associate_tags[locale.to_sym] rescue nil
59
+ end
60
+
61
+ # Sets the associate tag for the current locale
53
62
  #
54
63
  # worker = Sucker.new
55
64
  # worker.associate_tag = 'foo-bar'
56
65
  #
57
66
  def associate_tag=(token)
58
- parameters["AssociateTag"] = token
67
+ @associate_tags = HOSTS.keys.inject({}) do |tags, loc|
68
+ tags[loc] = token
69
+ tags
70
+ end
71
+ end
72
+
73
+ # Sets associate tags for all locales
74
+ #
75
+ # tags = {
76
+ # :us => 'foo-bar-10',
77
+ # :uk => 'foo-bar-20',
78
+ # :de => 'foo-bar-30',
79
+ # ... }
80
+ #
81
+ # worker = Sucker.new
82
+ # worker.associate_tags = tags
83
+ #
84
+ def associate_tags=(tokens)
85
+ @associate_tags = tokens
59
86
  end
60
87
 
61
- # A configurable curl object
88
+ # Returns options for curl and yields them if given a block
62
89
  #
63
90
  # worker = Sucker.new
64
91
  # worker.curl { |c| c.interface = "eth1" }
65
92
  #
66
- def curl
67
- @curl ||= Curl::Easy.new
68
- yield @curl if block_given?
69
- @curl
93
+ def curl_opts
94
+ @curl_opts ||= CurlOptions.new
95
+ yield @curl_opts if block_given?
96
+
97
+ @curl_opts.marshal_dump
70
98
  end
71
99
 
72
- # Performs the request and returns a response object
100
+ # Performs a request and returns a response
73
101
  #
74
102
  # worker = Sucker.new
75
103
  # response = worker.get
76
104
  #
77
105
  def get
78
- curl.url = uri.to_s
79
- curl.perform
106
+ raise ArgumentError.new "Locale missing" unless locale
107
+ raise ArgumentError.new "AWS access key missing" unless key
108
+
109
+ curl = Curl::Easy.perform(uri.to_s) do |easy|
110
+ curl_opts.each { |k, v| easy.send(k, v) }
111
+ end
80
112
 
81
113
  Response.new(curl)
82
114
  end
83
115
 
84
- Similar to get but raises an error if response is not valid
85
- def get!
86
- response = get
116
+ Performs a request for all locales, returns an array of responses, and
117
+ # yields them if given a block
118
+ #
119
+ # worker = Sucker.new
120
+ #
121
+ # # This blocks until all requests are complete
122
+ # responses = worker.get_all
123
+ #
124
+ # # This does not block
125
+ # worker.get_all do |response|
126
+ # process_response
127
+ # end
128
+ #
129
+ def get_all
130
+ uris = HOSTS.keys.map do |locale|
131
+ self.locale = locale
132
+ uri.to_s
133
+ end
134
+ responses = []
87
135
 
88
- unless response.valid?
89
- raise ResponseError, response.inspect
136
+ Curl::Multi.get(uris, curl_opts) do |curl|
137
+ response = Response.new(curl)
138
+ yield response if block_given?
139
+ responses << response
90
140
  end
91
141
 
92
- response
142
+ responses
93
143
  end
94
144
 
95
- # Sets the AWS Access Key ID
145
+ # Returns the AWS access key for the current locale
146
+ def key
147
+ @keys[locale.to_sym]
148
+ end
149
+
150
+ # Sets a global AWS access key ID
96
151
  #
97
152
  # worker = Sucker.new
98
153
  # worker.key = 'foo'
99
154
  #
100
155
  def key=(token)
101
- parameters["AWSAccessKeyId"] = token
156
+ @keys = HOSTS.keys.inject({}) do |keys, locale|
157
+ keys[locale] = token
158
+ keys
159
+ end
160
+ end
161
+
162
+ # Sets distinct AWS access keys for the locales
163
+ #
164
+ # keys = {
165
+ # :us => 'foo',
166
+ # :uk => 'bar',
167
+ # :de => 'baz',
168
+ # ... }
169
+ #
170
+ # worker = Sucker.new
171
+ # worker.keys = keys
172
+ #
173
+ def keys=(tokens)
174
+ @keys = tokens
102
175
  end
103
176
 
104
177
  # Sets the Amazon API version
@@ -116,6 +189,8 @@ module Sucker #:nodoc:
116
189
  def build_query
117
190
  parameters.
118
191
  merge(timestamp).
192
+ merge({ "AWSAccessKeyId" => key }).
193
+ merge({ "AssociateTag" => associate_tag }).
119
194
  sort.
120
195
  collect do |k, v|
121
196
  "#{k}=" + escape(v.is_a?(Array) ? v.join(",") : v.to_s)
@@ -156,4 +231,7 @@ module Sucker #:nodoc:
156
231
  { "Timestamp" => Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ') }
157
232
  end
158
233
  end
234
+
235
+ # Curl options
236
+ class CurlOptions < OpenStruct; end
159
237
  end
@@ -1,3 +1,5 @@
1
+ require "active_support/xml_mini/nokogiri"
2
+
1
3
  module Sucker #:nodoc:
2
4
 
3
5
  # A Nokogiri-driven wrapper around the cURL response
@@ -12,19 +14,23 @@ module Sucker #:nodoc:
12
14
  # Transaction time in seconds for request
13
15
  attr_accessor :time
14
16
 
17
+ # The request URI
18
+ attr_accessor :uri
19
+
15
20
  def initialize(curl)
16
21
  self.body = curl.body_str
17
22
  self.code = curl.response_code
18
23
  self.time = curl.total_time
24
+ self.uri = curl.url
19
25
  end
20
26
 
21
- # A shorthand that yields each match to a block
22
- #
23
- # worker.get.each("Item") { |item| process(item) }
24
- #
25
- def each(path)
26
- find(path).each { |node| yield node }
27
- end
27
+ # A shorthand that yields each match to a block
28
+ #
29
+ # worker.get.each("Item") { |item| process(item) }
30
+ #
31
+ def each(path)
32
+ find(path).each { |e| yield e }
33
+ end
28
34
 
29
35
  # Queries an xpath and returns an array of matching nodes
30
36
  #
@@ -32,15 +38,15 @@ module Sucker #:nodoc:
32
38
  # response.find("Item").each { |item| ... }
33
39
  #
34
40
  def find(path)
35
- xml.xpath("//xmlns:#{path}").map { |node| strip_content(node.to_hash[path]) }
41
+ xml.xpath("//xmlns:#{path}").map { |e| strip_content(e.to_hash[path]) }
36
42
  end
37
43
 
38
- # A shorthand that yields matches to a block and collects returned values
39
- #
40
- # descriptions = worker.get.map("Item") { |item| build_description(item) }
41
- #
42
- def map(path)
43
- find(path).map { |e| yield e }
44
+ # A shorthand that yields matches to a block and collects returned values
45
+ #
46
+ # descriptions = worker.get.map("Item") { |item| build_description(item) }
47
+ #
48
+ def map(path)
49
+ find(path).map { |e| yield e }
44
50
  end
45
51
 
46
52
  def node(path) # :nodoc:
@@ -1,3 +1,3 @@
1
1
  module Sucker #:nodoc:
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -5,11 +5,36 @@ module Sucker
5
5
 
6
6
  describe "Item lookup" do
7
7
 
8
- context "when using threads to search multiple locales" do
8
+ use_vcr_cassette "integration/multiple_locales", :record => :new_episodes
9
9
 
10
- use_vcr_cassette "integration/multiple_locales", :record => :new_episodes
10
+ context "when using Curl::Multi to search all locales simultaneously" do
11
11
 
12
- it "returns matches across all locales" do
12
+ it "returns matches for all locales" do
13
+ worker = Sucker.new(
14
+ :key => amazon["key"],
15
+ :secret => amazon["secret"])
16
+ worker << {
17
+ "Operation" => "ItemLookup",
18
+ "IdType" => "ASIN",
19
+ "ResponseGroup" => "ItemAttributes",
20
+ "ItemId" => "0816614024" }
21
+
22
+ bindings = worker.get_all.map do |response|
23
+ item = response.find("Item").first
24
+ item["ItemAttributes"]["Binding"]
25
+ end
26
+
27
+ bindings.uniq.should =~ %w{ Paperback Taschenbuch Broché ペーパーバック }
28
+
29
+ end
30
+
31
+ end
32
+
33
+ context "when using threads to search all locales simultaneously" do
34
+
35
+ # Leaving this spec here for reference purposes. Use approach in above spec.
36
+
37
+ it "returns matches for all locales" do
13
38
  locales = %w{us uk de ca fr jp}
14
39
 
15
40
  params = {
data/spec/support/vcr.rb CHANGED
@@ -2,10 +2,11 @@ require 'vcr'
2
2
 
3
3
  VCR.config do |c|
4
4
  c.cassette_library_dir = File.dirname(__FILE__) + '/../fixtures/cassette_library'
5
- c.http_stubbing_library = :webmock
6
5
  c.default_cassette_options = {
7
- :record => :new_episodes,
6
+ :record => :none,
8
7
  :match_requests_on => [:host] }
8
+
9
+ c.stub_with :webmock
9
10
  end
10
11
 
11
12
  RSpec.configure do |config|
@@ -42,60 +42,134 @@ module Sucker
42
42
 
43
43
  end
44
44
 
45
- describe "#associate_tag=" do
45
+ describe "#associate_tag" do
46
46
 
47
- it "sets the associate tag in the parameters" do
48
- worker.associate_tag = "foo"
49
- worker.parameters["AssociateTag"].should eql "foo"
47
+ it "returns the associate tag for the current locale" do
48
+ worker.instance_variable_set(:@associate_tags, { :us => 'foo-bar'})
49
+
50
+ worker.associate_tag.should eql 'foo-bar'
51
+ end
52
+
53
+ it "returns nil if an associate tag is not set for the current locale" do
54
+ worker.associate_tag.should eql nil
50
55
  end
51
56
 
52
57
  end
53
58
 
54
- describe "#curl" do
59
+ describe "#associate_tags=" do
55
60
 
56
- it "returns curl" do
57
- worker.curl.should be_an_instance_of Curl::Easy
61
+ it "sets associate tags for the locales" do
62
+ tags = {
63
+ :us => 'foo',
64
+ :uk => 'bar',
65
+ :de => 'baz',
66
+ :ca => 'foo',
67
+ :fr => 'bar',
68
+ :jp => 'baz' }
69
+ worker.associate_tags = tags
70
+
71
+ worker.instance_variable_get(:@associate_tags).should eql tags
58
72
  end
59
73
 
60
- context "when given a block" do
74
+ end
61
75
 
62
- it "yields curl" do
63
- worker.curl.interface.should be_nil
76
+ describe "#curl_opts" do
64
77
 
65
- worker.curl { |curl| curl.interface = "eth1" }
78
+ it "returns options for curl" do
79
+ worker.curl_opts.should be_an_instance_of Hash
80
+ end
81
+
82
+ context "when given a block" do
66
83
 
67
- worker.curl.interface.should eql "eth1"
84
+ it "yields options for curl" do
85
+ worker.curl_opts { |c| c.interface = "eth1" }
86
+
87
+ worker.curl_opts[:interface].should eql "eth1"
68
88
  end
69
89
 
70
90
  end
71
91
 
72
92
  end
73
93
 
74
- describe "#get!" do
94
+ describe "#get" do
95
+
96
+ it "returns a response" do
97
+ worker.get.class.ancestors.should include Response
98
+ end
75
99
 
76
- it "raises if response is not valid" do
77
- worker << {
78
- "Operation" => "ItemLookup",
79
- "IdType" => "ASIN",
80
- "ItemId" => "0816614024" }
81
- lambda { worker.get! }.should raise_error ResponseError
100
+ it "raises an argument error if no key is provided" do
101
+ worker.key = nil
102
+ expect do
103
+ worker.get
104
+ end.to raise_error(/AWS access key missing/)
82
105
  end
83
106
 
107
+ it "raises an argument error if no locale is provided" do
108
+ worker.locale = nil
109
+ expect do
110
+ worker.get
111
+ end.to raise_error(/Locale missing/)
112
+ end
84
113
  end
85
114
 
86
- describe "#get" do
115
+ describe "#get_all" do
87
116
 
88
- it "returns a response" do
89
- worker.get.class.ancestors.should include Response
117
+ it "returns an array of responses" do
118
+ responses = worker.get_all
119
+
120
+ responses.should be_an_instance_of Array
121
+ responses.each { |resp| resp.should be_an_instance_of Response }
122
+ end
123
+
124
+ context "when given a block" do
125
+
126
+ it "yields responses" do
127
+ count = 0
128
+ worker.get_all do |resp|
129
+ resp.should be_an_instance_of Response
130
+ count += 1
131
+ end
132
+
133
+ count.should eql Request::HOSTS.size
134
+ end
135
+ end
136
+ end
137
+
138
+ describe "#key" do
139
+
140
+ it "returns the Amazon AWS access key for the current locale" do
141
+ worker.instance_variable_set(:@keys, { :us => 'foo' })
142
+
143
+ worker.key.should eql 'foo'
90
144
  end
91
145
 
92
146
  end
93
147
 
94
148
  describe "#key=" do
95
149
 
96
- it "sets the Amazon AWS access key in the parameters" do
150
+ it "sets a global Amazon AWS access key" do
97
151
  worker.key = "foo"
98
- worker.parameters["AWSAccessKeyId"].should eql "foo"
152
+ keys = worker.instance_variable_get(:@keys)
153
+
154
+ keys.size.should eql Request::HOSTS.size
155
+ keys.values.uniq.should eql ["foo"]
156
+ end
157
+
158
+ end
159
+
160
+ describe "#keys=" do
161
+
162
+ it "sets distinct Amazon AWS access keys for the locales" do
163
+ keys = {
164
+ :us => 'foo',
165
+ :uk => 'bar',
166
+ :de => 'baz',
167
+ :ca => 'foo',
168
+ :fr => 'bar',
169
+ :jp => 'baz' }
170
+ worker.keys = keys
171
+
172
+ worker.instance_variable_get(:@keys).should eql keys
99
173
  end
100
174
 
101
175
  end
@@ -104,32 +178,38 @@ module Sucker
104
178
 
105
179
  describe "#build_query" do
106
180
 
181
+ let(:query) { worker.send(:build_query) }
182
+
107
183
  it "canonicalizes parameters" do
108
- query = worker.send(:build_query)
109
184
  query.should match /Service=([^&]+)&Timestamp=([^&]+)&Version=([^&]+)/
110
185
  end
111
186
 
187
+ it "includes the key for the current locale" do
188
+ worker.instance_variable_set(:@keys, { :us => 'foo' })
189
+ query.should include 'AWSAccessKeyId=foo'
190
+ end
191
+
192
+ it "includes a timestamp" do
193
+ query.should include 'Timestamp='
194
+ end
195
+
112
196
  it "sorts parameters" do
113
197
  worker.parameters["AAA"] = "foo"
114
- query = worker.send(:build_query)
115
198
  query.should match /^AAA=foo/
116
199
  end
117
200
 
118
201
  it "converts a parameter whose value is an array to a string" do
119
202
  worker.parameters["Foo"] = ["bar", "baz"]
120
- query = worker.send(:build_query)
121
203
  query.should match /Foo=bar%2Cbaz/
122
204
  end
123
205
 
124
206
  it "handles integer parameter values" do
125
207
  worker.parameters["Foo"] = 1
126
- query = worker.send(:build_query)
127
208
  query.should match /Foo=1/
128
209
  end
129
210
 
130
211
  it "handles floating-point parameter values" do
131
212
  worker.parameters["Foo"] = 1.0
132
- query = worker.send(:build_query)
133
213
  query.should match /Foo=1/
134
214
  end
135
215