acfs 1.3.0 → 1.4.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +50 -0
- data/README.md +3 -4
- data/acfs.gemspec +19 -10
- data/lib/acfs.rb +2 -0
- data/lib/acfs/adapter/base.rb +6 -8
- data/lib/acfs/adapter/typhoeus.rb +26 -7
- data/lib/acfs/collection.rb +2 -1
- data/lib/acfs/collections/paginatable.rb +2 -1
- data/lib/acfs/configuration.rb +14 -7
- data/lib/acfs/errors.rb +33 -12
- data/lib/acfs/global.rb +12 -2
- data/lib/acfs/location.rb +9 -5
- data/lib/acfs/middleware/base.rb +5 -1
- data/lib/acfs/middleware/json.rb +2 -0
- data/lib/acfs/middleware/logger.rb +2 -0
- data/lib/acfs/middleware/msgpack.rb +2 -0
- data/lib/acfs/middleware/print.rb +2 -0
- data/lib/acfs/middleware/serializer.rb +2 -0
- data/lib/acfs/operation.rb +5 -3
- data/lib/acfs/request.rb +3 -0
- data/lib/acfs/request/callbacks.rb +5 -1
- data/lib/acfs/resource.rb +2 -0
- data/lib/acfs/resource/attributes.rb +3 -2
- data/lib/acfs/resource/attributes/base.rb +2 -1
- data/lib/acfs/resource/attributes/boolean.rb +2 -0
- data/lib/acfs/resource/attributes/date_time.rb +2 -1
- data/lib/acfs/resource/attributes/dict.rb +2 -0
- data/lib/acfs/resource/attributes/float.rb +5 -3
- data/lib/acfs/resource/attributes/integer.rb +2 -0
- data/lib/acfs/resource/attributes/list.rb +2 -0
- data/lib/acfs/resource/attributes/string.rb +2 -0
- data/lib/acfs/resource/attributes/uuid.rb +4 -3
- data/lib/acfs/resource/dirty.rb +2 -0
- data/lib/acfs/resource/initialization.rb +2 -0
- data/lib/acfs/resource/loadable.rb +2 -0
- data/lib/acfs/resource/locatable.rb +10 -6
- data/lib/acfs/resource/operational.rb +2 -1
- data/lib/acfs/resource/persistence.rb +7 -4
- data/lib/acfs/resource/query_methods.rb +5 -3
- data/lib/acfs/resource/service.rb +3 -1
- data/lib/acfs/resource/validation.rb +3 -1
- data/lib/acfs/response.rb +2 -0
- data/lib/acfs/response/formats.rb +2 -0
- data/lib/acfs/response/status.rb +3 -1
- data/lib/acfs/rspec.rb +2 -0
- data/lib/acfs/runner.rb +6 -1
- data/lib/acfs/service.rb +8 -2
- data/lib/acfs/service/middleware.rb +2 -0
- data/lib/acfs/service/middleware/stack.rb +5 -3
- data/lib/acfs/singleton_resource.rb +4 -2
- data/lib/acfs/stub.rb +33 -11
- data/lib/acfs/util.rb +2 -0
- data/lib/acfs/version.rb +3 -1
- data/lib/acfs/yard.rb +1 -0
- data/spec/acfs/adapter/typhoeus_spec.rb +30 -3
- data/spec/acfs/collection_spec.rb +7 -5
- data/spec/acfs/configuration_spec.rb +2 -0
- data/spec/acfs/global_spec.rb +48 -1
- data/spec/acfs/location_spec.rb +25 -0
- data/spec/acfs/middleware/json_spec.rb +2 -0
- data/spec/acfs/middleware/msgpack_spec.rb +2 -0
- data/spec/acfs/operation_spec.rb +2 -0
- data/spec/acfs/request/callbacks_spec.rb +2 -0
- data/spec/acfs/request_spec.rb +3 -1
- data/spec/acfs/resource/attributes/boolean_spec.rb +2 -0
- data/spec/acfs/resource/attributes/date_time_spec.rb +2 -0
- data/spec/acfs/resource/attributes/dict_spec.rb +4 -2
- data/spec/acfs/resource/attributes/float_spec.rb +2 -0
- data/spec/acfs/resource/attributes/integer_spec.rb +2 -0
- data/spec/acfs/resource/attributes/list_spec.rb +5 -3
- data/spec/acfs/resource/attributes/uuid_spec.rb +2 -0
- data/spec/acfs/resource/attributes_spec.rb +6 -4
- data/spec/acfs/resource/dirty_spec.rb +2 -0
- data/spec/acfs/resource/initialization_spec.rb +8 -2
- data/spec/acfs/resource/loadable_spec.rb +2 -0
- data/spec/acfs/resource/locatable_spec.rb +2 -0
- data/spec/acfs/resource/persistance_spec.rb +10 -4
- data/spec/acfs/resource/query_methods_spec.rb +25 -18
- data/spec/acfs/resource/validation_spec.rb +2 -0
- data/spec/acfs/response/formats_spec.rb +3 -1
- data/spec/acfs/response/status_spec.rb +2 -0
- data/spec/acfs/runner_spec.rb +6 -8
- data/spec/acfs/service/middleware_spec.rb +2 -0
- data/spec/acfs/service_spec.rb +3 -1
- data/spec/acfs/singleton_resource_spec.rb +2 -0
- data/spec/acfs/stub_spec.rb +2 -0
- data/spec/acfs_spec.rb +2 -0
- data/spec/spec_helper.rb +11 -6
- data/spec/support/hash.rb +2 -0
- data/spec/support/response.rb +2 -0
- data/spec/support/service.rb +1 -0
- data/spec/support/shared/find_callbacks.rb +2 -0
- metadata +12 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6f998ff3e28801676c732fa44df93e18f651e96eb986c857c61b7f25b312a2c1
|
|
4
|
+
data.tar.gz: a122064cb630a664489629ef658d5ecde917ced4cdc43a600b49d0e18e00bea7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7801c96d794f08ad03b9ad204f8e7c8b611300922b12714ce7864a33c5a6268bc47c42e66b86c410358f17a0439d382c358ba15283eee07ff092d19a1f86a8be
|
|
7
|
+
data.tar.gz: 78b2c804251fb6aaee270d9c894ff36b7b8dc7bb777148de55963255847fc28adcdbff9c7132352c5448bef7b9980fd72e6a14ffceda38540d661aceaf1e5e9d
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,55 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
## Unreleased
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
### New
|
|
9
|
+
|
|
10
|
+
### Changes
|
|
11
|
+
|
|
12
|
+
### Fixes
|
|
13
|
+
|
|
14
|
+
### Breaks
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## 1.4.0 - (2020-06-12)
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
### New
|
|
21
|
+
* Use strict TCP keepalive probing by default (5s/5s)
|
|
22
|
+
* Adapter accepts curl request opts
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## 1.3.4 - (2020-03-22)
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
### Fixes
|
|
29
|
+
* Empty package build for Gem release 1.3.3
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
## 1.3.3 - (2020-03-22)
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
### Changes
|
|
36
|
+
* Improved handling of low-level connection errors and timeouts
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
## 1.3.2 - (2019-09-24)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
### Fixes
|
|
43
|
+
* Fix Acfs.on callbacks for empty find_by results (#42)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 1.3.1 - (2019-07-02)
|
|
49
|
+
|
|
50
|
+
### Fixes
|
|
51
|
+
* Improve URL argument encoding when building resource requests
|
|
52
|
+
|
|
3
53
|
## 1.3.0
|
|
4
54
|
|
|
5
55
|
* Change default error messages to a more compact representation to ease integration with error reporting services.
|
data/README.md
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
# Acfs - *API client for services*
|
|
2
2
|
|
|
3
|
-
[](https://rubygems.org/gems/acfs)
|
|
4
|
+
[](https://travis-ci.org/jgraichen/acfs)
|
|
5
|
+
[](https://github.com/jgraichen/acfs/actions?query=branch%3Amaster)
|
|
5
6
|
[](https://coveralls.io/r/jgraichen/acfs)
|
|
6
|
-
[](https://codeclimate.com/github/jgraichen/acfs)
|
|
7
|
-
[](https://gemnasium.com/jgraichen/acfs)
|
|
8
7
|
[](http://rubydoc.info/github/jgraichen/acfs/master/frames)
|
|
9
8
|
|
|
10
9
|
Acfs is a library to develop API client libraries for single services within a larger service oriented application.
|
data/acfs.gemspec
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
5
|
require 'acfs/version'
|
|
5
6
|
|
|
@@ -7,20 +8,26 @@ Gem::Specification.new do |spec|
|
|
|
7
8
|
spec.name = 'acfs'
|
|
8
9
|
spec.version = Acfs::VERSION
|
|
9
10
|
spec.authors = ['Jan Graichen']
|
|
10
|
-
spec.email = %w
|
|
11
|
-
spec.description = 'API Client For Services'
|
|
12
|
-
spec.summary = 'An abstract API base client for service oriented application.'
|
|
11
|
+
spec.email = %w[jgraichen@altimos.de]
|
|
13
12
|
spec.homepage = 'https://github.com/jgraichen/acfs'
|
|
14
13
|
spec.license = 'MIT'
|
|
14
|
+
spec.description = 'API Client For Services'
|
|
15
|
+
spec.summary = <<~SUMMARY.strip
|
|
16
|
+
An abstract API base client for service oriented application.
|
|
17
|
+
SUMMARY
|
|
18
|
+
|
|
19
|
+
spec.files = Dir['**/*'].grep(%r{
|
|
20
|
+
^((bin|lib|test|spec|features)/|
|
|
21
|
+
.*\.gemspec|.*LICENSE.*|.*README.*|.*CHANGELOG.*)
|
|
22
|
+
}xi)
|
|
15
23
|
|
|
16
|
-
spec.files = Dir['**/*'].grep(%r{^((bin|lib|test|spec|features)/|.*\.gemspec|.*LICENSE.*|.*README.*|.*CHANGELOG.*)})
|
|
17
24
|
spec.executables = spec.files.grep(%r{^bin/}) {|f| File.basename(f) }
|
|
18
25
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
19
|
-
spec.require_paths = %w
|
|
26
|
+
spec.require_paths = %w[lib]
|
|
20
27
|
|
|
21
|
-
spec.add_runtime_dependency 'activesupport', '>= 4.2'
|
|
22
|
-
spec.add_runtime_dependency 'activemodel', '>= 4.2'
|
|
23
28
|
spec.add_runtime_dependency 'actionpack', '>= 4.2'
|
|
29
|
+
spec.add_runtime_dependency 'activemodel', '>= 4.2'
|
|
30
|
+
spec.add_runtime_dependency 'activesupport', '>= 4.2'
|
|
24
31
|
spec.add_runtime_dependency 'multi_json'
|
|
25
32
|
|
|
26
33
|
# Bundle update w/o version resolves to 0.3.3 ...
|
|
@@ -28,10 +35,12 @@ Gem::Specification.new do |spec|
|
|
|
28
35
|
|
|
29
36
|
spec.add_runtime_dependency 'rack'
|
|
30
37
|
|
|
31
|
-
spec.add_development_dependency 'bundler'
|
|
38
|
+
spec.add_development_dependency 'bundler'
|
|
32
39
|
|
|
33
40
|
if ENV['TRAVIS_BUILD_NUMBER'] && !ENV['TRAVIS_TAG']
|
|
34
41
|
# Append travis build number for auto-releases
|
|
42
|
+
# rubocop:disable Gemspec/DuplicatedAssignment
|
|
35
43
|
spec.version = "#{spec.version}.1.b#{ENV['TRAVIS_BUILD_NUMBER']}"
|
|
44
|
+
# rubocop:enable Gemspec/DuplicatedAssignment
|
|
36
45
|
end
|
|
37
46
|
end
|
data/lib/acfs.rb
CHANGED
data/lib/acfs/adapter/base.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Acfs::Adapter
|
|
2
4
|
# Base adapter handling operation queuing
|
|
3
5
|
# and processing.
|
|
@@ -5,22 +7,18 @@ module Acfs::Adapter
|
|
|
5
7
|
class Base
|
|
6
8
|
# Start processing queued requests.
|
|
7
9
|
#
|
|
8
|
-
def start
|
|
9
|
-
end
|
|
10
|
+
def start; end
|
|
10
11
|
|
|
11
12
|
# Abort running and queued requests.
|
|
12
13
|
#
|
|
13
|
-
def abort
|
|
14
|
-
end
|
|
14
|
+
def abort; end
|
|
15
15
|
|
|
16
16
|
# Run request right now skipping queue.
|
|
17
17
|
#
|
|
18
|
-
def run(_)
|
|
19
|
-
end
|
|
18
|
+
def run(_); end
|
|
20
19
|
|
|
21
20
|
# Enqueue request to be run later.
|
|
22
21
|
#
|
|
23
|
-
def queue(_)
|
|
24
|
-
end
|
|
22
|
+
def queue(_); end
|
|
25
23
|
end
|
|
26
24
|
end
|
|
@@ -1,17 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'typhoeus'
|
|
2
4
|
|
|
3
5
|
module Acfs
|
|
4
6
|
module Adapter
|
|
7
|
+
DEFAULT_OPTIONS = {
|
|
8
|
+
tcp_keepalive: true,
|
|
9
|
+
tcp_keepidle: 5,
|
|
10
|
+
tcp_keepintvl: 5
|
|
11
|
+
}.freeze
|
|
12
|
+
|
|
5
13
|
# Adapter for Typhoeus.
|
|
6
14
|
#
|
|
7
15
|
class Typhoeus < Base
|
|
8
|
-
def initialize(**kwargs)
|
|
9
|
-
@
|
|
16
|
+
def initialize(opts: {}, **kwargs)
|
|
17
|
+
@opts = DEFAULT_OPTIONS.merge(opts)
|
|
18
|
+
@kwargs = kwargs
|
|
10
19
|
end
|
|
11
20
|
|
|
12
21
|
def start
|
|
13
22
|
hydra.run
|
|
14
|
-
rescue
|
|
23
|
+
rescue StandardError
|
|
15
24
|
@hydra = nil
|
|
16
25
|
raise
|
|
17
26
|
end
|
|
@@ -29,21 +38,31 @@ module Acfs
|
|
|
29
38
|
protected
|
|
30
39
|
|
|
31
40
|
def hydra
|
|
32
|
-
@hydra ||= ::Typhoeus::Hydra.new(**@
|
|
41
|
+
@hydra ||= ::Typhoeus::Hydra.new(**@kwargs)
|
|
33
42
|
end
|
|
34
43
|
|
|
35
44
|
def convert_request(req)
|
|
36
|
-
|
|
45
|
+
opts = {
|
|
37
46
|
method: req.method,
|
|
38
47
|
params: req.params,
|
|
39
48
|
headers: req.headers.merge(
|
|
40
|
-
'Expect'
|
|
49
|
+
'Expect' => '',
|
|
41
50
|
'Transfer-Encoding' => ''
|
|
42
51
|
),
|
|
43
52
|
body: req.body
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
request = ::Typhoeus::Request.new(req.url, **@opts.merge(opts))
|
|
44
56
|
|
|
45
57
|
request.on_complete do |response|
|
|
46
|
-
|
|
58
|
+
if response.timed_out?
|
|
59
|
+
raise ::Acfs::TimeoutError.new(req)
|
|
60
|
+
elsif response.code.zero?
|
|
61
|
+
# Failed to get HTTP response
|
|
62
|
+
raise ::Acfs::RequestError.new(req, response.return_message)
|
|
63
|
+
else
|
|
64
|
+
req.complete! convert_response(req, response)
|
|
65
|
+
end
|
|
47
66
|
end
|
|
48
67
|
|
|
49
68
|
request
|
data/lib/acfs/collection.rb
CHANGED
data/lib/acfs/configuration.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'uri'
|
|
2
4
|
require 'yaml'
|
|
3
5
|
|
|
@@ -25,7 +27,7 @@ module Acfs
|
|
|
25
27
|
# @return [undefined]
|
|
26
28
|
#
|
|
27
29
|
def configure(&block)
|
|
28
|
-
if block.arity
|
|
30
|
+
if block.arity.positive?
|
|
29
31
|
block.call self
|
|
30
32
|
else
|
|
31
33
|
instance_eval(&block)
|
|
@@ -37,8 +39,12 @@ module Acfs
|
|
|
37
39
|
# @overload locate(service, uri)
|
|
38
40
|
# Configures URL where a service can be reached.
|
|
39
41
|
#
|
|
40
|
-
# @param [Symbol] service
|
|
41
|
-
#
|
|
42
|
+
# @param [Symbol] service
|
|
43
|
+
# Service identity key for service that is reachable under given URL.
|
|
44
|
+
#
|
|
45
|
+
# @param [String] uri
|
|
46
|
+
# URL where service is reachable. Will be passed to {URI.parse}.
|
|
47
|
+
#
|
|
42
48
|
# @return [undefined]
|
|
43
49
|
#
|
|
44
50
|
# @overload locate(service)
|
|
@@ -64,7 +70,7 @@ module Acfs
|
|
|
64
70
|
# @return [undefined]
|
|
65
71
|
#
|
|
66
72
|
def load(filename)
|
|
67
|
-
config = YAML.
|
|
73
|
+
config = YAML.safe_load(File.read(filename), [], [], true)
|
|
68
74
|
env = ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development'
|
|
69
75
|
|
|
70
76
|
config = config[env] if config.key? env
|
|
@@ -95,18 +101,19 @@ module Acfs
|
|
|
95
101
|
# @return [Configuration]
|
|
96
102
|
#
|
|
97
103
|
def current
|
|
98
|
-
@
|
|
104
|
+
@current ||= new
|
|
99
105
|
end
|
|
100
106
|
|
|
101
107
|
# @api private
|
|
102
108
|
#
|
|
103
|
-
# Swap configuration object with given new one. Must be
|
|
109
|
+
# Swap configuration object with given new one. Must be
|
|
110
|
+
# a {Configuration} object.
|
|
104
111
|
#
|
|
105
112
|
# @param [Configuration] configuration
|
|
106
113
|
# @return [undefined]
|
|
107
114
|
#
|
|
108
115
|
def set(configuration)
|
|
109
|
-
@
|
|
116
|
+
@current = configuration if configuration.is_a? Configuration
|
|
110
117
|
end
|
|
111
118
|
end
|
|
112
119
|
end
|
data/lib/acfs/errors.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Acfs
|
|
2
4
|
# Acfs base error.
|
|
3
5
|
#
|
|
@@ -10,6 +12,24 @@ module Acfs
|
|
|
10
12
|
|
|
11
13
|
class UnsupportedOperation < StandardError; end
|
|
12
14
|
|
|
15
|
+
class RequestError < Error
|
|
16
|
+
attr_reader :request
|
|
17
|
+
|
|
18
|
+
def initialize(request, message)
|
|
19
|
+
@request = request
|
|
20
|
+
|
|
21
|
+
message = "#{message}: #{request.method.upcase} #{request.url}"
|
|
22
|
+
|
|
23
|
+
super message: message
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class TimeoutError < RequestError
|
|
28
|
+
def initialize(request)
|
|
29
|
+
super(request, "Timeout reached")
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
13
33
|
# Response error containing the responsible response object.
|
|
14
34
|
#
|
|
15
35
|
class ErroneousResponse < Error
|
|
@@ -17,17 +37,15 @@ module Acfs
|
|
|
17
37
|
|
|
18
38
|
def initialize(opts = {})
|
|
19
39
|
@response = opts[:response]
|
|
20
|
-
|
|
40
|
+
|
|
21
41
|
if response
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
message = 'Received'
|
|
26
|
-
end
|
|
27
|
-
message << " #{response.code} for #{response.request.method.upcase} #{response.request.url} #{response.request.format}"
|
|
42
|
+
message = (opts[:message] ? opts[:message] + ':' : 'Received') +
|
|
43
|
+
" #{response.code} for #{response.request.method.upcase}" \
|
|
44
|
+
" #{response.request.url} #{response.request.format}"
|
|
28
45
|
else
|
|
29
|
-
message
|
|
46
|
+
message = opts[:message] || 'Received erroneous response'
|
|
30
47
|
end
|
|
48
|
+
|
|
31
49
|
super opts, message
|
|
32
50
|
end
|
|
33
51
|
end
|
|
@@ -41,8 +59,11 @@ module Acfs
|
|
|
41
59
|
@stubs = opts.delete :stubs
|
|
42
60
|
@operation = opts.delete :operation
|
|
43
61
|
|
|
44
|
-
|
|
45
|
-
|
|
62
|
+
message = "Ambiguous stubs for #{operation.action} " \
|
|
63
|
+
"on #{operation.resource}.\n" +
|
|
64
|
+
stubs.map {|s| " #{s.opts.pretty_inspect}" }.join
|
|
65
|
+
|
|
66
|
+
super opts, message
|
|
46
67
|
end
|
|
47
68
|
end
|
|
48
69
|
|
|
@@ -51,7 +72,6 @@ module Acfs
|
|
|
51
72
|
class ResourceNotFound < ErroneousResponse
|
|
52
73
|
end
|
|
53
74
|
|
|
54
|
-
#
|
|
55
75
|
class InvalidResource < ErroneousResponse
|
|
56
76
|
attr_reader :errors, :resource
|
|
57
77
|
|
|
@@ -97,7 +117,8 @@ module Acfs
|
|
|
97
117
|
def initialize(opts = {})
|
|
98
118
|
@base_class = opts.delete :base_class
|
|
99
119
|
@type_name = opts.delete :type_name
|
|
100
|
-
opts[:message] = "Received resource type `#{type_name}`
|
|
120
|
+
opts[:message] = "Received resource type `#{type_name}` " \
|
|
121
|
+
"is no subclass of #{base_class}"
|
|
101
122
|
super
|
|
102
123
|
end
|
|
103
124
|
end
|
data/lib/acfs/global.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Acfs
|
|
2
4
|
#
|
|
3
5
|
# Global Acfs module methods.
|
|
@@ -73,7 +75,7 @@ module Acfs
|
|
|
73
75
|
end
|
|
74
76
|
return false if block.nil?
|
|
75
77
|
|
|
76
|
-
if resource.loaded?
|
|
78
|
+
if resource.nil? || resource.loaded?
|
|
77
79
|
block.call resource
|
|
78
80
|
else
|
|
79
81
|
resource.__callbacks__ << block
|
|
@@ -81,9 +83,17 @@ module Acfs
|
|
|
81
83
|
end
|
|
82
84
|
|
|
83
85
|
def on(*resources)
|
|
86
|
+
# If all resources have already been loaded, we run the callback immediately.
|
|
87
|
+
if resources.all? {|res| res.nil? || res.loaded? }
|
|
88
|
+
yield(*resources)
|
|
89
|
+
return
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Otherwise, we add a callback to *each* resource with a guard that ensures
|
|
93
|
+
# that only the very last resource being loaded executes the callback.
|
|
84
94
|
resources.each do |resource|
|
|
85
95
|
add_callback resource do |_|
|
|
86
|
-
yield(*resources)
|
|
96
|
+
yield(*resources) if resources.all? {|res| res.nil? || res.loaded? }
|
|
87
97
|
end
|
|
88
98
|
end
|
|
89
99
|
end
|
data/lib/acfs/location.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Acfs
|
|
2
4
|
# @api private
|
|
3
5
|
#
|
|
@@ -6,7 +8,7 @@ module Acfs
|
|
|
6
8
|
class Location
|
|
7
9
|
attr_reader :arguments, :raw, :struct, :args
|
|
8
10
|
|
|
9
|
-
REGEXP = /^:([A-z][A-z0-9_]*)
|
|
11
|
+
REGEXP = /^:([A-z][A-z0-9_]*)$/.freeze
|
|
10
12
|
|
|
11
13
|
def initialize(uri, args = {})
|
|
12
14
|
@raw = URI.parse uri
|
|
@@ -33,20 +35,22 @@ module Acfs
|
|
|
33
35
|
|
|
34
36
|
def str
|
|
35
37
|
uri = raw.dup
|
|
36
|
-
uri.path =
|
|
38
|
+
uri.path = '/' + struct.map {|s| lookup_arg(s, args) }.join('/')
|
|
37
39
|
uri.to_s
|
|
38
40
|
end
|
|
39
41
|
|
|
40
42
|
def raw_uri
|
|
41
43
|
raw.to_s
|
|
42
44
|
end
|
|
43
|
-
|
|
45
|
+
alias to_s raw_uri
|
|
44
46
|
|
|
45
47
|
private
|
|
46
48
|
|
|
47
49
|
def extract_arg(key, hashes)
|
|
48
50
|
hashes.each_with_index do |hash, index|
|
|
49
|
-
|
|
51
|
+
if hash.key?(key)
|
|
52
|
+
return (index == 0 ? hash.delete(key) : hash.fetch(key))
|
|
53
|
+
end
|
|
50
54
|
end
|
|
51
55
|
|
|
52
56
|
nil
|
|
@@ -58,7 +62,7 @@ module Acfs
|
|
|
58
62
|
|
|
59
63
|
def lookup_replacement(sym, args)
|
|
60
64
|
value = get_replacement(sym, args).to_s
|
|
61
|
-
return value unless value.empty?
|
|
65
|
+
return ::URI.encode_www_form_component(value) unless value.empty?
|
|
62
66
|
|
|
63
67
|
raise ArgumentError.new "Cannot replace path argument `#{sym}' with empty string."
|
|
64
68
|
end
|