acfs 1.0.0.dev.1.b305 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +5 -13
  2. data/CHANGELOG.md +64 -0
  3. data/README.md +2 -2
  4. data/acfs.gemspec +4 -4
  5. data/lib/acfs.rb +7 -5
  6. data/lib/acfs/adapter/base.rb +0 -2
  7. data/lib/acfs/adapter/typhoeus.rb +17 -13
  8. data/lib/acfs/collections/paginatable.rb +10 -10
  9. data/lib/acfs/configuration.rb +4 -5
  10. data/lib/acfs/errors.rb +10 -9
  11. data/lib/acfs/global.rb +16 -7
  12. data/lib/acfs/location.rb +11 -11
  13. data/lib/acfs/middleware/base.rb +1 -2
  14. data/lib/acfs/middleware/json.rb +27 -0
  15. data/lib/acfs/middleware/logger.rb +0 -2
  16. data/lib/acfs/middleware/msgpack.rb +30 -0
  17. data/lib/acfs/middleware/print.rb +0 -2
  18. data/lib/acfs/middleware/serializer.rb +39 -0
  19. data/lib/acfs/operation.rb +5 -5
  20. data/lib/acfs/request.rb +4 -4
  21. data/lib/acfs/request/callbacks.rb +2 -3
  22. data/lib/acfs/resource.rb +2 -2
  23. data/lib/acfs/resource/attributes.rb +10 -37
  24. data/lib/acfs/resource/attributes/base.rb +10 -19
  25. data/lib/acfs/resource/attributes/boolean.rb +10 -8
  26. data/lib/acfs/resource/attributes/date_time.rb +6 -9
  27. data/lib/acfs/resource/attributes/dict.rb +37 -0
  28. data/lib/acfs/resource/attributes/float.rb +11 -5
  29. data/lib/acfs/resource/attributes/integer.rb +7 -5
  30. data/lib/acfs/resource/attributes/list.rb +13 -6
  31. data/lib/acfs/resource/attributes/string.rb +3 -5
  32. data/lib/acfs/resource/attributes/uuid.rb +8 -17
  33. data/lib/acfs/resource/loadable.rb +0 -1
  34. data/lib/acfs/resource/locatable.rb +0 -4
  35. data/lib/acfs/resource/operational.rb +0 -2
  36. data/lib/acfs/resource/persistence.rb +17 -17
  37. data/lib/acfs/resource/query_methods.rb +3 -5
  38. data/lib/acfs/resource/service.rb +0 -2
  39. data/lib/acfs/resource/validation.rb +0 -2
  40. data/lib/acfs/response.rb +1 -2
  41. data/lib/acfs/response/formats.rb +1 -2
  42. data/lib/acfs/response/status.rb +3 -5
  43. data/lib/acfs/runner.rb +21 -11
  44. data/lib/acfs/service.rb +4 -6
  45. data/lib/acfs/service/middleware.rb +20 -30
  46. data/lib/acfs/service/middleware/stack.rb +63 -0
  47. data/lib/acfs/singleton_resource.rb +0 -2
  48. data/lib/acfs/stub.rb +30 -21
  49. data/lib/acfs/util.rb +1 -1
  50. data/lib/acfs/version.rb +4 -2
  51. data/spec/acfs/adapter/typhoeus_spec.rb +12 -4
  52. data/spec/acfs/collection_spec.rb +45 -33
  53. data/spec/acfs/configuration_spec.rb +9 -1
  54. data/spec/acfs/global_spec.rb +21 -3
  55. data/spec/acfs/middleware/json_spec.rb +63 -0
  56. data/spec/acfs/middleware/msgpack_spec.rb +60 -0
  57. data/spec/acfs/operation_spec.rb +10 -0
  58. data/spec/acfs/request/callbacks_spec.rb +8 -8
  59. data/spec/acfs/request_spec.rb +5 -5
  60. data/spec/acfs/resource/attributes/boolean_spec.rb +40 -9
  61. data/spec/acfs/resource/attributes/date_time_spec.rb +29 -35
  62. data/spec/acfs/resource/attributes/dict_spec.rb +75 -0
  63. data/spec/acfs/resource/attributes/float_spec.rb +48 -9
  64. data/spec/acfs/resource/attributes/integer_spec.rb +34 -0
  65. data/spec/acfs/resource/attributes/list_spec.rb +43 -19
  66. data/spec/acfs/resource/attributes/uuid_spec.rb +31 -54
  67. data/spec/acfs/resource/attributes_spec.rb +17 -31
  68. data/spec/acfs/resource/locatable_spec.rb +2 -2
  69. data/spec/acfs/resource/persistance_spec.rb +65 -34
  70. data/spec/acfs/resource/query_methods_spec.rb +87 -87
  71. data/spec/acfs/resource/validation_spec.rb +4 -5
  72. data/spec/acfs/response/formats_spec.rb +1 -1
  73. data/spec/acfs/response/status_spec.rb +1 -1
  74. data/spec/acfs/runner_spec.rb +28 -3
  75. data/spec/acfs/service/middleware_spec.rb +4 -20
  76. data/spec/acfs/service_spec.rb +3 -5
  77. data/spec/acfs/singleton_resource_spec.rb +1 -2
  78. data/spec/acfs/stub_spec.rb +137 -22
  79. data/spec/acfs_spec.rb +22 -19
  80. data/spec/spec_helper.rb +2 -1
  81. data/spec/support/service.rb +10 -6
  82. data/spec/support/shared/find_callbacks.rb +7 -7
  83. metadata +37 -30
  84. data/lib/acfs/middleware/json_decoder.rb +0 -16
  85. data/lib/acfs/middleware/json_encoder.rb +0 -20
  86. data/lib/acfs/middleware/msgpack_decoder.rb +0 -26
  87. data/lib/acfs/middleware/msgpack_encoder.rb +0 -19
  88. data/spec/acfs/middleware/json_decoder_spec.rb +0 -45
  89. data/spec/acfs/middleware/msgpack_decoder_spec.rb +0 -36
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- YTU2MGNhOGYzMzZiYWQyMWZjMDc2ZDA1ZmI0OTUxNTJkMDEzNTI2OA==
5
- data.tar.gz: !binary |-
6
- N2QwNTZiNDBiZDc4NjJhNjc3NjU3M2YxOTI4MzY2YWM4ZGZjMzE0MA==
2
+ SHA1:
3
+ metadata.gz: 6d20f4360733b38c6a3fde5716cf43ff586e7579
4
+ data.tar.gz: b3f8ba827e8813e21182d1b48d3e17ab4b8e1f89
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- MmU2NDdiNzRkODE4NTQzM2I4MDIzY2QwYTA2OWE3NjUwZGMwYTUyZmUwMGE5
10
- OTBiMjY4ZDE4ZTJjNDk4YjEwZjVjYjEzMGJiNzNkZDY3Y2IxMWM3Y2VhN2Q1
11
- M2I1OWI0NTVlODIxMjFiYzJhYTYwZTZjMTI3M2ZmMTQxYjBkYzI=
12
- data.tar.gz: !binary |-
13
- Zjk4MzhhNGM0YzNjNmY4ZDAzOWFiYTE2MzViYTdhM2QxMTc0ZTI3MzJkMmI3
14
- MThkZDNlYWFiM2FjYmE4MWVkY2I5N2RlZTMwYjA4OGE5ZTZmMmUzM2MxZjUz
15
- ZTZkZTNhNmUwNmEyYTIzZGJhZDk0ZjgyN2Q2ZjAzMjkzMzdkMzA=
6
+ metadata.gz: 0841dd869d9e38ae2cc009c80fa7c9a327f970ee35ec3011f535a5f1f0f43bf6fd086efd1d16256793f8c80abeb6db6962ab7459d3c123f405f62b457639effc
7
+ data.tar.gz: bd81043d09374bbd5984120563c3425441fda4939fcd3154182aed6e28bd78fb0b6118025c17003ff642c274657ab575bf420045d8bbfd468b0eadaaa79a9cab
@@ -1,5 +1,69 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.0
4
+
5
+ * Switch to first non-development major as it's long time used in production.
6
+ * Fix NewRelic RPM inference with middleware stack inherited from `ActionDispatch::MiddlewareStack`.
7
+
8
+ ## 0.48.0
9
+
10
+ * Remove #attribute_types broke since f7e4109 (Sep 2013, v0.23)
11
+ * Fix attribute inheritance on subclassing broken since commit 7cf1d11 (Apr 2014, v0.43)
12
+
13
+ ## 0.47.0
14
+
15
+ * Change blank value handling of dict and list type (0a12ef1)
16
+
17
+ ## 0.46.0
18
+
19
+ * Rework types system (#39)
20
+
21
+ ## 0.45.0
22
+
23
+ * Fetching multiple records (`find(ary)`) is stable now, but untested (#38)
24
+ * Middleware stack is build on ActionDispatch::MiddlewareStack now
25
+ * Deprecate legacy middleware names (xyEncoder, xyDecoder)
26
+
27
+ ## 0.44.0
28
+
29
+ * Add option to configure adapter creation and pass option to typhoeus adapter e.g.
30
+ limiting concurrency.
31
+
32
+ ## 0.43.2
33
+
34
+ * add `total_count` for paginated collections
35
+
36
+ ## 0.43.1
37
+
38
+ * Fix `:with` condition matching on stubs
39
+
40
+ ## 0.43.0
41
+
42
+ * Remove `Acfs::Model` (inherit from `Acfs::Resource`)
43
+ * Stub does only a partial match of `:with` attributes now
44
+ * Allow blocks as stub `:return`s
45
+
46
+ ## 0.42.0
47
+
48
+ * Add simple dict attribute type
49
+
50
+ ## 0.40.0
51
+
52
+ * Change `Resource#persisted?` to return true if it is not new
53
+
54
+ ## 0.39.1
55
+
56
+ * Fix automatic path parameter handling for #destroy
57
+
58
+ ## 0.39.0
59
+
60
+ * Add new event acfs.operation.before_process
61
+
62
+ ## 0.38.0
63
+
64
+ * Allow middlewares to abort request processing
65
+ * Allow middlewares to receive the request operation object (via the request)
66
+
3
67
  ## 0.37.0
4
68
 
5
69
  * Add Acfs.on
data/README.md CHANGED
@@ -250,8 +250,8 @@ it 'should find user number one' do
250
250
  expect(user.name).to be == 'John Smith'
251
251
  expect(user.age).to be == 32
252
252
 
253
- expect(@stub).to has_called
254
- expect(@stub).to_not have_called 5.times
253
+ expect(@stub).to be_called
254
+ expect(@stub).to_not be_called 5.times
255
255
  end
256
256
 
257
257
  it 'should not find user number two' do
@@ -8,13 +8,13 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Acfs::VERSION
9
9
  spec.authors = ['Jan Graichen']
10
10
  spec.email = %w(jg@altimos.de)
11
- spec.description = %q{API Client For Services}
12
- spec.summary = %q{An abstract API base client for service oriented application.}
11
+ spec.description = 'API Client For Services'
12
+ spec.summary = 'An abstract API base client for service oriented application.'
13
13
  spec.homepage = 'https://github.com/jgraichen/acfs'
14
14
  spec.license = 'MIT'
15
15
 
16
16
  spec.files = Dir['**/*'].grep(%r{^((bin|lib|test|spec|features)/|.*\.gemspec|.*LICENSE.*|.*README.*|.*CHANGELOG.*)})
17
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.executables = spec.files.grep(%r{^bin/}) {|f| File.basename(f) }
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = %w(lib)
20
20
 
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
24
24
  spec.add_runtime_dependency 'multi_json'
25
25
 
26
26
  # Bundle update w/o version resolves to 0.3.3 ...
27
- spec.add_runtime_dependency 'typhoeus', '>= 0.6.5'
27
+ spec.add_runtime_dependency 'typhoeus', '~> 1.0'
28
28
 
29
29
  spec.add_runtime_dependency 'rack'
30
30
 
@@ -30,13 +30,16 @@ module Acfs
30
30
  module Middleware
31
31
  extend ActiveSupport::Autoload
32
32
  require 'acfs/middleware/base'
33
+ require 'acfs/middleware/serializer'
33
34
 
34
35
  autoload :Print
35
36
  autoload :Logger
36
- autoload :JsonDecoder
37
- autoload :MessagePackDecoder, 'acfs/middleware/msgpack_decoder'
38
- autoload :JsonEncoder
39
- autoload :MessagePackEncoder, 'acfs/middleware/msgpack_encoder'
37
+ autoload :JSON
38
+ autoload :JsonDecoder, 'acfs/middleware/json'
39
+ autoload :JsonEncoder, 'acfs/middleware/json'
40
+ autoload :MessagePack, 'acfs/middleware/msgpack'
41
+ autoload :MessagePackDecoder, 'acfs/middleware/msgpack'
42
+ autoload :MessagePackEncoder, 'acfs/middleware/msgpack'
40
43
  end
41
44
 
42
45
  module Adapter
@@ -44,4 +47,3 @@ module Acfs
44
47
  require 'acfs/adapter/typhoeus'
45
48
  end
46
49
  end
47
-
@@ -1,10 +1,8 @@
1
1
  module Acfs::Adapter
2
-
3
2
  # Base adapter handling operation queuing
4
3
  # and processing.
5
4
  #
6
5
  class Base
7
-
8
6
  # Start processing queued requests.
9
7
  #
10
8
  def start
@@ -2,10 +2,12 @@ require 'typhoeus'
2
2
 
3
3
  module Acfs
4
4
  module Adapter
5
-
6
5
  # Adapter for Typhoeus.
7
6
  #
8
7
  class Typhoeus < Base
8
+ def initialize(**kwargs)
9
+ @options = kwargs
10
+ end
9
11
 
10
12
  def start
11
13
  hydra.run
@@ -14,9 +16,7 @@ module Acfs
14
16
  raise
15
17
  end
16
18
 
17
- def abort
18
- hydra.abort
19
- end
19
+ delegate :abort, to: :hydra
20
20
 
21
21
  def run(request)
22
22
  convert_request(request).run
@@ -26,17 +26,21 @@ module Acfs
26
26
  hydra.queue convert_request request
27
27
  end
28
28
 
29
- protected
29
+ protected
30
+
30
31
  def hydra
31
- @hydra ||= ::Typhoeus::Hydra.new
32
+ @hydra ||= ::Typhoeus::Hydra.new(**@options)
32
33
  end
33
34
 
34
35
  def convert_request(req)
35
36
  request = ::Typhoeus::Request.new req.url,
36
- method: req.method,
37
- params: req.params,
38
- headers: req.headers,
39
- body: req.body
37
+ method: req.method,
38
+ params: req.params,
39
+ headers: req.headers.merge(
40
+ 'Expect' => '',
41
+ 'Transfer-Encoding' => ''
42
+ ),
43
+ body: req.body
40
44
 
41
45
  request.on_complete do |response|
42
46
  req.complete! convert_response(req, response)
@@ -47,9 +51,9 @@ module Acfs
47
51
 
48
52
  def convert_response(request, response)
49
53
  Acfs::Response.new request,
50
- status: response.code,
51
- headers: response.headers,
52
- body: response.body
54
+ status: response.code,
55
+ headers: response.headers,
56
+ body: response.body
53
57
  end
54
58
  end
55
59
  end
@@ -1,15 +1,14 @@
1
1
  module Acfs::Collections
2
-
3
2
  #
4
3
  module Paginatable
5
4
  extend ActiveSupport::Concern
6
5
 
7
6
  included do
8
- def self.operation(action, opts = {}, &block)
7
+ def self.operation(_action, opts = {}, &_block)
9
8
  opts[:url]
10
9
  end
11
10
 
12
- attr_reader :total_pages, :current_page
11
+ attr_reader :total_pages, :current_page, :total_count
13
12
  end
14
13
 
15
14
  def process_response(response)
@@ -34,12 +33,9 @@ module Acfs::Collections
34
33
  end
35
34
 
36
35
  def page(rel, &block)
37
- if relations[rel]
38
- @resource_class.all nil, url: relations[rel], &block
39
- else
40
- # raise ArgumentError.new "No relative page `#{rel}'."
41
- nil
42
- end
36
+ return unless relations[rel]
37
+
38
+ @resource_class.all nil, url: relations[rel], &block
43
39
  end
44
40
 
45
41
  private
@@ -53,13 +49,17 @@ module Acfs::Collections
53
49
  @total_pages = Integer(headers['X-Total-Pages'])
54
50
  end
55
51
 
52
+ if headers['X-Total-Count']
53
+ @total_count = Integer(headers['X-Total-Count'])
54
+ end
55
+
56
56
  setup_links headers['Link'] if headers['Link']
57
57
  end
58
58
 
59
59
  def setup_links(links)
60
60
  links.split(/,\s+/).each do |link|
61
61
  if link =~ /^\s*<([^>]+)>.*\s+rel="([\w_-]+)".*$/
62
- relations[$2] = $1
62
+ relations[Regexp.last_match[2]] = Regexp.last_match[1]
63
63
  end
64
64
  end
65
65
  end
@@ -2,11 +2,11 @@ require 'uri'
2
2
  require 'yaml'
3
3
 
4
4
  module Acfs
5
-
6
5
  # Acfs configuration is used to locate services and get their base URLs.
7
6
  #
8
7
  class Configuration
9
8
  attr_reader :locations
9
+ attr_accessor :adapter
10
10
 
11
11
  # @api private
12
12
  def initialize
@@ -28,7 +28,7 @@ module Acfs
28
28
  if block.arity > 0
29
29
  block.call self
30
30
  else
31
- instance_eval &block
31
+ instance_eval(&block)
32
32
  end
33
33
  end
34
34
 
@@ -64,10 +64,10 @@ module Acfs
64
64
  # @return [undefined]
65
65
  #
66
66
  def load(filename)
67
- config = YAML::load File.read filename
67
+ config = YAML.load File.read filename
68
68
  env = ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development'
69
69
 
70
- config = config[env] if config.has_key? env
70
+ config = config[env] if config.key? env
71
71
  config.each do |key, value|
72
72
  case key
73
73
  when 'services' then load_services value
@@ -88,7 +88,6 @@ module Acfs
88
88
  end
89
89
 
90
90
  class << self
91
-
92
91
  # @api private
93
92
  #
94
93
  # Return current configuration object.
@@ -1,5 +1,4 @@
1
1
  module Acfs
2
-
3
2
  # Acfs base error.
4
3
  #
5
4
  class Error < StandardError
@@ -23,20 +22,20 @@ module Acfs
23
22
  message << ": #{response.code}"
24
23
  if response.data
25
24
  message << "\n with content:\n "
26
- message << response.data.map{|k,v| "#{k.inspect}: #{v.inspect}"}.join("\n ")
25
+ message << response.data.map {|k, v| "#{k.inspect}: #{v.inspect}" }.join("\n ")
27
26
  end
28
27
  if response.headers.any?
29
28
  message << "\n with headers:\n "
30
- message << response.headers.map{|k,v| "#{k}: #{v}"}.join("\n ")
29
+ message << response.headers.map {|k, v| "#{k}: #{v}" }.join("\n ")
31
30
  end
32
31
  message << "\nbased on request: #{response.request.method.upcase} #{response.request.url} #{response.request.format}"
33
32
  if response.request.data
34
33
  message << "\n with content:\n "
35
- message << response.request.data.map{|k,v| "#{k.inspect}: #{v.inspect}"}.join("\n ")
34
+ message << response.request.data.map {|k, v| "#{k.inspect}: #{v.inspect}" }.join("\n ")
36
35
  end
37
36
  if response.request.headers.any?
38
37
  message << "\n with headers:\n "
39
- message << response.request.headers.map{|k,v| "#{k}: #{v}"}.join("\n ")
38
+ message << response.request.headers.map {|k, v| "#{k}: #{v}" }.join("\n ")
40
39
  end
41
40
  end
42
41
  super opts, message
@@ -47,12 +46,14 @@ module Acfs
47
46
  attr_reader :stubs, :operation
48
47
 
49
48
  def initialize(opts = {})
49
+ require 'pp'
50
+
50
51
  @stubs = opts.delete :stubs
51
52
  @operation = opts.delete :operation
52
53
 
53
- super opts, 'Ambiguous stubs.'
54
+ super opts, "Ambiguous stubs for #{operation.action} on #{operation.resource}.\n" +
55
+ stubs.map {|s| " #{s.opts.pretty_inspect}" }.join
54
56
  end
55
-
56
57
  end
57
58
 
58
59
  # Resource not found error raised on a 404 response
@@ -67,7 +68,7 @@ module Acfs
67
68
  def initialize(opts = {})
68
69
  @errors = opts.delete :errors
69
70
  @resource = opts.delete :resource
70
- opts[:message] ||= @errors.map{ |k,v| "#{k}: #{v.join ', '}" }.join ', ' if @errors.is_a? Hash
71
+ opts[:message] ||= @errors.map {|k, v| "#{k}: #{v.join ', '}" }.join ', ' if @errors.is_a? Hash
71
72
  opts[:message] ||= @errors.join ', ' if @errors.is_a? Array
72
73
  super
73
74
  end
@@ -99,7 +100,7 @@ module Acfs
99
100
  def initialize(opts = {})
100
101
  @base_class = opts.delete :base_class
101
102
  @type_name = opts.delete :type_name
102
- opts[:message] = "Recieved ressource type `#{type_name}` is no subclass of #{base_class}"
103
+ opts[:message] = "Received resource type `#{type_name}` is no subclass of #{base_class}"
103
104
  super
104
105
  end
105
106
  end
@@ -1,14 +1,22 @@
1
1
  module Acfs
2
-
2
+ #
3
3
  # Global Acfs module methods.
4
4
  #
5
5
  module Global
6
-
6
+ #
7
7
  # @api private
8
8
  # @return [Runner]
9
9
  #
10
10
  def runner
11
- @runner ||= Runner.new Adapter::Typhoeus.new
11
+ Thread.current[:acfs_runner] ||= begin
12
+ adapter = Configuration.current.adapter
13
+
14
+ if adapter
15
+ Runner.new adapter.call
16
+ else
17
+ Runner.new Adapter::Typhoeus.new
18
+ end
19
+ end
12
20
  end
13
21
 
14
22
  # @api public
@@ -59,9 +67,10 @@ module Acfs
59
67
  # Acfs.add_callback(user, &callback_two)
60
68
  #
61
69
  def add_callback(resource, &block)
62
- raise ArgumentError.new "Given resource is not an Acfs resource but "\
63
- "a: #{resource.class.name}" \
64
- unless resource.respond_to?(:__callbacks__)
70
+ unless resource.respond_to?(:__callbacks__)
71
+ raise ArgumentError.new 'Given resource is not an Acfs resource ' \
72
+ "delegator but a: #{resource.class.name}"
73
+ end
65
74
  return false if block.nil?
66
75
 
67
76
  if resource.loaded?
@@ -73,7 +82,7 @@ module Acfs
73
82
 
74
83
  def on(*resources)
75
84
  resources.each do |resource|
76
- add_callback resource do |ret|
85
+ add_callback resource do |_|
77
86
  yield(*resources) unless resources.any? {|res| !res.loaded? }
78
87
  end
79
88
  end
@@ -1,5 +1,4 @@
1
1
  module Acfs
2
-
3
2
  # @api private
4
3
  #
5
4
  # Describes a URL with placeholders.
@@ -7,17 +6,17 @@ module Acfs
7
6
  class Location
8
7
  attr_reader :arguments, :raw, :struct, :args
9
8
 
10
- REGEXP= /^:([A-z][A-z0-9_]*)$/
9
+ REGEXP = /^:([A-z][A-z0-9_]*)$/
11
10
 
12
11
  def initialize(uri, args = {})
13
12
  @raw = URI.parse uri
14
13
  @args = args
15
- @struct = raw.path.split('/').reject(&:empty?).map{|s| s =~ REGEXP ? $1.to_sym : s }
16
- @arguments = struct.select{|s| Symbol === s }
14
+ @struct = raw.path.split('/').reject(&:empty?).map {|s| s =~ REGEXP ? Regexp.last_match[1].to_sym : s }
15
+ @arguments = struct.select {|s| s.is_a?(Symbol) }
17
16
  end
18
17
 
19
18
  def build(args = {})
20
- unless Hash === args
19
+ unless args.is_a?(Hash)
21
20
  raise ArgumentError.new "URI path arguments must be a hash, `#{args.inspect}' given."
22
21
  end
23
22
 
@@ -25,8 +24,8 @@ module Acfs
25
24
  end
26
25
 
27
26
  def extract_from(*args)
28
- args = Hash.new.tap do |collect|
29
- arguments.each{|key| collect[key] = extract_arg key, args }
27
+ args = {}.tap do |collect|
28
+ arguments.each {|key| collect[key] = extract_arg key, args }
30
29
  end
31
30
 
32
31
  build args
@@ -34,7 +33,7 @@ module Acfs
34
33
 
35
34
  def str
36
35
  uri = raw.dup
37
- uri.path = URI.escape '/' + struct.map{|s| lookup_arg(s, args) }.join('/')
36
+ uri.path = URI.escape '/' + struct.map {|s| lookup_arg(s, args) }.join('/')
38
37
  uri.to_s
39
38
  end
40
39
 
@@ -44,16 +43,17 @@ module Acfs
44
43
  alias_method :to_s, :raw_uri
45
44
 
46
45
  private
46
+
47
47
  def extract_arg(key, hashes)
48
48
  hashes.each_with_index do |hash, index|
49
- return (index == 0 ? hash.delete(key) : hash.fetch(key)) if hash.has_key?(key)
49
+ return (index == 0 ? hash.delete(key) : hash.fetch(key)) if hash.key?(key)
50
50
  end
51
51
 
52
52
  nil
53
53
  end
54
54
 
55
55
  def lookup_arg(arg, args)
56
- Symbol === arg ? lookup_replacement(arg, args) : arg
56
+ arg.is_a?(Symbol) ? lookup_replacement(arg, args) : arg
57
57
  end
58
58
 
59
59
  def lookup_replacement(sym, args)
@@ -67,7 +67,7 @@ module Acfs
67
67
  args.fetch(sym.to_s) do
68
68
  args.fetch(sym) do
69
69
  if args[:raise].nil? || args[:raise]
70
- raise ArgumentError.new "URI path argument `#{sym}' missing on `#{to_s}'. Given: `#{args}.inspect'"
70
+ raise ArgumentError.new "URI path argument `#{sym}' missing on `#{self}'. Given: `#{args}.inspect'"
71
71
  else
72
72
  ":#{sym}"
73
73
  end