acfs 0.7.0 → 0.8.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/README.md +32 -8
- data/lib/acfs.rb +3 -0
- data/lib/acfs/adapter/typhoeus.rb +9 -3
- data/lib/acfs/errors.rb +7 -0
- data/lib/acfs/middleware/json_encoder.rb +20 -0
- data/lib/acfs/middleware/msgpack_encoder.rb +19 -0
- data/lib/acfs/model.rb +4 -0
- data/lib/acfs/model/attributes.rb +57 -8
- data/lib/acfs/model/dirty.rb +39 -0
- data/lib/acfs/model/initialization.rb +0 -13
- data/lib/acfs/model/locatable.rb +5 -0
- data/lib/acfs/model/persistence.rb +73 -0
- data/lib/acfs/request.rb +2 -1
- data/lib/acfs/response/formats.rb +9 -4
- data/lib/acfs/service.rb +2 -2
- data/lib/acfs/service/middleware.rb +2 -5
- data/lib/acfs/service/request_handler.rb +27 -0
- data/lib/acfs/version.rb +1 -1
- data/spec/{model → acfs/model}/attributes_spec.rb +12 -1
- data/spec/acfs/model/dirty_spec.rb +50 -0
- data/spec/{model → acfs/model}/initialization_spec.rb +0 -0
- data/spec/acfs/model/loadable_spec.rb +21 -0
- data/spec/acfs/model/locatable_spec.rb +47 -0
- data/spec/acfs/model/persistance_spec.rb +80 -0
- data/spec/acfs/model/query_methods_spec.rb +65 -0
- data/spec/acfs/request_spec.rb +16 -1
- data/spec/acfs/response/formats_spec.rb +8 -0
- data/spec/acfs_spec.rb +32 -5
- data/spec/support/service.rb +2 -0
- metadata +22 -9
- data/lib/acfs/service/queue.rb +0 -16
- data/spec/model/locatable_spec.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 70e3e163082aec963c5162cd4fd59d69eb915819
|
4
|
+
data.tar.gz: c4385962f0d06f27a89cb48e4d5d214e904478a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1e2908198cf1314b37fa8c1829ac1995ec36458069203daf334ff0a46b1e35efe9e022f9b375c12dfe3ef6dff9a140594671e33866ecd479384c8c26a1900a7
|
7
|
+
data.tar.gz: d1c128c7028e83f9e79a52bbd449495c38a5aa97c116d02df18828fe2084c739a5b06dd65e805b80e477c19d56e0819c47e802dff01cff45271db2b67e6ccb38
|
data/README.md
CHANGED
@@ -2,15 +2,18 @@
|
|
2
2
|
|
3
3
|
[](http://badge.fury.io/rb/acfs) [](https://travis-ci.org/jgraichen/acfs) [](https://coveralls.io/r/jgraichen/acfs) [](https://codeclimate.com/github/jgraichen/acfs) [](https://gemnasium.com/jgraichen/acfs)
|
4
4
|
|
5
|
-
|
5
|
+
Acfs is a library to develop API client libraries for single services within a
|
6
|
+
larger service oriented application.
|
6
7
|
|
7
|
-
|
8
|
+
Acfs covers model and service abstraction, convenient query and filter methods,
|
9
|
+
full middleware stack for pre-processing requests and responses on a per service
|
10
|
+
level and automatic request queuing and parallel processing. See Usage for more.
|
8
11
|
|
9
12
|
## Installation
|
10
13
|
|
11
14
|
Add this line to your application's Gemfile:
|
12
15
|
|
13
|
-
gem 'acfs', '0.
|
16
|
+
gem 'acfs', '0.8.0'
|
14
17
|
|
15
18
|
**Note:** Acfs is under development. I'll try to avoid changes to the public
|
16
19
|
API but internal APIs may change quite often.
|
@@ -31,7 +34,7 @@ First you need to define your service(s):
|
|
31
34
|
class UserService < Acfs::Service
|
32
35
|
self.base_url = 'http://users.myapp.org'
|
33
36
|
|
34
|
-
# You can configure middlewares you want use for the service here.
|
37
|
+
# You can configure middlewares you want to use for the service here.
|
35
38
|
# Each service has it own middleware stack.
|
36
39
|
#
|
37
40
|
use Acfs::Middleware::JsonDecoder
|
@@ -39,8 +42,8 @@ class UserService < Acfs::Service
|
|
39
42
|
end
|
40
43
|
```
|
41
44
|
|
42
|
-
This specifies where the `UserService`
|
43
|
-
models representing resources
|
45
|
+
This specifies where the `UserService` is located. You can now create some
|
46
|
+
models representing resources served by the `UserService`.
|
44
47
|
|
45
48
|
```ruby
|
46
49
|
class User
|
@@ -122,9 +125,30 @@ Acfs.run # This call will fire all request as parallel as possible.
|
|
122
125
|
@friends[0].name # => "Miraculix"
|
123
126
|
```
|
124
127
|
|
125
|
-
|
128
|
+
Acfs has basic update support using `PUT` requests:
|
126
129
|
|
127
|
-
|
130
|
+
```ruby
|
131
|
+
@user = User.find 5
|
132
|
+
@user.name = "Bob"
|
133
|
+
|
134
|
+
@user.changed? # => true
|
135
|
+
@user.persisted? # => false
|
136
|
+
|
137
|
+
@user.save # Or .save!
|
138
|
+
# Will PUT new resource to service synchronously.
|
139
|
+
|
140
|
+
@user.changed? # => false
|
141
|
+
@user.persisted? # => true
|
142
|
+
```
|
143
|
+
|
144
|
+
## Roadmap
|
145
|
+
|
146
|
+
* Create operations
|
147
|
+
* Update
|
148
|
+
* Better new? detection eg. storing ETag from request resources.
|
149
|
+
* Use PATCH for with only changed attributes and `If-Unmodifed-Since`
|
150
|
+
and `If-Match` header fields if resource was surly loaded from service
|
151
|
+
and not created with an id (e.g `User.new id: 5, name: "john"`).
|
128
152
|
* High level features
|
129
153
|
* Pagination? Filtering? (If service API provides such features.)
|
130
154
|
* Messaging Queue support for services and models
|
data/lib/acfs.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'active_support'
|
2
2
|
require 'active_support/core_ext'
|
3
3
|
require 'acfs/version'
|
4
|
+
require 'acfs/errors'
|
4
5
|
|
5
6
|
module Acfs
|
6
7
|
extend ActiveSupport::Autoload
|
@@ -18,6 +19,8 @@ module Acfs
|
|
18
19
|
autoload :Print
|
19
20
|
autoload :JsonDecoder
|
20
21
|
autoload :MessagePackDecoder, 'acfs/middleware/msgpack_decoder'
|
22
|
+
autoload :JsonEncoder
|
23
|
+
autoload :MessagePackEncoder, 'acfs/middleware/msgpack_encoder'
|
21
24
|
end
|
22
25
|
|
23
26
|
module Adapter
|
@@ -9,8 +9,10 @@ module Acfs
|
|
9
9
|
|
10
10
|
# Run all queued requests.
|
11
11
|
#
|
12
|
-
def run
|
13
|
-
hydra.run
|
12
|
+
def run(request = nil)
|
13
|
+
return hydra.run unless request
|
14
|
+
|
15
|
+
convert_request(request).run
|
14
16
|
end
|
15
17
|
|
16
18
|
# Add a new request or URL to the queue.
|
@@ -25,7 +27,11 @@ module Acfs
|
|
25
27
|
end
|
26
28
|
|
27
29
|
def convert_request(req)
|
28
|
-
request = ::Typhoeus::Request.new req.url,
|
30
|
+
request = ::Typhoeus::Request.new req.url,
|
31
|
+
method: req.method,
|
32
|
+
params: req.params,
|
33
|
+
headers: req.headers,
|
34
|
+
body: req.body
|
29
35
|
|
30
36
|
request.on_complete do |response|
|
31
37
|
req.complete! convert_response(req, response)
|
data/lib/acfs/errors.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
|
3
|
+
module Acfs
|
4
|
+
module Middleware
|
5
|
+
|
6
|
+
# A middleware to encore request data using JSON.
|
7
|
+
#
|
8
|
+
class JsonEncoder < Base
|
9
|
+
|
10
|
+
def call(request)
|
11
|
+
unless request.method == :get or request.data.nil?
|
12
|
+
request.body = ::MultiJson.dump(request.data)
|
13
|
+
request.headers['Content-Type'] = 'application/json'
|
14
|
+
end
|
15
|
+
|
16
|
+
app.call request
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'msgpack'
|
2
|
+
require 'action_dispatch'
|
3
|
+
|
4
|
+
module Acfs
|
5
|
+
module Middleware
|
6
|
+
|
7
|
+
# A middleware to encode request data with Message Pack.
|
8
|
+
#
|
9
|
+
class MessagePackEncoder < Base
|
10
|
+
|
11
|
+
def call(request)
|
12
|
+
request.body = ::MessagePack.dump(request.data)
|
13
|
+
request.headers['Content-Type'] = 'application/x-msgpack'
|
14
|
+
|
15
|
+
app.call request
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/acfs/model.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
require 'active_model'
|
2
2
|
|
3
3
|
require 'acfs/model/attributes'
|
4
|
+
require 'acfs/model/dirty'
|
4
5
|
require 'acfs/model/loadable'
|
5
6
|
require 'acfs/model/locatable'
|
7
|
+
require 'acfs/model/persistence'
|
6
8
|
require 'acfs/model/query_methods'
|
7
9
|
require 'acfs/model/relations'
|
8
10
|
require 'acfs/model/service'
|
@@ -26,10 +28,12 @@ module Acfs
|
|
26
28
|
|
27
29
|
include Model::Attributes
|
28
30
|
include Model::Loadable
|
31
|
+
include Model::Persistence
|
29
32
|
include Model::Locatable
|
30
33
|
include Model::QueryMethods
|
31
34
|
include Model::Relations
|
32
35
|
include Model::Service
|
36
|
+
include Model::Dirty
|
33
37
|
end
|
34
38
|
end
|
35
39
|
end
|
@@ -16,10 +16,11 @@ module Acfs::Model
|
|
16
16
|
#
|
17
17
|
module Attributes
|
18
18
|
extend ActiveSupport::Concern
|
19
|
+
include ActiveModel::AttributeMethods
|
19
20
|
|
20
21
|
def initialize(*attrs) # :nodoc:
|
21
|
-
self.class.attributes
|
22
|
-
super
|
22
|
+
self.write_attributes self.class.attributes, change: false
|
23
|
+
super
|
23
24
|
end
|
24
25
|
|
25
26
|
# Returns ActiveModel compatible list of attributes and values.
|
@@ -38,11 +39,50 @@ module Acfs::Model
|
|
38
39
|
# Update all attributes with given hash.
|
39
40
|
#
|
40
41
|
def attributes=(attributes)
|
41
|
-
|
42
|
-
|
42
|
+
write_attributes attributes
|
43
|
+
end
|
44
|
+
|
45
|
+
# Read an attribute.
|
46
|
+
#
|
47
|
+
def read_attribute(name)
|
48
|
+
instance_variable_get :"@#{name}"
|
49
|
+
end
|
50
|
+
|
51
|
+
# Write a hash of attributes and values.
|
52
|
+
#
|
53
|
+
def write_attributes(attributes, opts = {})
|
54
|
+
procs = {}
|
55
|
+
|
56
|
+
attributes.each do |key, _|
|
57
|
+
if attributes[key].is_a? Proc
|
58
|
+
procs[key] = attributes[key]
|
59
|
+
else
|
60
|
+
write_attribute key, attributes[key], opts
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
procs.each do |key, proc|
|
65
|
+
write_attribute key, instance_exec(&proc), opts
|
43
66
|
end
|
44
67
|
end
|
45
68
|
|
69
|
+
# Write an attribute.
|
70
|
+
#
|
71
|
+
def write_attribute(name, value, opts = {})
|
72
|
+
if (type = self.class.attribute_types[name.to_sym]).nil?
|
73
|
+
raise "Unknown attribute #{name}."
|
74
|
+
end
|
75
|
+
|
76
|
+
write_raw_attribute name, value.nil? ? nil : type.cast(value), opts
|
77
|
+
end
|
78
|
+
|
79
|
+
# Write an attribute without checking type and existence or casting
|
80
|
+
# value to attributes type.
|
81
|
+
#
|
82
|
+
def write_raw_attribute(name, value, _ = {})
|
83
|
+
instance_variable_set :"@#{name}", value
|
84
|
+
end
|
85
|
+
|
46
86
|
module ClassMethods # :nodoc:
|
47
87
|
|
48
88
|
# Define a model attribute by name and type. Will create getter and
|
@@ -76,17 +116,26 @@ module Acfs::Model
|
|
76
116
|
@attributes ||= {}
|
77
117
|
end
|
78
118
|
|
119
|
+
# Return hash of attributes and there types.
|
120
|
+
#
|
121
|
+
def attribute_types
|
122
|
+
@attribute_types ||= {}
|
123
|
+
end
|
124
|
+
|
79
125
|
private
|
80
126
|
def define_attribute(name, type, opts = {}) # :nodoc:
|
81
|
-
|
82
|
-
|
127
|
+
default_value = opts.has_key?(:default) ? opts[:default] : nil
|
128
|
+
default_value = type.cast default_value unless default_value.is_a? Proc or default_value.nil?
|
129
|
+
attributes[name] = default_value
|
130
|
+
attribute_types[name.to_sym] = type
|
131
|
+
define_attribute_method name
|
83
132
|
|
84
133
|
self.send :define_method, name do
|
85
|
-
|
134
|
+
read_attribute name
|
86
135
|
end
|
87
136
|
|
88
137
|
self.send :define_method, :"#{name}=" do |value|
|
89
|
-
|
138
|
+
write_attribute name, value
|
90
139
|
end
|
91
140
|
end
|
92
141
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Acfs
|
2
|
+
module Model
|
3
|
+
|
4
|
+
# Thin wrapper around ActiveModel::Dirty
|
5
|
+
#
|
6
|
+
module Dirty
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
include ActiveModel::Dirty
|
9
|
+
|
10
|
+
# Resets all changes. Do not touch previous changes.
|
11
|
+
#
|
12
|
+
def reset_changes
|
13
|
+
changed_attributes.clear
|
14
|
+
end
|
15
|
+
|
16
|
+
# Save current changes as previous changes and reset
|
17
|
+
# current one.
|
18
|
+
#
|
19
|
+
def swap_changes
|
20
|
+
@previously_changed = changes
|
21
|
+
reset_changes
|
22
|
+
end
|
23
|
+
|
24
|
+
def save!(*) # :nodoc:
|
25
|
+
super.tap { |__| swap_changes }
|
26
|
+
end
|
27
|
+
|
28
|
+
def loaded! # :nodoc:
|
29
|
+
reset_changes
|
30
|
+
super
|
31
|
+
end
|
32
|
+
|
33
|
+
def write_raw_attribute(name, value, opts = {}) # :nodoc:
|
34
|
+
attribute_will_change! name if opts[:change].nil? or opts[:change]
|
35
|
+
super
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -24,18 +24,5 @@ module Acfs::Model
|
|
24
24
|
end if params
|
25
25
|
end
|
26
26
|
|
27
|
-
# Indicates if the model is persisted. Default is +false+.
|
28
|
-
#
|
29
|
-
# class User
|
30
|
-
# include Acfs::Model
|
31
|
-
# attribute :name
|
32
|
-
# end
|
33
|
-
#
|
34
|
-
# user = User.new(name: 'bob')
|
35
|
-
# user.persisted? # => false
|
36
|
-
#
|
37
|
-
def persisted?
|
38
|
-
false
|
39
|
-
end
|
40
27
|
end
|
41
28
|
end
|
data/lib/acfs/model/locatable.rb
CHANGED
@@ -0,0 +1,73 @@
|
|
1
|
+
module Acfs
|
2
|
+
module Model
|
3
|
+
|
4
|
+
# Allow to track the persistence state of a model.
|
5
|
+
#
|
6
|
+
module Persistence
|
7
|
+
|
8
|
+
# Check if the model is persisted. A model is persisted if
|
9
|
+
# it is saved after beeing created or when it was not changed
|
10
|
+
# since it was loaded.
|
11
|
+
#
|
12
|
+
# user = User.new name: "John"
|
13
|
+
# user.persisted? # => false
|
14
|
+
# user.save
|
15
|
+
# user.persisted? # => true
|
16
|
+
#
|
17
|
+
# user2 = User.find 5
|
18
|
+
# user2.persisted? # => true
|
19
|
+
# user2.name = 'Amy'
|
20
|
+
# user2.persisted? # => false
|
21
|
+
# user2.save
|
22
|
+
# user2.persisted? # => true
|
23
|
+
#
|
24
|
+
def persisted?
|
25
|
+
!new? && !changed?
|
26
|
+
end
|
27
|
+
|
28
|
+
# Return true if model is a new record and was not saved yet.
|
29
|
+
#
|
30
|
+
def new?
|
31
|
+
read_attribute(:id).nil?
|
32
|
+
end
|
33
|
+
alias :new_record? :new?
|
34
|
+
|
35
|
+
# Save the resource.
|
36
|
+
#
|
37
|
+
# It will PATCH to the service to update the resource or send
|
38
|
+
# a POST to create a new one if the resource is new.
|
39
|
+
#
|
40
|
+
# `#save` return true of operation was successful, otherwise false.
|
41
|
+
#
|
42
|
+
def save(*args)
|
43
|
+
save! *args
|
44
|
+
true
|
45
|
+
rescue Acfs::Error
|
46
|
+
false
|
47
|
+
end
|
48
|
+
|
49
|
+
def save!(*) # :nodoc:
|
50
|
+
request = new? ? create_request : put_request
|
51
|
+
request.on_complete do |response|
|
52
|
+
update_with response.data
|
53
|
+
end
|
54
|
+
|
55
|
+
self.class.service.run request
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
def update_with(data)
|
60
|
+
self.attributes = data
|
61
|
+
loaded!
|
62
|
+
end
|
63
|
+
|
64
|
+
def create_request
|
65
|
+
Acfs::Request.new self.class.url, method: :post, data: attributes
|
66
|
+
end
|
67
|
+
|
68
|
+
def put_request
|
69
|
+
Acfs::Request.new url, method: :put, data: attributes
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/acfs/request.rb
CHANGED
@@ -7,7 +7,7 @@ module Acfs
|
|
7
7
|
#
|
8
8
|
class Request
|
9
9
|
attr_accessor :body, :format
|
10
|
-
attr_reader :url, :headers, :params, :data
|
10
|
+
attr_reader :url, :headers, :params, :data, :method
|
11
11
|
|
12
12
|
include Request::Callbacks
|
13
13
|
|
@@ -17,6 +17,7 @@ module Acfs
|
|
17
17
|
@format = options.delete(:format) || :json
|
18
18
|
@headers = options.delete(:headers) || {}
|
19
19
|
@params = options.delete(:params) || {}
|
20
|
+
@method = options.delete(:method) || :get
|
20
21
|
|
21
22
|
url.query = nil # params.any? ? params.to_param : nil
|
22
23
|
end.to_s
|
@@ -7,15 +7,20 @@ module Acfs
|
|
7
7
|
module Formats
|
8
8
|
|
9
9
|
def content_type
|
10
|
-
@content_type ||=
|
11
|
-
content_type = headers['Content-Type'].split(/;\s*\w+="?\w+"?/).first
|
12
|
-
Mime::Type.parse(content_type).first
|
13
|
-
end
|
10
|
+
@content_type ||= read_content_type
|
14
11
|
end
|
15
12
|
|
16
13
|
def json?
|
17
14
|
content_type == Mime::JSON
|
18
15
|
end
|
16
|
+
|
17
|
+
private
|
18
|
+
def read_content_type
|
19
|
+
return 'text/plain' unless headers && headers['Content-Type']
|
20
|
+
|
21
|
+
content_type = headers['Content-Type'].split(/;\s*\w+="?\w+"?/).first
|
22
|
+
Mime::Type.parse(content_type).first
|
23
|
+
end
|
19
24
|
end
|
20
25
|
end
|
21
26
|
end
|
data/lib/acfs/service.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
+
require 'acfs/service/request_handler'
|
1
2
|
require 'acfs/service/middleware'
|
2
|
-
require 'acfs/service/queue'
|
3
3
|
|
4
4
|
module Acfs
|
5
5
|
|
@@ -9,7 +9,7 @@ module Acfs
|
|
9
9
|
attr_accessor :options
|
10
10
|
class_attribute :base_url
|
11
11
|
|
12
|
-
include Service::
|
12
|
+
include Service::RequestHandler
|
13
13
|
include Service::Middleware
|
14
14
|
|
15
15
|
def initialize(options = {})
|
@@ -8,11 +8,8 @@ module Acfs
|
|
8
8
|
module Middleware
|
9
9
|
extend ActiveSupport::Concern
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
#
|
14
|
-
def queue(req)
|
15
|
-
super self.class.middleware.call req
|
11
|
+
def prepare(_) # :nodoc:
|
12
|
+
self.class.middleware.call super
|
16
13
|
end
|
17
14
|
|
18
15
|
module ClassMethods
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Acfs
|
2
|
+
class Service
|
3
|
+
|
4
|
+
# Methods to queue or executed request through this service.
|
5
|
+
#
|
6
|
+
module RequestHandler
|
7
|
+
|
8
|
+
# Queue a new request on global adapter queue.
|
9
|
+
#
|
10
|
+
def queue(request)
|
11
|
+
Acfs.adapter.queue prepare request
|
12
|
+
end
|
13
|
+
|
14
|
+
# Executes a request now.
|
15
|
+
#
|
16
|
+
def run(request)
|
17
|
+
Acfs.adapter.run prepare request
|
18
|
+
end
|
19
|
+
|
20
|
+
# Prepares a request to be processed through this service.
|
21
|
+
#
|
22
|
+
def prepare(request)
|
23
|
+
request
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/acfs/version.rb
CHANGED
@@ -13,6 +13,17 @@ describe Acfs::Model::Attributes do
|
|
13
13
|
it 'should set default attributes' do
|
14
14
|
expect(model.new.name).to be == 'John'
|
15
15
|
end
|
16
|
+
|
17
|
+
context 'with dynamic default value' do
|
18
|
+
before do
|
19
|
+
model.attribute :name, :string, default: 'John'
|
20
|
+
model.attribute :mail, :string, default: -> { "#{name}@srv.tld" }
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should set dynamic default attributes' do
|
24
|
+
expect(model.new.mail).to be == 'John@srv.tld'
|
25
|
+
end
|
26
|
+
end
|
16
27
|
end
|
17
28
|
|
18
29
|
describe '#attributes' do
|
@@ -90,7 +101,7 @@ describe Acfs::Model::Attributes do
|
|
90
101
|
it 'should add an attribute to model attribute list' do
|
91
102
|
model.send :attribute, :name, :string
|
92
103
|
|
93
|
-
expect(model.attributes).to be == { :name =>
|
104
|
+
expect(model.attributes).to be == { :name => nil }
|
94
105
|
end
|
95
106
|
|
96
107
|
it 'should accept a default value' do
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Acfs::Model::Dirty do
|
4
|
+
let(:model) { MyUser.new }
|
5
|
+
before do
|
6
|
+
stub_request(:get, "http://users.example.org/users/1").to_return(
|
7
|
+
body: MessagePack.dump({ id: 1, name: 'Anon', age: 12 }),
|
8
|
+
headers: {'Content-Type' => 'application/x-msgpack'})
|
9
|
+
|
10
|
+
stub_request(:post, 'http://users.example.org/users').to_return(
|
11
|
+
body: MessagePack.dump({ id: 5, name: 'dhh', age: 12 }),
|
12
|
+
headers: {'Content-Type' => 'application/x-msgpack'})
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'includes ActiveModel::Dirty' do
|
16
|
+
model.is_a? ActiveModel::Dirty
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#changed?' do
|
20
|
+
context 'after attribute change' do
|
21
|
+
let(:user) { MyUser.new name: 'dhh' }
|
22
|
+
|
23
|
+
it { expect(user).to be_changed }
|
24
|
+
|
25
|
+
context 'and saving' do
|
26
|
+
before { user.save }
|
27
|
+
it { expect(user).to_not be_changed }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'after model load' do
|
32
|
+
let(:user) { MyUser.find 1 }
|
33
|
+
before { user; Acfs.run}
|
34
|
+
|
35
|
+
it { expect(user).to_not be_changed }
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'after model new without attrs' do
|
39
|
+
let(:user) { MyUser.new }
|
40
|
+
|
41
|
+
it { expect(user).to_not be_changed }
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'after model new with attrs' do
|
45
|
+
let(:user) { MyUser.new name: "Uschi" }
|
46
|
+
|
47
|
+
it { expect(user).to be_changed }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
File without changes
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Acfs::Model::Loadable do
|
4
|
+
let(:model) { MyUser.find 1 }
|
5
|
+
before do
|
6
|
+
stub_request(:get, "http://users.example.org/users/1").to_return(
|
7
|
+
body: MessagePack.dump({ id: 1, name: "Anon", age: 12 }),
|
8
|
+
headers: {'Content-Type' => 'application/x-msgpack'})
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '#loaded?' do
|
12
|
+
context 'before Acfs#run' do
|
13
|
+
it { expect(model).to_not be_loaded }
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'afer Acfs#run' do
|
17
|
+
before { model; Acfs.run}
|
18
|
+
it { expect(model).to be_loaded }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Acfs::Model::Locatable do
|
4
|
+
let(:model) { MyUser }
|
5
|
+
before do
|
6
|
+
stub_request(:get, "http://users.example.org/users/1").to_return(
|
7
|
+
body: MessagePack.dump({ id: 1, name: "Anon", age: 12 }),
|
8
|
+
headers: {'Content-Type' => 'application/x-msgpack'})
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '.url' do
|
12
|
+
it 'should return URL' do
|
13
|
+
expect(model.url).to be == 'http://users.example.org/users'
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should return URL with id path part if specified' do
|
17
|
+
expect(model.url(5)).to be == 'http://users.example.org/users/5'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#url' do
|
22
|
+
context 'new resource' do
|
23
|
+
let(:m) { model.new }
|
24
|
+
|
25
|
+
it "should return nil" do
|
26
|
+
expect(m.url).to be == nil
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'new resource with id' do
|
30
|
+
let(:m) { model.new id: 475 }
|
31
|
+
|
32
|
+
it "should return resource URL" do
|
33
|
+
expect(m.url).to be == 'http://users.example.org/users/475'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'loaded resource' do
|
39
|
+
let(:m) { model.find 1 }
|
40
|
+
before { m; Acfs.run }
|
41
|
+
|
42
|
+
it "should return resource's URL" do
|
43
|
+
expect(m.url).to be == 'http://users.example.org/users/1'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Acfs::Model::Persistence do
|
4
|
+
let(:model_class) { MyUser }
|
5
|
+
before do
|
6
|
+
@get_stub = stub_request(:get, "http://users.example.org/users/1").to_return(
|
7
|
+
body: MessagePack.dump({ id: 1, name: "Anon", age: 12 }),
|
8
|
+
headers: {'Content-Type' => 'application/x-msgpack'})
|
9
|
+
|
10
|
+
@patch_stub = stub_request(:put, 'http://users.example.org/users/1')
|
11
|
+
.with(
|
12
|
+
body: '{"id":1,"name":"Idefix","age":12}')
|
13
|
+
.to_return(
|
14
|
+
body: MessagePack.dump({ id: 1, name: 'Idefix', age: 12 }),
|
15
|
+
headers: {'Content-Type' => 'application/x-msgpack'})
|
16
|
+
|
17
|
+
@post_stub = stub_request(:post, 'http://users.example.org/users').to_return(
|
18
|
+
body: MessagePack.dump({ id: 5, name: 'Idefix', age: 12 }),
|
19
|
+
headers: {'Content-Type' => 'application/x-msgpack'})
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'new model' do
|
23
|
+
let(:model) { model_class.new }
|
24
|
+
|
25
|
+
it { expect(model).to_not be_persisted }
|
26
|
+
it { expect(model).to be_new }
|
27
|
+
|
28
|
+
describe '#save!' do
|
29
|
+
context 'when modified' do
|
30
|
+
let(:model) { model_class.find 1 }
|
31
|
+
before do
|
32
|
+
model
|
33
|
+
Acfs.run
|
34
|
+
model.name = 'Idefix'
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should PUT to model URL' do
|
38
|
+
model.save!
|
39
|
+
|
40
|
+
expect(@patch_stub).to have_been_requested
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'when new' do
|
45
|
+
let(:model) { model_class.new name: 'Idefix', age: 12 }
|
46
|
+
|
47
|
+
it 'should POST to collection URL' do
|
48
|
+
model.save!
|
49
|
+
|
50
|
+
expect(@post_stub).to have_been_requested
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'after save' do
|
56
|
+
before { model.save! }
|
57
|
+
|
58
|
+
it { expect(model).to be_persisted }
|
59
|
+
it { expect(model).to_not be_new }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'loaded model' do
|
64
|
+
context 'without changes' do
|
65
|
+
let(:model) { model_class.find 1 }
|
66
|
+
before { model; Acfs.run }
|
67
|
+
|
68
|
+
it { expect(model).to be_persisted }
|
69
|
+
it { expect(model).to_not be_new }
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'with changes' do
|
73
|
+
let(:model) { model_class.find 1 }
|
74
|
+
before { model; Acfs.run; model.name = "dhh" }
|
75
|
+
|
76
|
+
it { expect(model).to_not be_persisted }
|
77
|
+
it { expect(model).to_not be_new }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Acfs::Model::QueryMethods do
|
4
|
+
let(:model) { MyUser }
|
5
|
+
|
6
|
+
describe '.find' do
|
7
|
+
context 'with single id' do
|
8
|
+
before do
|
9
|
+
stub_request(:get, 'http://users.example.org/users/1').to_return(
|
10
|
+
body: MessagePack.dump({ id: 1, name: 'Anon', age: 12 }),
|
11
|
+
headers: {'Content-Type' => 'application/x-msgpack'})
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should load a single remote resource' do
|
15
|
+
user = model.find 1
|
16
|
+
Acfs.run
|
17
|
+
|
18
|
+
expect(user.attributes).to be == { id: 1, name: 'Anon', age: 12 }.stringify_keys
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should invoke callback after model is loaded' do
|
22
|
+
proc = Proc.new { }
|
23
|
+
proc.should_receive(:call) do |user|
|
24
|
+
expect(user).to be === @user
|
25
|
+
expect(user).to be_loaded
|
26
|
+
end
|
27
|
+
|
28
|
+
@user = model.find 1, &proc
|
29
|
+
Acfs.run
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'with multiple ids' do
|
34
|
+
before do
|
35
|
+
stub_request(:get, 'http://users.example.org/users/1').to_return(
|
36
|
+
body: MessagePack.dump({ id: 1, name: 'Anon', age: 12 }),
|
37
|
+
headers: {'Content-Type' => 'application/x-msgpack'})
|
38
|
+
stub_request(:get, 'http://users.example.org/users/2').to_return(
|
39
|
+
body: MessagePack.dump({ id: 2, name: 'Johnny', age: 42 }),
|
40
|
+
headers: {'Content-Type' => 'application/x-msgpack'})
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should load a multiple remote resources' do
|
44
|
+
users = model.find 1, 2
|
45
|
+
Acfs.run
|
46
|
+
|
47
|
+
expect(users.size).to be == 2
|
48
|
+
expect(users[0].attributes).to be == { id: 1, name: 'Anon', age: 12 }.stringify_keys
|
49
|
+
expect(users[1].attributes).to be == { id: 2, name: 'Johnny', age: 42 }.stringify_keys
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should invoke callback after all models are loaded' do
|
53
|
+
proc = Proc.new { }
|
54
|
+
proc.should_receive(:call) do |users|
|
55
|
+
expect(users).to be === @users
|
56
|
+
expect(users.size).to be == 2
|
57
|
+
expect(users).to be_loaded
|
58
|
+
end
|
59
|
+
|
60
|
+
@users = model.find 1, 2, &proc
|
61
|
+
Acfs.run
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/spec/acfs/request_spec.rb
CHANGED
@@ -5,7 +5,8 @@ describe Acfs::Request do
|
|
5
5
|
let(:headers) { nil }
|
6
6
|
let(:params) { nil }
|
7
7
|
let(:data) { nil }
|
8
|
-
let(:
|
8
|
+
let(:method) { :get }
|
9
|
+
let(:options) { {method: method, headers: headers, params: params, data: data} }
|
9
10
|
let(:request) { Acfs::Request.new(url, options) }
|
10
11
|
|
11
12
|
describe '#url' do
|
@@ -39,6 +40,20 @@ describe Acfs::Request do
|
|
39
40
|
end
|
40
41
|
end
|
41
42
|
|
43
|
+
describe '#method' do
|
44
|
+
context 'when nil given' do
|
45
|
+
let(:method) { nil }
|
46
|
+
|
47
|
+
it 'should default to :get' do
|
48
|
+
expect(request.method).to be == :get
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should return request method' do
|
53
|
+
expect(request.method).to be == method
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
42
57
|
describe '#params' do
|
43
58
|
let(:params) { { id: 10 }}
|
44
59
|
|
@@ -8,6 +8,14 @@ describe Acfs::Response::Formats do
|
|
8
8
|
let(:body) { nil }
|
9
9
|
let(:response) { Acfs::Response.new request, status, headers, body }
|
10
10
|
|
11
|
+
context 'without Content-Type header' do
|
12
|
+
let(:headers) { {} }
|
13
|
+
|
14
|
+
it "should fallback on 'text/plain'" do
|
15
|
+
expect(response.content_type).to be == Mime::TEXT
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
11
19
|
context 'with JSON mimetype' do
|
12
20
|
let(:mime_type) { 'application/json' }
|
13
21
|
|
data/spec/acfs_spec.rb
CHANGED
@@ -3,18 +3,18 @@ require 'spec_helper'
|
|
3
3
|
describe "Acfs" do
|
4
4
|
|
5
5
|
before do
|
6
|
-
headers
|
6
|
+
headers = {}
|
7
7
|
stub_request(:get, "http://users.example.org/users").to_return(
|
8
8
|
body: MessagePack.dump([{ id: 1, name: "Anon", age: 12 }, { id: 2, name: "John", age: 26 }]),
|
9
9
|
headers: headers.merge({'Content-Type' => 'application/x-msgpack'}))
|
10
10
|
stub_request(:get, "http://users.example.org/users/2").to_return(
|
11
11
|
body: MessagePack.dump({ id: 2, name: "John", age: 26 }),
|
12
|
-
headers: headers.merge({'Content-Type' => 'application/x-msgpack'}))
|
12
|
+
headers: headers.merge({'Content-Type' => 'application/x-msgpack', 'ETag' => 'LukeSkywalker' }))
|
13
13
|
stub_request(:get, "http://users.example.org/users/3").to_return(
|
14
|
-
body: MessagePack.dump({ id:
|
14
|
+
body: MessagePack.dump({ id: 3, name: "Miraculix", age: 122 }),
|
15
15
|
headers: headers.merge({'Content-Type' => 'application/x-msgpack'}))
|
16
16
|
stub_request(:get, "http://users.example.org/users/100").to_return(
|
17
|
-
body: '{"id":
|
17
|
+
body: '{"id":100,"name":"Jimmy","age":45}',
|
18
18
|
headers: headers.merge({'Content-Type' => 'application/json'}))
|
19
19
|
stub_request(:get, "http://users.example.org/users/2/friends").to_return(
|
20
20
|
body: '[{"id":1,"name":"Anon","age":12}]',
|
@@ -24,6 +24,28 @@ describe "Acfs" do
|
|
24
24
|
headers: headers.merge({'Content-Type' => 'application/json'}))
|
25
25
|
end
|
26
26
|
|
27
|
+
it 'should update single resource synchronously' do
|
28
|
+
stub = stub_request(:put, "http://users.example.org/users/2")
|
29
|
+
.to_return { |request| { body: request.body, headers: {'Content-Type' => request.headers['Content-Type']}} }
|
30
|
+
|
31
|
+
@user = MyUser.find(2)
|
32
|
+
Acfs.run
|
33
|
+
|
34
|
+
expect(@user).to_not be_changed
|
35
|
+
expect(@user).to be_persisted
|
36
|
+
|
37
|
+
@user.name = "Johnny"
|
38
|
+
|
39
|
+
expect(@user).to be_changed
|
40
|
+
expect(@user).to_not be_persisted
|
41
|
+
|
42
|
+
@user.save
|
43
|
+
|
44
|
+
expect(stub).to have_been_requested
|
45
|
+
expect(@user).to_not be_changed
|
46
|
+
expect(@user).to be_persisted
|
47
|
+
end
|
48
|
+
|
27
49
|
it 'should load single resource' do
|
28
50
|
@user = MyUser.find(2)
|
29
51
|
|
@@ -32,6 +54,7 @@ describe "Acfs" do
|
|
32
54
|
Acfs.run
|
33
55
|
|
34
56
|
expect(@user).to be_loaded
|
57
|
+
expect(@user.id).to be == 2
|
35
58
|
expect(@user.name).to be == 'John'
|
36
59
|
expect(@user.age).to be == 26
|
37
60
|
end
|
@@ -51,14 +74,17 @@ describe "Acfs" do
|
|
51
74
|
expect(@users).to be_loaded
|
52
75
|
expect(@users).to have(3).items
|
53
76
|
|
77
|
+
expect(@users[0].id).to be == 2
|
54
78
|
expect(@users[0].name).to be == 'John'
|
55
79
|
expect(@users[0].age).to be == 26
|
56
80
|
expect(@users[0]).to be == @john
|
57
81
|
|
82
|
+
expect(@users[1].id).to be == 3
|
58
83
|
expect(@users[1].name).to be == 'Miraculix'
|
59
84
|
expect(@users[1].age).to be == 122
|
60
85
|
expect(@users[1]).to be == @mirx
|
61
86
|
|
87
|
+
expect(@users[2].id).to be == 100
|
62
88
|
expect(@users[2].name).to be == 'Jimmy'
|
63
89
|
expect(@users[2].age).to be == 45
|
64
90
|
expect(@users[2]).to be == @jimy
|
@@ -95,12 +121,13 @@ describe "Acfs" do
|
|
95
121
|
end
|
96
122
|
|
97
123
|
it 'should load associated resources from different service' do
|
98
|
-
@user = MyUser.find
|
124
|
+
@user = MyUser.find 2 do |user|
|
99
125
|
@comments = Comment.where user: user.id
|
100
126
|
end
|
101
127
|
|
102
128
|
Acfs.run
|
103
129
|
|
130
|
+
expect(@user.id).to be == 2
|
104
131
|
expect(@user.name).to be == 'John'
|
105
132
|
expect(@user.age).to be == 26
|
106
133
|
|
data/spec/support/service.rb
CHANGED
@@ -3,6 +3,7 @@ class UserService < Acfs::Service
|
|
3
3
|
self.base_url = 'http://users.example.org'
|
4
4
|
use Acfs::Middleware::MessagePackDecoder
|
5
5
|
use Acfs::Middleware::JsonDecoder
|
6
|
+
use Acfs::Middleware::JsonEncoder
|
6
7
|
end
|
7
8
|
|
8
9
|
class CommentService < Acfs::Service
|
@@ -23,5 +24,6 @@ class Comment
|
|
23
24
|
include Acfs::Model
|
24
25
|
service CommentService
|
25
26
|
|
27
|
+
attribute :id, :integer
|
26
28
|
attribute :text, :string
|
27
29
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acfs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jan Graichen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-04-
|
11
|
+
date: 2013-04-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -200,18 +200,23 @@ files:
|
|
200
200
|
- lib/acfs.rb
|
201
201
|
- lib/acfs/adapter/typhoeus.rb
|
202
202
|
- lib/acfs/collection.rb
|
203
|
+
- lib/acfs/errors.rb
|
203
204
|
- lib/acfs/middleware/base.rb
|
204
205
|
- lib/acfs/middleware/json_decoder.rb
|
206
|
+
- lib/acfs/middleware/json_encoder.rb
|
205
207
|
- lib/acfs/middleware/msgpack_decoder.rb
|
208
|
+
- lib/acfs/middleware/msgpack_encoder.rb
|
206
209
|
- lib/acfs/middleware/print.rb
|
207
210
|
- lib/acfs/model.rb
|
208
211
|
- lib/acfs/model/attributes.rb
|
209
212
|
- lib/acfs/model/attributes/boolean.rb
|
210
213
|
- lib/acfs/model/attributes/integer.rb
|
211
214
|
- lib/acfs/model/attributes/string.rb
|
215
|
+
- lib/acfs/model/dirty.rb
|
212
216
|
- lib/acfs/model/initialization.rb
|
213
217
|
- lib/acfs/model/loadable.rb
|
214
218
|
- lib/acfs/model/locatable.rb
|
219
|
+
- lib/acfs/model/persistence.rb
|
215
220
|
- lib/acfs/model/query_methods.rb
|
216
221
|
- lib/acfs/model/relations.rb
|
217
222
|
- lib/acfs/model/service.rb
|
@@ -221,18 +226,22 @@ files:
|
|
221
226
|
- lib/acfs/response/formats.rb
|
222
227
|
- lib/acfs/service.rb
|
223
228
|
- lib/acfs/service/middleware.rb
|
224
|
-
- lib/acfs/service/
|
229
|
+
- lib/acfs/service/request_handler.rb
|
225
230
|
- lib/acfs/version.rb
|
226
231
|
- spec/acfs/middleware/json_decoder_spec.rb
|
227
232
|
- spec/acfs/middleware/msgpack_decoder_spec.rb
|
233
|
+
- spec/acfs/model/attributes_spec.rb
|
234
|
+
- spec/acfs/model/dirty_spec.rb
|
235
|
+
- spec/acfs/model/initialization_spec.rb
|
236
|
+
- spec/acfs/model/loadable_spec.rb
|
237
|
+
- spec/acfs/model/locatable_spec.rb
|
238
|
+
- spec/acfs/model/persistance_spec.rb
|
239
|
+
- spec/acfs/model/query_methods_spec.rb
|
228
240
|
- spec/acfs/request/callbacks_spec.rb
|
229
241
|
- spec/acfs/request_spec.rb
|
230
242
|
- spec/acfs/response/formats_spec.rb
|
231
243
|
- spec/acfs/service_spec.rb
|
232
244
|
- spec/acfs_spec.rb
|
233
|
-
- spec/model/attributes_spec.rb
|
234
|
-
- spec/model/initialization_spec.rb
|
235
|
-
- spec/model/locatable_spec.rb
|
236
245
|
- spec/spec_helper.rb
|
237
246
|
- spec/support/service.rb
|
238
247
|
homepage: ''
|
@@ -262,13 +271,17 @@ summary: An abstract API base client for service oriented application.
|
|
262
271
|
test_files:
|
263
272
|
- spec/acfs/middleware/json_decoder_spec.rb
|
264
273
|
- spec/acfs/middleware/msgpack_decoder_spec.rb
|
274
|
+
- spec/acfs/model/attributes_spec.rb
|
275
|
+
- spec/acfs/model/dirty_spec.rb
|
276
|
+
- spec/acfs/model/initialization_spec.rb
|
277
|
+
- spec/acfs/model/loadable_spec.rb
|
278
|
+
- spec/acfs/model/locatable_spec.rb
|
279
|
+
- spec/acfs/model/persistance_spec.rb
|
280
|
+
- spec/acfs/model/query_methods_spec.rb
|
265
281
|
- spec/acfs/request/callbacks_spec.rb
|
266
282
|
- spec/acfs/request_spec.rb
|
267
283
|
- spec/acfs/response/formats_spec.rb
|
268
284
|
- spec/acfs/service_spec.rb
|
269
285
|
- spec/acfs_spec.rb
|
270
|
-
- spec/model/attributes_spec.rb
|
271
|
-
- spec/model/initialization_spec.rb
|
272
|
-
- spec/model/locatable_spec.rb
|
273
286
|
- spec/spec_helper.rb
|
274
287
|
- spec/support/service.rb
|
data/lib/acfs/service/queue.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
module Acfs
|
2
|
-
class Service
|
3
|
-
|
4
|
-
# Allows to queue request on this service that will be
|
5
|
-
# delegated to global Acfs adapter queue.
|
6
|
-
#
|
7
|
-
module Queue
|
8
|
-
|
9
|
-
# Queue a new request on global adapter queue.
|
10
|
-
#
|
11
|
-
def queue(request)
|
12
|
-
Acfs.adapter.queue request
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe 'Acfs::Model::Locatable' do
|
4
|
-
let(:model) { MyUser }
|
5
|
-
|
6
|
-
describe '.url' do
|
7
|
-
it 'should return URL' do
|
8
|
-
expect(model.url).to be == 'http://users.example.org/users'
|
9
|
-
end
|
10
|
-
|
11
|
-
it 'should return URL with id path part if specified' do
|
12
|
-
expect(model.url(5)).to be == 'http://users.example.org/users/5'
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|