acfs 1.3.2 → 1.3.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/lib/acfs/service.rb
DELETED
@@ -1,91 +0,0 @@
|
|
1
|
-
require 'acfs/service/middleware'
|
2
|
-
|
3
|
-
module Acfs
|
4
|
-
# User {Acfs::Service} to define your services. That includes
|
5
|
-
# an identity used to identify the service in configuration files
|
6
|
-
# and middlewares the service uses.
|
7
|
-
#
|
8
|
-
# Configure your service URLs in a YAML file loaded in an
|
9
|
-
# initializer using the identity as a key:
|
10
|
-
#
|
11
|
-
# production:
|
12
|
-
# services:
|
13
|
-
# user_service_key: "http://users.service.org/base/path"
|
14
|
-
#
|
15
|
-
# @example
|
16
|
-
# class UserService < Acfs::Service
|
17
|
-
# identity :user_service_key
|
18
|
-
#
|
19
|
-
# use Acfs::Middleware::MessagePackDecoder
|
20
|
-
# end
|
21
|
-
#
|
22
|
-
class Service
|
23
|
-
attr_accessor :options
|
24
|
-
|
25
|
-
include Service::Middleware
|
26
|
-
|
27
|
-
# @api private
|
28
|
-
#
|
29
|
-
def initialize(options = {})
|
30
|
-
@options = options
|
31
|
-
end
|
32
|
-
|
33
|
-
# @api private
|
34
|
-
# @return [Location]
|
35
|
-
#
|
36
|
-
def location(resource_class, opts = {})
|
37
|
-
opts.reverse_merge! options
|
38
|
-
|
39
|
-
action = opts[:action] || :list
|
40
|
-
|
41
|
-
path = if opts[:path].is_a?(Hash) && opts[:path].key?(action)
|
42
|
-
opts[:path].fetch(action)
|
43
|
-
else
|
44
|
-
path = if opts[:path].is_a?(Hash)
|
45
|
-
opts[:path][:all].to_s
|
46
|
-
else
|
47
|
-
opts[:path].to_s
|
48
|
-
end
|
49
|
-
|
50
|
-
path = (resource_class.name || 'class').pluralize.underscore if path.blank?
|
51
|
-
|
52
|
-
resource_class.location_default_path(action, path.strip)
|
53
|
-
end
|
54
|
-
|
55
|
-
raise ArgumentError.new "Location for `#{action}' explicit disabled by set to nil." if path.nil?
|
56
|
-
|
57
|
-
Location.new [self.class.base_url.to_s, path.to_s].join('/')
|
58
|
-
end
|
59
|
-
|
60
|
-
class << self
|
61
|
-
# @api public
|
62
|
-
#
|
63
|
-
# @overload identity()
|
64
|
-
# Return configured identity key or derive key from class name.
|
65
|
-
#
|
66
|
-
# @return [Symbol] Service identity key.
|
67
|
-
#
|
68
|
-
# @overload identity(identity)
|
69
|
-
# Set identity key.
|
70
|
-
#
|
71
|
-
# @param [#to_s] identity New identity key.
|
72
|
-
# @return [Symbol] New set identity key.
|
73
|
-
#
|
74
|
-
def identity(identity = nil)
|
75
|
-
@identity = identity.to_s.to_sym unless identity.nil?
|
76
|
-
@identity ||= name.to_sym
|
77
|
-
end
|
78
|
-
|
79
|
-
# @api private
|
80
|
-
# @return [String]
|
81
|
-
#
|
82
|
-
def base_url
|
83
|
-
unless (base = Acfs::Configuration.current.locate identity)
|
84
|
-
raise ArgumentError.new "#{identity} not configured. Add `locate '#{identity.to_s.underscore}', 'http://service.url/'` to your configuration."
|
85
|
-
end
|
86
|
-
|
87
|
-
base.to_s
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
@@ -1,56 +0,0 @@
|
|
1
|
-
require 'acfs/service/middleware/stack'
|
2
|
-
|
3
|
-
module Acfs
|
4
|
-
class Service
|
5
|
-
# Module providing all function to register middlewares
|
6
|
-
# on services and process queued request through the
|
7
|
-
# middleware stack.
|
8
|
-
#
|
9
|
-
module Middleware
|
10
|
-
extend ActiveSupport::Concern
|
11
|
-
|
12
|
-
# @api private
|
13
|
-
# @return [Request]
|
14
|
-
#
|
15
|
-
def prepare(request)
|
16
|
-
self.class.middleware.call request
|
17
|
-
end
|
18
|
-
|
19
|
-
module ClassMethods
|
20
|
-
# @!method use(klass, *args, &block)
|
21
|
-
# @api public
|
22
|
-
#
|
23
|
-
# Register a new middleware to be used for this service.
|
24
|
-
#
|
25
|
-
# @example
|
26
|
-
# class MyService < Acfs::Service
|
27
|
-
# self.base_url = 'http://my.srv'
|
28
|
-
# use Acfs::Middleware::JSON
|
29
|
-
# end
|
30
|
-
#
|
31
|
-
# @param [Class] klass Middleware class to append
|
32
|
-
# @param [Array<Object>] args Arguments passed to klass initialize
|
33
|
-
# @param [Proc] block Block passed to klass initialize
|
34
|
-
# @return [undefined]
|
35
|
-
#
|
36
|
-
def use(klass, *args, &block)
|
37
|
-
# Backward compatible behavior
|
38
|
-
middleware.insert(0, klass, *args, &block)
|
39
|
-
end
|
40
|
-
|
41
|
-
# @api private
|
42
|
-
#
|
43
|
-
# Return top most middleware.
|
44
|
-
#
|
45
|
-
# @return [#call]
|
46
|
-
#
|
47
|
-
def middleware
|
48
|
-
@middleware ||= Stack.new
|
49
|
-
end
|
50
|
-
|
51
|
-
# @deprecated
|
52
|
-
delegate :clear, to: :middleware
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
@@ -1,63 +0,0 @@
|
|
1
|
-
module Acfs
|
2
|
-
class Service
|
3
|
-
module Middleware
|
4
|
-
class Stack
|
5
|
-
include Enumerable
|
6
|
-
|
7
|
-
MUTEX = Mutex.new
|
8
|
-
IDENTITY = -> (i) { i }
|
9
|
-
|
10
|
-
attr_reader :middlewares
|
11
|
-
|
12
|
-
def initialize
|
13
|
-
@middlewares = []
|
14
|
-
end
|
15
|
-
|
16
|
-
def call(request)
|
17
|
-
build! unless @app
|
18
|
-
|
19
|
-
@app.call request
|
20
|
-
end
|
21
|
-
|
22
|
-
def build!
|
23
|
-
return if @app
|
24
|
-
|
25
|
-
MUTEX.synchronize do
|
26
|
-
return if @app
|
27
|
-
|
28
|
-
@app = build
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def build(app = IDENTITY)
|
33
|
-
middlewares.reverse.inject(app) do |next_middleware, current_middleware|
|
34
|
-
klass, args, block = current_middleware
|
35
|
-
args ||= []
|
36
|
-
|
37
|
-
if klass.is_a?(Class)
|
38
|
-
klass.new(next_middleware, *args, &block)
|
39
|
-
elsif klass.respond_to?(:call)
|
40
|
-
lambda do |env|
|
41
|
-
next_middleware.call(klass.call(env, *args))
|
42
|
-
end
|
43
|
-
else
|
44
|
-
fail "Invalid middleware, doesn't respond to `call`: #{klass.inspect}"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def insert(index, klass, *args, &block)
|
50
|
-
middlewares.insert(index, [klass, args, block])
|
51
|
-
end
|
52
|
-
|
53
|
-
def each
|
54
|
-
middlewares.each { |x| yield x.first }
|
55
|
-
end
|
56
|
-
|
57
|
-
def clear
|
58
|
-
middlewares.clear
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
@@ -1,83 +0,0 @@
|
|
1
|
-
module Acfs
|
2
|
-
# Acfs SingletonResources
|
3
|
-
#
|
4
|
-
# Usage explanation:
|
5
|
-
# Single.find => sends GET request to http://service:port/single
|
6
|
-
# my_single.save => sends POST request to http://service:port/single
|
7
|
-
# if my_single is a new object
|
8
|
-
# or sends PUT request to http://service:port/single
|
9
|
-
# if my_single has been requested before
|
10
|
-
# my_single.delete => sends DELETE request to http://service:port/single
|
11
|
-
#
|
12
|
-
# SingletonResources do not support the Resource method :all, since
|
13
|
-
# always only a single instance of the resource is being returned
|
14
|
-
#
|
15
|
-
class SingletonResource < Acfs::Resource
|
16
|
-
# @api public
|
17
|
-
#
|
18
|
-
# Destroy resource by sending a DELETE request.
|
19
|
-
# Will raise an error in case something goes wrong.
|
20
|
-
#
|
21
|
-
# Deleting a resource is a synchronous operation.
|
22
|
-
#
|
23
|
-
# @raise [Acfs::ErroneousResponse]
|
24
|
-
# If remote service respond with not successful response.
|
25
|
-
# @return [undefined]
|
26
|
-
# @see #delete
|
27
|
-
#
|
28
|
-
def delete!(opts = {})
|
29
|
-
opts[:params] ||= {}
|
30
|
-
|
31
|
-
operation :delete, opts do |data|
|
32
|
-
update_with data
|
33
|
-
freeze
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
# @api private
|
38
|
-
def need_primary_key?
|
39
|
-
false
|
40
|
-
end
|
41
|
-
|
42
|
-
class << self
|
43
|
-
# @api public
|
44
|
-
#
|
45
|
-
# @overload find(id, opts = {})
|
46
|
-
# Find a singleton resource, optionally with params.
|
47
|
-
#
|
48
|
-
# @example
|
49
|
-
# single = Singleton.find # Will query `http://base.url/singletons/`
|
50
|
-
#
|
51
|
-
# @param [ Hash ] opts Additional options.
|
52
|
-
# @option opts [ Hash ] :params Additional parameters added to request.
|
53
|
-
#
|
54
|
-
# @yield [ resource ] Callback block to be executed after
|
55
|
-
# resource was fetched successfully.
|
56
|
-
# @yieldparam resource [ self ] Fetched resources.
|
57
|
-
#
|
58
|
-
# @return [ self ] Resource object.
|
59
|
-
#
|
60
|
-
def find(*attrs, &block)
|
61
|
-
find_single nil, params: attrs.extract_options!, &block
|
62
|
-
end
|
63
|
-
|
64
|
-
# @api public
|
65
|
-
#
|
66
|
-
# Undefined, raises NoMethodError.
|
67
|
-
# A singleton always only returns one object, therefore the
|
68
|
-
# methods :all and :where are not defined.
|
69
|
-
# :find_by is not defined on singletons, use :find instead
|
70
|
-
#
|
71
|
-
def all
|
72
|
-
raise ::Acfs::UnsupportedOperation.new
|
73
|
-
end
|
74
|
-
alias_method :find_by, :all
|
75
|
-
alias_method :find_by!, :all
|
76
|
-
|
77
|
-
# @api private
|
78
|
-
def location_default_path(_, path)
|
79
|
-
path
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
data/lib/acfs/stub.rb
DELETED
@@ -1,172 +0,0 @@
|
|
1
|
-
require 'rack/utils'
|
2
|
-
|
3
|
-
module Acfs
|
4
|
-
# Global handler for stubbing resources.
|
5
|
-
#
|
6
|
-
class Stub
|
7
|
-
ACTIONS = [:read, :create, :update, :delete, :list]
|
8
|
-
|
9
|
-
attr_reader :opts
|
10
|
-
|
11
|
-
def initialize(opts)
|
12
|
-
@opts = opts
|
13
|
-
|
14
|
-
@opts[:with].stringify_keys! if @opts[:with].is_a? Hash
|
15
|
-
@opts[:return].stringify_keys! if @opts[:return].is_a? Hash
|
16
|
-
@opts[:return].map! {|h| h.stringify_keys! if h.is_a? Hash } if @opts[:return].is_a? Array
|
17
|
-
end
|
18
|
-
|
19
|
-
def accept?(op)
|
20
|
-
return opts[:with].call op if opts[:with].respond_to? :call
|
21
|
-
|
22
|
-
params = op.full_params.stringify_keys
|
23
|
-
data = op.data.stringify_keys
|
24
|
-
with = opts[:with]
|
25
|
-
|
26
|
-
return true if with.nil?
|
27
|
-
|
28
|
-
case opts.fetch(:match, :inclusion)
|
29
|
-
when :legacy
|
30
|
-
return true if with.empty? && params.empty? && data.empty?
|
31
|
-
return true if with.reject {|_, v| v.nil? } == params.reject {|_, v| v.nil? }
|
32
|
-
return true if with.reject {|_, v| v.nil? } == data.reject {|_, v| v.nil? }
|
33
|
-
false
|
34
|
-
when :inclusion
|
35
|
-
with.each_pair.all? do |k, v|
|
36
|
-
(params.key?(k) && params[k] == v) || (data.key?(k) && data[k] == v)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def calls
|
42
|
-
@calls ||= []
|
43
|
-
end
|
44
|
-
|
45
|
-
def called?(count = nil)
|
46
|
-
count = count.count if count.respond_to? :count # For `5.times` Enumerators
|
47
|
-
count.nil? ? calls.any? : calls.size == count
|
48
|
-
end
|
49
|
-
|
50
|
-
def call(op)
|
51
|
-
calls << op
|
52
|
-
|
53
|
-
err = opts[:raise]
|
54
|
-
data = opts[:return]
|
55
|
-
|
56
|
-
if err
|
57
|
-
raise_error op, err, opts[:return]
|
58
|
-
elsif data
|
59
|
-
data = data.call(op) if data.respond_to?(:call)
|
60
|
-
|
61
|
-
response = Acfs::Response.new op.request,
|
62
|
-
headers: opts[:headers] || {},
|
63
|
-
status: opts[:status] || 200,
|
64
|
-
data: data || {}
|
65
|
-
op.call data, response
|
66
|
-
else
|
67
|
-
raise ArgumentError.new 'Unsupported stub.'
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
private
|
72
|
-
|
73
|
-
def raise_error(op, name, data)
|
74
|
-
raise name if name.is_a? Class
|
75
|
-
data.stringify_keys! if data.respond_to? :stringify_keys!
|
76
|
-
|
77
|
-
op.handle_failure ::Acfs::Response.new op.request, status: Rack::Utils.status_code(name), data: data
|
78
|
-
end
|
79
|
-
|
80
|
-
class << self
|
81
|
-
# Stub a resource with given handler block. An already created handler
|
82
|
-
# for same resource class will be overridden.
|
83
|
-
#
|
84
|
-
def resource(klass, action, opts = {}, &_block)
|
85
|
-
action = action.to_sym
|
86
|
-
raise ArgumentError.new "Unknown action `#{action}`." unless ACTIONS.include? action
|
87
|
-
|
88
|
-
Stub.new(opts).tap do |stub|
|
89
|
-
stubs[klass] ||= {}
|
90
|
-
stubs[klass][action] ||= []
|
91
|
-
stubs[klass][action] << stub
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def allow_requests=(allow)
|
96
|
-
@allow_requests = allow ? true : false
|
97
|
-
end
|
98
|
-
|
99
|
-
def allow_requests?
|
100
|
-
@allow_requests ||= false
|
101
|
-
end
|
102
|
-
|
103
|
-
def enabled?
|
104
|
-
@enabled ||= false
|
105
|
-
end
|
106
|
-
|
107
|
-
def enable
|
108
|
-
@enabled = true
|
109
|
-
end
|
110
|
-
|
111
|
-
def disable
|
112
|
-
@enabled = false
|
113
|
-
end
|
114
|
-
|
115
|
-
# Clear all stubs.
|
116
|
-
#
|
117
|
-
def clear(klass = nil)
|
118
|
-
klass.nil? ? stubs.clear : stubs[klass].try(:clear)
|
119
|
-
end
|
120
|
-
|
121
|
-
def stubs
|
122
|
-
@stubs ||= {}
|
123
|
-
end
|
124
|
-
|
125
|
-
def stub_for(op)
|
126
|
-
return false unless (classes = stubs[op.resource])
|
127
|
-
return false unless (stubs = classes[op.action])
|
128
|
-
|
129
|
-
accepted_stubs = stubs.select {|stub| stub.accept? op }
|
130
|
-
|
131
|
-
raise AmbiguousStubError.new stubs: accepted_stubs, operation: op if accepted_stubs.size > 1
|
132
|
-
|
133
|
-
accepted_stubs.first
|
134
|
-
end
|
135
|
-
|
136
|
-
def stubbed(op)
|
137
|
-
stub = stub_for op
|
138
|
-
unless stub
|
139
|
-
return false if allow_requests?
|
140
|
-
raise RealRequestsNotAllowedError.new <<-MSG.strip.gsub(/^[ ]{12}/, '')
|
141
|
-
No stub found for `#{op.action}' on `#{op.resource.name}' with params `#{op.full_params.inspect}', data `#{op.data.inspect}' and id `#{op.id}'.
|
142
|
-
|
143
|
-
Available stubs:
|
144
|
-
#{pretty_print}
|
145
|
-
MSG
|
146
|
-
end
|
147
|
-
|
148
|
-
stub.call op
|
149
|
-
true
|
150
|
-
end
|
151
|
-
|
152
|
-
private
|
153
|
-
|
154
|
-
def pretty_print
|
155
|
-
out = ''
|
156
|
-
stubs.each do |klass, actions|
|
157
|
-
out << ' ' << klass.name << ":\n"
|
158
|
-
actions.each do |action, stubs|
|
159
|
-
stubs.each do |stub|
|
160
|
-
out << " #{action}"
|
161
|
-
out << " with #{stub.opts[:with].inspect}" if stub.opts[:with]
|
162
|
-
out << " and return #{stub.opts[:return].inspect}" if stub.opts[:return]
|
163
|
-
out << " and raise #{stub.opts[:raise].inspect}" if stub.opts[:raise]
|
164
|
-
out << "\n"
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
168
|
-
out
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|