acfs 1.3.2 → 1.3.3
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
- metadata +8 -141
- data/CHANGELOG.md +0 -325
- data/LICENSE +0 -22
- data/README.md +0 -334
- data/acfs.gemspec +0 -37
- data/lib/acfs.rb +0 -49
- data/lib/acfs/adapter/base.rb +0 -26
- data/lib/acfs/adapter/typhoeus.rb +0 -60
- data/lib/acfs/collection.rb +0 -27
- data/lib/acfs/collections/paginatable.rb +0 -75
- data/lib/acfs/configuration.rb +0 -113
- data/lib/acfs/errors.rb +0 -106
- data/lib/acfs/global.rb +0 -99
- data/lib/acfs/location.rb +0 -78
- data/lib/acfs/middleware/base.rb +0 -20
- data/lib/acfs/middleware/json.rb +0 -27
- data/lib/acfs/middleware/logger.rb +0 -23
- data/lib/acfs/middleware/msgpack.rb +0 -30
- data/lib/acfs/middleware/print.rb +0 -21
- data/lib/acfs/middleware/serializer.rb +0 -39
- data/lib/acfs/operation.rb +0 -81
- data/lib/acfs/request.rb +0 -36
- data/lib/acfs/request/callbacks.rb +0 -50
- data/lib/acfs/resource.rb +0 -37
- data/lib/acfs/resource/attributes.rb +0 -268
- data/lib/acfs/resource/attributes/base.rb +0 -28
- data/lib/acfs/resource/attributes/boolean.rb +0 -37
- data/lib/acfs/resource/attributes/date_time.rb +0 -31
- data/lib/acfs/resource/attributes/dict.rb +0 -37
- data/lib/acfs/resource/attributes/float.rb +0 -31
- data/lib/acfs/resource/attributes/integer.rb +0 -27
- data/lib/acfs/resource/attributes/list.rb +0 -34
- data/lib/acfs/resource/attributes/string.rb +0 -24
- data/lib/acfs/resource/attributes/uuid.rb +0 -47
- data/lib/acfs/resource/dirty.rb +0 -35
- data/lib/acfs/resource/initialization.rb +0 -29
- data/lib/acfs/resource/loadable.rb +0 -33
- data/lib/acfs/resource/locatable.rb +0 -128
- data/lib/acfs/resource/operational.rb +0 -22
- data/lib/acfs/resource/persistence.rb +0 -257
- data/lib/acfs/resource/query_methods.rb +0 -264
- data/lib/acfs/resource/service.rb +0 -42
- data/lib/acfs/resource/validation.rb +0 -37
- data/lib/acfs/response.rb +0 -28
- data/lib/acfs/response/formats.rb +0 -25
- data/lib/acfs/response/status.rb +0 -31
- data/lib/acfs/rspec.rb +0 -11
- data/lib/acfs/runner.rb +0 -97
- data/lib/acfs/service.rb +0 -91
- data/lib/acfs/service/middleware.rb +0 -56
- data/lib/acfs/service/middleware/stack.rb +0 -63
- data/lib/acfs/singleton_resource.rb +0 -83
- data/lib/acfs/stub.rb +0 -172
- data/lib/acfs/util.rb +0 -20
- data/lib/acfs/version.rb +0 -14
- data/lib/acfs/yard.rb +0 -5
- data/spec/acfs/adapter/typhoeus_spec.rb +0 -28
- data/spec/acfs/collection_spec.rb +0 -155
- data/spec/acfs/configuration_spec.rb +0 -51
- data/spec/acfs/global_spec.rb +0 -137
- data/spec/acfs/location_spec.rb +0 -23
- data/spec/acfs/middleware/json_spec.rb +0 -63
- data/spec/acfs/middleware/msgpack_spec.rb +0 -60
- data/spec/acfs/operation_spec.rb +0 -10
- data/spec/acfs/request/callbacks_spec.rb +0 -46
- data/spec/acfs/request_spec.rb +0 -77
- data/spec/acfs/resource/attributes/boolean_spec.rb +0 -56
- data/spec/acfs/resource/attributes/date_time_spec.rb +0 -49
- data/spec/acfs/resource/attributes/dict_spec.rb +0 -75
- data/spec/acfs/resource/attributes/float_spec.rb +0 -59
- data/spec/acfs/resource/attributes/integer_spec.rb +0 -34
- data/spec/acfs/resource/attributes/list_spec.rb +0 -58
- data/spec/acfs/resource/attributes/uuid_spec.rb +0 -40
- data/spec/acfs/resource/attributes_spec.rb +0 -179
- data/spec/acfs/resource/dirty_spec.rb +0 -47
- data/spec/acfs/resource/initialization_spec.rb +0 -30
- data/spec/acfs/resource/loadable_spec.rb +0 -20
- data/spec/acfs/resource/locatable_spec.rb +0 -116
- data/spec/acfs/resource/persistance_spec.rb +0 -316
- data/spec/acfs/resource/query_methods_spec.rb +0 -541
- data/spec/acfs/resource/validation_spec.rb +0 -127
- data/spec/acfs/response/formats_spec.rb +0 -50
- data/spec/acfs/response/status_spec.rb +0 -69
- data/spec/acfs/runner_spec.rb +0 -97
- data/spec/acfs/service/middleware_spec.rb +0 -33
- data/spec/acfs/service_spec.rb +0 -46
- data/spec/acfs/singleton_resource_spec.rb +0 -15
- data/spec/acfs/stub_spec.rb +0 -343
- data/spec/acfs_spec.rb +0 -203
- data/spec/fixtures/config.yml +0 -14
- data/spec/spec_helper.rb +0 -41
- data/spec/support/hash.rb +0 -9
- data/spec/support/response.rb +0 -10
- data/spec/support/service.rb +0 -91
- data/spec/support/shared/find_callbacks.rb +0 -48
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
require 'typhoeus'
|
|
2
|
-
|
|
3
|
-
module Acfs
|
|
4
|
-
module Adapter
|
|
5
|
-
# Adapter for Typhoeus.
|
|
6
|
-
#
|
|
7
|
-
class Typhoeus < Base
|
|
8
|
-
def initialize(**kwargs)
|
|
9
|
-
@options = kwargs
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def start
|
|
13
|
-
hydra.run
|
|
14
|
-
rescue
|
|
15
|
-
@hydra = nil
|
|
16
|
-
raise
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
delegate :abort, to: :hydra
|
|
20
|
-
|
|
21
|
-
def run(request)
|
|
22
|
-
convert_request(request).run
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def queue(request)
|
|
26
|
-
hydra.queue convert_request request
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
protected
|
|
30
|
-
|
|
31
|
-
def hydra
|
|
32
|
-
@hydra ||= ::Typhoeus::Hydra.new(**@options)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def convert_request(req)
|
|
36
|
-
request = ::Typhoeus::Request.new req.url,
|
|
37
|
-
method: req.method,
|
|
38
|
-
params: req.params,
|
|
39
|
-
headers: req.headers.merge(
|
|
40
|
-
'Expect' => '',
|
|
41
|
-
'Transfer-Encoding' => ''
|
|
42
|
-
),
|
|
43
|
-
body: req.body
|
|
44
|
-
|
|
45
|
-
request.on_complete do |response|
|
|
46
|
-
req.complete! convert_response(req, response)
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
request
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def convert_response(request, response)
|
|
53
|
-
Acfs::Response.new request,
|
|
54
|
-
status: response.code,
|
|
55
|
-
headers: response.headers,
|
|
56
|
-
body: response.body
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
data/lib/acfs/collection.rb
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
require 'delegate'
|
|
2
|
-
|
|
3
|
-
require 'acfs/resource/loadable'
|
|
4
|
-
require 'acfs/collections/paginatable'
|
|
5
|
-
|
|
6
|
-
module Acfs
|
|
7
|
-
#
|
|
8
|
-
class Collection < ::Delegator
|
|
9
|
-
include Resource::Loadable
|
|
10
|
-
include Acfs::Util::Callbacks
|
|
11
|
-
include Collections::Paginatable
|
|
12
|
-
|
|
13
|
-
def initialize(resource_class)
|
|
14
|
-
super([])
|
|
15
|
-
|
|
16
|
-
@resource_class = resource_class
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def __getobj__
|
|
20
|
-
@models
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def __setobj__(obj)
|
|
24
|
-
@models = obj
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
module Acfs::Collections
|
|
2
|
-
#
|
|
3
|
-
module Paginatable
|
|
4
|
-
extend ActiveSupport::Concern
|
|
5
|
-
|
|
6
|
-
included do
|
|
7
|
-
def self.operation(_action, opts = {}, &_block)
|
|
8
|
-
opts[:url]
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
attr_reader :total_pages, :current_page, :total_count
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def process_response(response)
|
|
15
|
-
setup_params response.request.params if response.request
|
|
16
|
-
setup_headers response.headers
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def next_page(&block)
|
|
20
|
-
page 'next', &block
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def prev_page(&block)
|
|
24
|
-
page 'prev', &block
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def first_page(&block)
|
|
28
|
-
page 'first', &block
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def last_page(&block)
|
|
32
|
-
page 'last', &block
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def page(rel, &block)
|
|
36
|
-
return unless relations[rel]
|
|
37
|
-
|
|
38
|
-
@resource_class.all nil, url: relations[rel], &block
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
private
|
|
42
|
-
|
|
43
|
-
def relations
|
|
44
|
-
@relations ||= {}
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def setup_headers(headers)
|
|
48
|
-
if headers['X-Total-Pages']
|
|
49
|
-
@total_pages = Integer(headers['X-Total-Pages'])
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
if headers['X-Total-Count']
|
|
53
|
-
@total_count = Integer(headers['X-Total-Count'])
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
setup_links headers['Link'] if headers['Link']
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def setup_links(links)
|
|
60
|
-
links.split(/,\s+/).each do |link|
|
|
61
|
-
if link =~ /^\s*<([^>]+)>.*\s+rel="([\w_-]+)".*$/
|
|
62
|
-
relations[Regexp.last_match[2]] = Regexp.last_match[1]
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def setup_params(params)
|
|
68
|
-
@current_page = begin
|
|
69
|
-
Integer params.fetch(:page, 1)
|
|
70
|
-
rescue ArgumentError
|
|
71
|
-
params[:page]
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
end
|
data/lib/acfs/configuration.rb
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
require 'uri'
|
|
2
|
-
require 'yaml'
|
|
3
|
-
|
|
4
|
-
module Acfs
|
|
5
|
-
# Acfs configuration is used to locate services and get their base URLs.
|
|
6
|
-
#
|
|
7
|
-
class Configuration
|
|
8
|
-
attr_reader :locations
|
|
9
|
-
attr_accessor :adapter
|
|
10
|
-
|
|
11
|
-
# @api private
|
|
12
|
-
def initialize
|
|
13
|
-
@locations = {}
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
# @api public
|
|
17
|
-
#
|
|
18
|
-
# Configure using given block. If block accepts zero arguments
|
|
19
|
-
# bock will be evaluated in context of the configuration instance
|
|
20
|
-
# otherwise the configuration instance will be given as first arguments.
|
|
21
|
-
#
|
|
22
|
-
# @yield [configuration] Give configuration as arguments or evaluate block
|
|
23
|
-
# in context of configuration object.
|
|
24
|
-
# @yieldparam configuration [Configuration] Configuration object.
|
|
25
|
-
# @return [undefined]
|
|
26
|
-
#
|
|
27
|
-
def configure(&block)
|
|
28
|
-
if block.arity > 0
|
|
29
|
-
block.call self
|
|
30
|
-
else
|
|
31
|
-
instance_eval(&block)
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
# @api public
|
|
36
|
-
#
|
|
37
|
-
# @overload locate(service, uri)
|
|
38
|
-
# Configures URL where a service can be reached.
|
|
39
|
-
#
|
|
40
|
-
# @param [Symbol] service Service identity key for service that is reachable under given URL.
|
|
41
|
-
# @param [String] uri URL where service is reachable. Will be passed to {URI.parse}.
|
|
42
|
-
# @return [undefined]
|
|
43
|
-
#
|
|
44
|
-
# @overload locate(service)
|
|
45
|
-
# Return configured base URL for given service identity key.
|
|
46
|
-
#
|
|
47
|
-
# @param [Symbol] service Service identity key to lookup.
|
|
48
|
-
# @return [URI, NilClass] Configured base URL or nil.
|
|
49
|
-
#
|
|
50
|
-
def locate(service, uri = nil)
|
|
51
|
-
service = service.to_s.underscore.to_sym
|
|
52
|
-
if uri.nil?
|
|
53
|
-
locations[service]
|
|
54
|
-
else
|
|
55
|
-
locations[service] = URI.parse uri
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
# @api public
|
|
60
|
-
#
|
|
61
|
-
# Load configuration from given YAML file.
|
|
62
|
-
#
|
|
63
|
-
# @param [String] filename Path to YAML configuration file.
|
|
64
|
-
# @return [undefined]
|
|
65
|
-
#
|
|
66
|
-
def load(filename)
|
|
67
|
-
config = YAML.load File.read filename
|
|
68
|
-
env = ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development'
|
|
69
|
-
|
|
70
|
-
config = config[env] if config.key? env
|
|
71
|
-
config.each do |key, value|
|
|
72
|
-
case key
|
|
73
|
-
when 'services' then load_services value
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
# @api private
|
|
79
|
-
#
|
|
80
|
-
# Load services from configuration YAML.
|
|
81
|
-
#
|
|
82
|
-
def load_services(services)
|
|
83
|
-
services.each do |service, data|
|
|
84
|
-
if (val = data).is_a?(String) || (val = data['locate'])
|
|
85
|
-
locate service.to_sym, val
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
class << self
|
|
91
|
-
# @api private
|
|
92
|
-
#
|
|
93
|
-
# Return current configuration object.
|
|
94
|
-
#
|
|
95
|
-
# @return [Configuration]
|
|
96
|
-
#
|
|
97
|
-
def current
|
|
98
|
-
@configuration ||= new
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
# @api private
|
|
102
|
-
#
|
|
103
|
-
# Swap configuration object with given new one. Must be a {Configuration} object.
|
|
104
|
-
#
|
|
105
|
-
# @param [Configuration] configuration
|
|
106
|
-
# @return [undefined]
|
|
107
|
-
#
|
|
108
|
-
def set(configuration)
|
|
109
|
-
@configuration = configuration if configuration.is_a? Configuration
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
end
|
data/lib/acfs/errors.rb
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
module Acfs
|
|
2
|
-
# Acfs base error.
|
|
3
|
-
#
|
|
4
|
-
class Error < StandardError
|
|
5
|
-
def initialize(opts = {}, message = nil)
|
|
6
|
-
opts.merge! message: message if message
|
|
7
|
-
super opts[:message]
|
|
8
|
-
end
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
class UnsupportedOperation < StandardError; end
|
|
12
|
-
|
|
13
|
-
# Response error containing the responsible response object.
|
|
14
|
-
#
|
|
15
|
-
class ErroneousResponse < Error
|
|
16
|
-
attr_reader :response
|
|
17
|
-
|
|
18
|
-
def initialize(opts = {})
|
|
19
|
-
@response = opts[:response]
|
|
20
|
-
message = opts[:message]
|
|
21
|
-
if response
|
|
22
|
-
if message
|
|
23
|
-
message << ':'
|
|
24
|
-
else
|
|
25
|
-
message = 'Received'
|
|
26
|
-
end
|
|
27
|
-
message << " #{response.code} for #{response.request.method.upcase} #{response.request.url} #{response.request.format}"
|
|
28
|
-
else
|
|
29
|
-
message ||= 'Received erroneous response'
|
|
30
|
-
end
|
|
31
|
-
super opts, message
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
class AmbiguousStubError < Error
|
|
36
|
-
attr_reader :stubs, :operation
|
|
37
|
-
|
|
38
|
-
def initialize(opts = {})
|
|
39
|
-
require 'pp'
|
|
40
|
-
|
|
41
|
-
@stubs = opts.delete :stubs
|
|
42
|
-
@operation = opts.delete :operation
|
|
43
|
-
|
|
44
|
-
super opts, "Ambiguous stubs for #{operation.action} on #{operation.resource}.\n" +
|
|
45
|
-
stubs.map {|s| " #{s.opts.pretty_inspect}" }.join
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
# Resource not found error raised on a 404 response
|
|
50
|
-
#
|
|
51
|
-
class ResourceNotFound < ErroneousResponse
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
#
|
|
55
|
-
class InvalidResource < ErroneousResponse
|
|
56
|
-
attr_reader :errors, :resource
|
|
57
|
-
|
|
58
|
-
def initialize(opts = {})
|
|
59
|
-
@errors = opts.delete :errors
|
|
60
|
-
@resource = opts.delete :resource
|
|
61
|
-
|
|
62
|
-
if @errors.is_a?(Hash)
|
|
63
|
-
opts[:message] ||= @errors.each_pair.map do |k, v|
|
|
64
|
-
@errors.is_a?(Array) ? "#{k}: #{v.join(', ')}" : "#{k}: #{v}"
|
|
65
|
-
end.join ', '
|
|
66
|
-
elsif @errors.is_a?(Array)
|
|
67
|
-
opts[:message] ||= @errors.join ', '
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
super
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
# A ResourceNotLoaded error will be thrown when calling some
|
|
75
|
-
# modifing methods on not loaded resources as it is usally
|
|
76
|
-
# unwanted to call e.g. `update_attributes` on a not loaded
|
|
77
|
-
# resource.
|
|
78
|
-
# Correct solution is to first run `Acfs.run` to fetch the
|
|
79
|
-
# resource and then update the resource.
|
|
80
|
-
#
|
|
81
|
-
class ResourceNotLoaded < Error
|
|
82
|
-
attr_reader :resource
|
|
83
|
-
|
|
84
|
-
def initialize(opts = {})
|
|
85
|
-
@resource = opts.delete :resource
|
|
86
|
-
super
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
# Gets raised if ressource type is no valid subclass of
|
|
91
|
-
# parent resource. Check if the type is set to the correct
|
|
92
|
-
# Acfs::Resource Name
|
|
93
|
-
class ResourceTypeError < Error
|
|
94
|
-
attr_reader :base_class
|
|
95
|
-
attr_reader :type_name
|
|
96
|
-
|
|
97
|
-
def initialize(opts = {})
|
|
98
|
-
@base_class = opts.delete :base_class
|
|
99
|
-
@type_name = opts.delete :type_name
|
|
100
|
-
opts[:message] = "Received resource type `#{type_name}` is no subclass of #{base_class}"
|
|
101
|
-
super
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
class RealRequestsNotAllowedError < StandardError; end
|
|
106
|
-
end
|
data/lib/acfs/global.rb
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
module Acfs
|
|
2
|
-
#
|
|
3
|
-
# Global Acfs module methods.
|
|
4
|
-
#
|
|
5
|
-
module Global
|
|
6
|
-
#
|
|
7
|
-
# @api private
|
|
8
|
-
# @return [Runner]
|
|
9
|
-
#
|
|
10
|
-
def runner
|
|
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
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
# @api public
|
|
23
|
-
#
|
|
24
|
-
# Run all queued operations.
|
|
25
|
-
#
|
|
26
|
-
# @return [undefined]
|
|
27
|
-
#
|
|
28
|
-
def run
|
|
29
|
-
::ActiveSupport::Notifications.instrument 'acfs.before_run'
|
|
30
|
-
::ActiveSupport::Notifications.instrument 'acfs.run' do
|
|
31
|
-
runner.start
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
# @api public
|
|
36
|
-
#
|
|
37
|
-
# Configure acfs using given block.
|
|
38
|
-
#
|
|
39
|
-
# @return [undefined]
|
|
40
|
-
# @see Configuration#configure
|
|
41
|
-
#
|
|
42
|
-
def configure(&block)
|
|
43
|
-
Configuration.current.configure(&block)
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
# @api public
|
|
47
|
-
#
|
|
48
|
-
# Reset all queues, stubs and internal state.
|
|
49
|
-
#
|
|
50
|
-
def reset
|
|
51
|
-
::ActiveSupport::Notifications.instrument 'acfs.reset' do
|
|
52
|
-
runner.clear
|
|
53
|
-
Acfs::Stub.clear
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# @api public
|
|
58
|
-
#
|
|
59
|
-
# Add an additional callback hook to not loaded resource.
|
|
60
|
-
# If given resource already loaded callback will be invoked immediately.
|
|
61
|
-
#
|
|
62
|
-
# This method will be replaced by explicit callback
|
|
63
|
-
# handling when query methods return explicit future objects.
|
|
64
|
-
#
|
|
65
|
-
# @example
|
|
66
|
-
# user = MyUser.find 1, &callback_one
|
|
67
|
-
# Acfs.add_callback(user, &callback_two)
|
|
68
|
-
#
|
|
69
|
-
def add_callback(resource, &block)
|
|
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
|
|
74
|
-
return false if block.nil?
|
|
75
|
-
|
|
76
|
-
if resource.nil? || resource.loaded?
|
|
77
|
-
block.call resource
|
|
78
|
-
else
|
|
79
|
-
resource.__callbacks__ << block
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def on(*resources)
|
|
84
|
-
# If all resources have already been loaded, we run the callback immediately.
|
|
85
|
-
if resources.all? {|res| res.nil? || res.loaded? }
|
|
86
|
-
yield(*resources)
|
|
87
|
-
return
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
# Otherwise, we add a callback to *each* resource with a guard that ensures
|
|
91
|
-
# that only the very last resource being loaded executes the callback.
|
|
92
|
-
resources.each do |resource|
|
|
93
|
-
add_callback resource do |_|
|
|
94
|
-
yield(*resources) if resources.all? {|res| res.nil? || res.loaded? }
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
end
|