acfs 1.0.0.dev.1.b305 → 1.0.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 (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