wavefront-sdk 1.3.0 → 1.3.1

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -1142
  3. data/Gemfile +1 -1
  4. data/Rakefile +1 -1
  5. data/lib/wavefront-sdk/alert.rb +3 -3
  6. data/lib/wavefront-sdk/base.rb +25 -25
  7. data/lib/wavefront-sdk/cloudintegration.rb +1 -2
  8. data/lib/wavefront-sdk/constants.rb +1 -1
  9. data/lib/wavefront-sdk/credentials.rb +4 -6
  10. data/lib/wavefront-sdk/dashboard.rb +2 -3
  11. data/lib/wavefront-sdk/event.rb +2 -3
  12. data/lib/wavefront-sdk/exception.rb +36 -36
  13. data/lib/wavefront-sdk/externallink.rb +2 -2
  14. data/lib/wavefront-sdk/integration.rb +1 -2
  15. data/lib/wavefront-sdk/maintenancewindow.rb +3 -3
  16. data/lib/wavefront-sdk/message.rb +1 -2
  17. data/lib/wavefront-sdk/mixins.rb +25 -20
  18. data/lib/wavefront-sdk/notificant.rb +1 -2
  19. data/lib/wavefront-sdk/parse_time.rb +14 -13
  20. data/lib/wavefront-sdk/proxy.rb +2 -3
  21. data/lib/wavefront-sdk/query.rb +4 -8
  22. data/lib/wavefront-sdk/response.rb +8 -16
  23. data/lib/wavefront-sdk/savedsearch.rb +3 -5
  24. data/lib/wavefront-sdk/search.rb +2 -3
  25. data/lib/wavefront-sdk/source.rb +1 -1
  26. data/lib/wavefront-sdk/user.rb +1 -3
  27. data/lib/wavefront-sdk/validators.rb +12 -14
  28. data/lib/wavefront-sdk/version.rb +1 -1
  29. data/lib/wavefront-sdk/webhook.rb +2 -2
  30. data/lib/wavefront-sdk/write.rb +48 -24
  31. data/spec/spec_helper.rb +6 -4
  32. data/spec/wavefront-sdk/credentials_spec.rb +9 -7
  33. data/spec/wavefront-sdk/externallink_spec.rb +2 -0
  34. data/spec/wavefront-sdk/mixins_spec.rb +4 -3
  35. data/spec/wavefront-sdk/parse_time_spec.rb +26 -20
  36. data/spec/wavefront-sdk/query_spec.rb +2 -1
  37. data/spec/wavefront-sdk/response_spec.rb +13 -1
  38. data/spec/wavefront-sdk/validators_spec.rb +9 -2
  39. data/spec/wavefront-sdk/write_spec.rb +18 -6
  40. data/wavefront-sdk.gemspec +8 -7
  41. metadata +29 -29
data/Gemfile CHANGED
@@ -1,2 +1,2 @@
1
- source 'https://rubygems.org'
1
+ source 'https://rubygems.org'
2
2
  gemspec
data/Rakefile CHANGED
@@ -2,7 +2,7 @@ require 'yard'
2
2
  require 'rake/testtask'
3
3
  require 'rubocop/rake_task'
4
4
 
5
- task default: :test
5
+ task default: %i[rubocop test]
6
6
 
7
7
  Rake::TestTask.new do |t|
8
8
  t.pattern = 'spec/wavefront-sdk/*_spec.rb'
@@ -7,8 +7,8 @@ module Wavefront
7
7
  #
8
8
  class Alert < Base
9
9
  def update_keys
10
- %i(id name target condition displayExpression minutes
11
- resolveAfterMinutes severity additionalInformation)
10
+ %i[id name target condition displayExpression minutes
11
+ resolveAfterMinutes severity additionalInformation]
12
12
  end
13
13
 
14
14
  # GET /api/v2/alert
@@ -19,7 +19,7 @@ module Wavefront
19
19
  # @return [Hash]
20
20
  #
21
21
  def list(offset = 0, limit = 100)
22
- api_get('', { offset: offset, limit: limit })
22
+ api_get('', offset: offset, limit: limit)
23
23
  end
24
24
 
25
25
  # POST /api/v2/alert
@@ -18,6 +18,7 @@ module Wavefront
18
18
  #
19
19
  # @return a Wavefront::Response object
20
20
  #
21
+ # rubocop:disable Metrics/ClassLength
21
22
  class Base
22
23
  include Wavefront::Validators
23
24
  include Wavefront::Mixins
@@ -60,10 +61,10 @@ module Wavefront
60
61
  # @param t [Integer] epoch timestamp
61
62
  # @return [Ingeter] epoch millisecond timestamp
62
63
  #
63
- def time_to_ms(t)
64
- return false unless t.is_a?(Integer)
65
- return t if t.to_s.size == 13
66
- (t.to_f * 1000).round
64
+ def time_to_ms(time)
65
+ return false unless time.is_a?(Integer)
66
+ return time if time.to_s.size == 13
67
+ (time.to_f * 1000).round
67
68
  end
68
69
 
69
70
  # Derive the first part of the API path from the class name. You
@@ -119,8 +120,8 @@ module Wavefront
119
120
  #
120
121
  def api_post(path, body = nil, ctype = 'text/plain')
121
122
  body = body.to_json unless body.is_a?(String)
122
- make_call(mk_conn(path, { 'Content-Type': ctype,
123
- 'Accept': 'application/json'}),
123
+ make_call(mk_conn(path, 'Content-Type': ctype,
124
+ 'Accept': 'application/json'),
124
125
  :post, nil, body)
125
126
  end
126
127
 
@@ -136,8 +137,8 @@ module Wavefront
136
137
  # @return [Hash] API response
137
138
  #
138
139
  def api_put(path, body = nil, ctype = 'application/json')
139
- make_call(mk_conn(path, { 'Content-Type': ctype,
140
- 'Accept': 'application/json' }),
140
+ make_call(mk_conn(path, 'Content-Type': ctype,
141
+ 'Accept': 'application/json'),
141
142
  :put, nil, body.to_json)
142
143
  end
143
144
 
@@ -191,8 +192,8 @@ module Wavefront
191
192
  # Print it unless it's a debug and we're not in debug
192
193
  #
193
194
  def print_message(msg, level)
194
- return if level == :debug && ! opts[:debug]
195
- return if level == :info && ! opts[:verbose]
195
+ return if level == :debug && !opts[:debug]
196
+ return if level == :info && !opts[:verbose]
196
197
  puts msg
197
198
  end
198
199
 
@@ -201,9 +202,11 @@ module Wavefront
201
202
  # 'User'), a class can provide a {#response_shim} method.
202
203
  #
203
204
  def respond(resp)
204
- body = respond_to?(:response_shim) ? response_shim(resp.body,
205
- resp.status) :
206
- resp.body
205
+ body = if respond_to?(:response_shim)
206
+ response_shim(resp.body, resp.status)
207
+ else
208
+ resp.body
209
+ end
207
210
 
208
211
  Wavefront::Response.new(body, resp.status, debug)
209
212
  end
@@ -217,7 +220,7 @@ module Wavefront
217
220
  limit = 100
218
221
 
219
222
  loop do
220
- resp = api_get('', { offset: offset, limit: limit }).response
223
+ resp = api_get('', offset: offset, limit: limit).response
221
224
  resp.items.map { |i| y.<< i }
222
225
  offset += limit
223
226
  raise StopIteration unless resp.moreItems == true
@@ -233,10 +236,9 @@ module Wavefront
233
236
  def verbosity(conn, method, *args)
234
237
  log "uri: #{method.upcase} #{conn.url_prefix}"
235
238
 
236
- if args.last && ! args.last.empty?
237
- puts log method == :get ? "params: #{args.last}" :
238
- "body: #{args.last}"
239
- end
239
+ return unless args.last && !args.last.empty?
240
+
241
+ puts log method == :get ? "params: #{args.last}" : "body: #{args.last}"
240
242
  end
241
243
 
242
244
  # Make the API call, or not, if noop is set.
@@ -256,7 +258,7 @@ module Wavefront
256
258
  end
257
259
 
258
260
  def setup_endpoint(creds)
259
- %w(endpoint token).each do |k|
261
+ %w[endpoint token].each do |k|
260
262
  raise "creds must contain #{k}" unless creds.key?(k.to_sym)
261
263
  end
262
264
 
@@ -264,12 +266,10 @@ module Wavefront
264
266
  creds[:agent] = "wavefront-sdk #{WF_SDK_VERSION}"
265
267
  end
266
268
 
267
- @net = {
268
- headers: { 'Authorization': "Bearer #{creds[:token]}",
269
- 'user-agent': creds[:agent] },
270
- endpoint: creds[:endpoint],
271
- api_base: ['', 'api', 'v2', api_base].uri_concat
272
- }
269
+ @net = { headers: { 'Authorization': "Bearer #{creds[:token]}",
270
+ 'user-agent': creds[:agent] },
271
+ endpoint: creds[:endpoint],
272
+ api_base: ['', 'api', 'v2', api_base].uri_concat }
273
273
  end
274
274
  end
275
275
  end
@@ -6,7 +6,6 @@ module Wavefront
6
6
  # a UUID.
7
7
  #
8
8
  class CloudIntegration < Base
9
-
10
9
  # GET /api/v2/cloudintegration
11
10
  # Get all cloud integrations for a customer
12
11
  #
@@ -15,7 +14,7 @@ module Wavefront
15
14
  # @return [Wavefront::Response]
16
15
  #
17
16
  def list(offset = 0, limit = 100)
18
- api_get('', { offset: offset, limit: limit })
17
+ api_get('', offset: offset, limit: limit)
19
18
  end
20
19
 
21
20
  # POST /api/v2/cloudintegration
@@ -1,3 +1,3 @@
1
1
  # Constants
2
2
  #
3
- DELTA = "\u2206" # "Increment" -- alt-J on a Mac
3
+ DELTA = "\u2206".freeze # "Increment" -- alt-J on a Mac
@@ -3,7 +3,6 @@ require 'inifile'
3
3
  require 'map'
4
4
 
5
5
  module Wavefront
6
-
7
6
  # Helper methods to get Wavefront credentials.
8
7
  #
9
8
  # @return [Wavefront::Credentials]
@@ -45,8 +44,7 @@ module Wavefront
45
44
  def env_override(raw)
46
45
  { endpoint: 'WAVEFRONT_ENDPOINT',
47
46
  token: 'WAVEFRONT_TOKEN',
48
- proxy: 'WAVEFRONT_PROXY'
49
- }.each { |k, v| raw[k] = ENV[v] if ENV[v] }
47
+ proxy: 'WAVEFRONT_PROXY' }.each { |k, v| raw[k] = ENV[v] if ENV[v] }
50
48
  raw
51
49
  end
52
50
 
@@ -59,8 +57,8 @@ module Wavefront
59
57
  #
60
58
  def populate(raw)
61
59
  @config = Map(raw)
62
- @creds = Map(raw.select { |k, _v| [:endpoint, :token].include?(k) })
63
- @proxy = Map(raw.select { |k, _v| [:proxy, :port].include?(k) })
60
+ @creds = Map(raw.select { |k, _v| %i[endpoint token].include?(k) })
61
+ @proxy = Map(raw.select { |k, _v| %i[proxy port].include?(k) })
64
62
  end
65
63
 
66
64
  # @return [Array] a list of possible credential files
@@ -70,7 +68,7 @@ module Wavefront
70
68
  Array(Pathname.new(opts[:file]))
71
69
  else
72
70
  [Pathname.new('/etc/wavefront/credentials'),
73
- Pathname.new(ENV['HOME']) + '.wavefront']
71
+ Pathname.new(ENV['HOME']) + '.wavefront']
74
72
  end
75
73
  end
76
74
 
@@ -6,7 +6,7 @@ module Wavefront
6
6
  #
7
7
  class Dashboard < Base
8
8
  def update_keys
9
- %i(id name url description sections)
9
+ %i[id name url description sections]
10
10
  end
11
11
 
12
12
  # GET /api/v2/dashboard
@@ -17,7 +17,7 @@ module Wavefront
17
17
  # @return [Wavefront::Response]
18
18
  #
19
19
  def list(offset = 0, limit = 100)
20
- api_get('', { offset: offset, limit: limit })
20
+ api_get('', offset: offset, limit: limit)
21
21
  end
22
22
 
23
23
  # POST /api/v2/dashboard
@@ -83,7 +83,6 @@ module Wavefront
83
83
  'application/json')
84
84
  end
85
85
 
86
-
87
86
  # GET /api/v2/dashboard/id/history
88
87
  # Get the version history of an dashboard.
89
88
  #
@@ -7,7 +7,7 @@ module Wavefront
7
7
  #
8
8
  class Event < Base
9
9
  def update_keys
10
- %i(startTime endTime name annotations)
10
+ %i[startTime endTime name annotations]
11
11
  end
12
12
 
13
13
  # GET /api/v2/event
@@ -34,8 +34,7 @@ module Wavefront
34
34
 
35
35
  api_get('', { earliestStartTimeEpochMillis: from,
36
36
  latestStartTimeEpochMillis: to,
37
- cursor: cursor,
38
- limit: limit }.select { |_k, v| v })
37
+ cursor: cursor, limit: limit }.select { |_k, v| v })
39
38
  end
40
39
 
41
40
  # POST /api/v2/event
@@ -3,41 +3,41 @@ module Wavefront
3
3
  # Simple exception classes
4
4
  #
5
5
  class Exception
6
- class EmptyMetricName < ::Exception; end
7
- class InvalidAlertId < ::Exception; end
8
- class InvalidAlertSeverity < ::Exception; end
9
- class InvalidCloudIntegrationId < ::Exception; end
10
- class InvalidDashboardId < ::Exception; end
11
- class InvalidEndpoint < ::Exception; end
12
- class InvalidEventId < ::Exception; end
13
- class InvalidExternalLinkId < ::Exception; end
14
- class InvalidGranularity < ::Exception; end
15
- class InvalidHostname < ::Exception; end
16
- class InvalidIntegrationId < ::Exception; end
17
- class InvalidRelativeTime < ::Exception; end
18
- class InvalidTimeUnit < ::Exception; end
19
- class InvalidMaintenanceWindowId < ::Exception; end
20
- class InvalidMessageId < ::Exception; end
21
- class InvalidMetricName < ::Exception; end
22
- class InvalidMetricValue < ::Exception; end
23
- class InvalidNotificantId < ::Exception; end
24
- class InvalidName < ::Exception; end
25
- class InvalidPoint < ::Exception; end
26
- class InvalidPrefixLength < ::Exception; end
27
- class InvalidProxyId < ::Exception; end
28
- class InvalidSavedSearchId < ::Exception; end
29
- class InvalidSavedSearchEntity < ::Exception; end
30
- class InvalidSourceId < ::Exception; end
31
- class InvalidString < ::Exception; end
32
- class InvalidTag < ::Exception; end
33
- class InvalidLinkTemplate < ::Exception; end
34
- class InvalidTimeFormat < ::Exception; end
35
- class InvalidTimestamp < ::Exception; end
36
- class InvalidUserId < ::Exception; end
37
- class InvalidWebhookId < ::Exception; end
38
- class InvalidVersion < ::Exception; end
39
- class NotImplemented < ::Exception; end
40
- class UnparseableResponse < ::Exception; end
41
- class ValueOutOfRange < ::Exception; end
6
+ class EmptyMetricName < RuntimeError; end
7
+ class InvalidAlertId < RuntimeError; end
8
+ class InvalidAlertSeverity < RuntimeError; end
9
+ class InvalidCloudIntegrationId < RuntimeError; end
10
+ class InvalidDashboardId < RuntimeError; end
11
+ class InvalidEndpoint < RuntimeError; end
12
+ class InvalidEventId < RuntimeError; end
13
+ class InvalidExternalLinkId < RuntimeError; end
14
+ class InvalidGranularity < RuntimeError; end
15
+ class InvalidHostname < RuntimeError; end
16
+ class InvalidIntegrationId < RuntimeError; end
17
+ class InvalidRelativeTime < RuntimeError; end
18
+ class InvalidTimeUnit < RuntimeError; end
19
+ class InvalidMaintenanceWindowId < RuntimeError; end
20
+ class InvalidMessageId < RuntimeError; end
21
+ class InvalidMetricName < RuntimeError; end
22
+ class InvalidMetricValue < RuntimeError; end
23
+ class InvalidNotificantId < RuntimeError; end
24
+ class InvalidName < RuntimeError; end
25
+ class InvalidPoint < RuntimeError; end
26
+ class InvalidPrefixLength < RuntimeError; end
27
+ class InvalidProxyId < RuntimeError; end
28
+ class InvalidSavedSearchId < RuntimeError; end
29
+ class InvalidSavedSearchEntity < RuntimeError; end
30
+ class InvalidSourceId < RuntimeError; end
31
+ class InvalidString < RuntimeError; end
32
+ class InvalidTag < RuntimeError; end
33
+ class InvalidLinkTemplate < RuntimeError; end
34
+ class InvalidTimeFormat < RuntimeError; end
35
+ class InvalidTimestamp < RuntimeError; end
36
+ class InvalidUserId < RuntimeError; end
37
+ class InvalidWebhookId < RuntimeError; end
38
+ class InvalidVersion < RuntimeError; end
39
+ class NotImplemented < RuntimeError; end
40
+ class UnparseableResponse < RuntimeError; end
41
+ class ValueOutOfRange < RuntimeError; end
42
42
  end
43
43
  end
@@ -10,7 +10,7 @@ module Wavefront
10
10
  end
11
11
 
12
12
  def update_keys
13
- %i(name template description)
13
+ %i[name template description]
14
14
  end
15
15
 
16
16
  # GET /api/v2/extlink
@@ -20,7 +20,7 @@ module Wavefront
20
20
  # @param limit [Int] the number of link to return
21
21
  #
22
22
  def list(offset = 0, limit = 100)
23
- api_get('', { offset: offset, limit: limit })
23
+ api_get('', offset: offset, limit: limit)
24
24
  end
25
25
 
26
26
  # POST /api/v2/extlink
@@ -5,7 +5,6 @@ module Wavefront
5
5
  # Manage and query Wavefront integrations.
6
6
  #
7
7
  class Integration < Base
8
-
9
8
  # GET /api/v2/integration
10
9
  # Gets a flat list of all Wavefront integrations available,
11
10
  # along with their status
@@ -14,7 +13,7 @@ module Wavefront
14
13
  # @param limit [Int] the number of proxies to return
15
14
  #
16
15
  def list(offset = 0, limit = 100)
17
- api_get('', { offset: offset, limit: limit })
16
+ api_get('', offset: offset, limit: limit)
18
17
  end
19
18
 
20
19
  # GET /api/v2/integration/id
@@ -6,8 +6,8 @@ module Wavefront
6
6
  #
7
7
  class MaintenanceWindow < Base
8
8
  def update_keys
9
- %i(reason title startTimeInSeconds endTimeInSeconds
10
- relevantCustomerTags relevantHostTags relevantHostNames)
9
+ %i[reason title startTimeInSeconds endTimeInSeconds
10
+ relevantCustomerTags relevantHostTags relevantHostNames]
11
11
  end
12
12
 
13
13
  # GET /api/v2/maintenancewindow
@@ -17,7 +17,7 @@ module Wavefront
17
17
  # @param limit [Integer] the number of window to return
18
18
  #
19
19
  def list(offset = 0, limit = 100)
20
- api_get('', { offset: offset, limit: limit })
20
+ api_get('', offset: offset, limit: limit)
21
21
  end
22
22
 
23
23
  # POST /api/v2/maintenancewindow
@@ -5,7 +5,6 @@ module Wavefront
5
5
  # Manage and query Wavefront messages.
6
6
  #
7
7
  class Message < Base
8
-
9
8
  # GET /api/v2/message
10
9
  # Gets messages applicable to the current user, i.e. within time
11
10
  # range and distribution scope
@@ -14,7 +13,7 @@ module Wavefront
14
13
  # @param limit [Int] the number of agents to return
15
14
  #
16
15
  def list(offset = 0, limit = 100, unread_only = true)
17
- api_get('', { offset: offset, limit: limit, unreadOnly: unread_only })
16
+ api_get('', offset: offset, limit: limit, unreadOnly: unread_only)
18
17
  end
19
18
 
20
19
  # POST /api/v2/message/id/read
@@ -3,47 +3,54 @@ require_relative './exception'
3
3
  require_relative './parse_time'
4
4
 
5
5
  module Wavefront
6
+ #
7
+ # Methods which help out in the SDK, but may also be useful when
8
+ # coding against the SDK.
9
+ #
6
10
  module Mixins
7
11
  # Return a time as an integer, however it might come in.
8
12
  #
9
- # @param t [Integer, String, Time] timestamp
10
- # @param ms [Boolean] whether to return epoch milliseconds.
13
+ # @param time [Integer, String, Time] timestamp
14
+ # @param in_ms [Boolean] whether to return epoch milliseconds.
11
15
  # Passing in an integer timestamp returns itself, regardless
12
16
  # of this value
13
17
  # @return [Integer] epoch time in seconds
14
18
  # @raise Wavefront::InvalidTimestamp
15
19
  #
16
- def parse_time(t, ms = false)
17
- return relative_time(t, ms) if t =~ /^[\-+]/
18
- ParseTime.new(t, ms).parse!
20
+ def parse_time(time, in_ms = false)
21
+ return relative_time(time, in_ms) if time =~ /^[\-+]/
22
+ ParseTime.new(time, in_ms).parse!
19
23
  end
20
24
 
21
- # Return a timetamp described by the given string. That is,
25
+ # Return a timestamp described by the given string. That is,
22
26
  # '+5m' is five minutes in the future, and '-.1h' is half an
23
27
  # hour ago.
24
28
  #
25
- # @param t [String] relative time string. Must begin with + or
29
+ # @param time [String] relative time string. Must begin with + or
26
30
  # -, followed by a number, finished with a lower-case time
27
31
  # unit identifier. See #time_multiplier
32
+ # @param in_ms [Boolean] whether to return epoch milliseconds.
33
+ # Passing in an integer timestamp returns itself, regardless
34
+ # of this value
28
35
  # @param ref [Time, DateTime] calculate time relative to this
29
36
  # point. Primarily for easier testing. Defaults to "now".
30
37
  # @return [Integer] integer timestamp
31
38
  # @raise [InvalidRelativeTime] if t does not meet requirements
32
39
  #
33
- def relative_time(t, ms = false, ref = DateTime.now)
34
- ref = ms ? ref.to_datetime.strftime('%Q') : ref.to_time
35
- ref.to_i + parse_relative_time(t, ms)
40
+ def relative_time(time, in_ms = false, ref = Time.now)
41
+ ref = in_ms ? ref.to_datetime.strftime('%Q') : ref.to_time
42
+ ref.to_i + parse_relative_time(time, in_ms)
36
43
  end
37
44
 
38
- def parse_relative_time(t, ms = false)
39
- unless t.start_with?('+') || t.start_with?('-')
45
+ def parse_relative_time(time, in_ms = false)
46
+ unless time.start_with?('+', '-')
40
47
  raise Wavefront::Exception::InvalidRelativeTime
41
48
  end
42
49
 
43
- m = ms ? 1000 : 1
50
+ m = in_ms ? 1000 : 1
44
51
 
45
- t = t[1..-1] if t.start_with?('+')
46
- match = t.match(/^(-?\d*\.?\d*)([smhdwy])$/)
52
+ time = time[1..-1] if time.start_with?('+')
53
+ match = time.match(/^(-?\d*\.?\d*)([smhdwy])$/)
47
54
  (match[1].to_f * time_multiplier(match[2]) * m).to_i
48
55
  rescue NoMethodError
49
56
  raise Wavefront::Exception::InvalidRelativeTime
@@ -61,7 +68,7 @@ module Wavefront
61
68
  # @raise InvalidTimeUnit if the suffix is unknown
62
69
  #
63
70
  def time_multiplier(suffix)
64
- u = { s: 1, m: 60, h: 3600, d: 86400, w: 604800, y: 31536000 }
71
+ u = { s: 1, m: 60, h: 3600, d: 86_400, w: 604_800, y: 31_536_000 }
65
72
 
66
73
  return u[suffix.to_sym] if u.key?(suffix.to_sym)
67
74
  raise Wavefront::Exception::InvalidTimeUnit
@@ -72,19 +79,17 @@ end
72
79
  # Extensions to stdlib Hash
73
80
  #
74
81
  class Hash
75
-
76
82
  # Convert a tag hash into a string. The quoting is recommended in
77
83
  # the WF wire-format guide. No validation is performed here.
78
84
  #
79
85
  def to_wf_tag
80
- self.map { |k, v| "#{k}=\"#{v}\"" }.join(' ')
86
+ map { |k, v| "#{k}=\"#{v}\"" }.join(' ')
81
87
  end
82
88
  end
83
89
 
84
90
  # Extensions to stdlib Array
85
91
  #
86
92
  class Array
87
-
88
93
  # Join strings together to make a URI path in a way that is more
89
94
  # flexible than URI::Join. Removes multiple and trailing
90
95
  # separators. Does not have to produce fully qualified paths. Has
@@ -93,6 +98,6 @@ class Array
93
98
  # @return [String] a URI path
94
99
  #
95
100
  def uri_concat
96
- self.join('/').squeeze('/').sub(/\/$/, '').sub(/\/\?/, '?')
101
+ join('/').squeeze('/').sub(%r{\/$}, '').sub(%r{\/\?}, '?')
97
102
  end
98
103
  end