acfs 0.20.0 → 0.21.0.b185
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +17 -10
- data/CHANGELOG.md +6 -0
- data/README.md +1 -5
- data/acfs.gemspec +2 -0
- data/lib/acfs.rb +17 -24
- data/lib/acfs/errors.rb +52 -29
- data/lib/acfs/model.rb +35 -36
- data/lib/acfs/model/attributes.rb +2 -2
- data/lib/acfs/model/persistence.rb +55 -6
- data/lib/acfs/model/validation.rb +13 -0
- data/lib/acfs/stub.rb +1 -1
- data/lib/acfs/version.rb +1 -1
- data/spec/acfs/model/attributes_spec.rb +1 -1
- data/spec/acfs/model/persistance_spec.rb +57 -3
- data/spec/acfs/model/validation_spec.rb +54 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/support/service.rb +12 -6
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 24c2d64318701de68d4bebf2c0454ae17222f41e
|
4
|
+
data.tar.gz: 7b058dbf9ce187553aa1a41420b3792b96f4b8f3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d2b103a60ada7149b1f58c79ffaad1f2419116040742217933819840b940b7f17ffa7a03294835b87ad346a33509c996b33872efd845b59fece94ce72bf265e8
|
7
|
+
data.tar.gz: 425866d67a2dd571cfd1e5dcb9519616720bf7059ec58004dd4ab61f06f94cf508385448dd9f1674937701e95ffb40ec05f4763803eae403ae5170f1611c39d8
|
data/.travis.yml
CHANGED
@@ -1,15 +1,22 @@
|
|
1
1
|
language: ruby
|
2
2
|
bundler_args: --without development
|
3
3
|
rvm:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
- 2.0.0
|
5
|
+
- 1.9.3
|
6
|
+
- jruby
|
7
|
+
- rbx-19mode
|
9
8
|
gemfile:
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
- gemfiles/Gemfile.rails-4-0
|
10
|
+
- gemfiles/Gemfile.rails-3-2
|
11
|
+
- gemfiles/Gemfile.rails-3-1
|
14
12
|
services:
|
15
|
-
|
13
|
+
- rabbitmq
|
14
|
+
deploy:
|
15
|
+
provider: rubygems
|
16
|
+
api_key:
|
17
|
+
secure: gNudZK0JaRRweudmkpdkJjUMydItTSW5cXjpYdYCfahqd/cD0xPjxotr2TCHrJibfVauoT/PytbQWcP3jnOYytp6oS0up5Y+uKpGmbqVYx/rZvShWALszcBs71lUh/IZpDXNHc+yo/01HCn10/uQUFRtrjWgMwHtHxXb09xE4wQ=
|
18
|
+
gem: acfs
|
19
|
+
on:
|
20
|
+
branch: master
|
21
|
+
repo: jgraichen/acfs
|
22
|
+
rvm: 2.0.0
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -15,7 +15,7 @@ Acfs covers model and service abstraction, convenient query and filter methods,
|
|
15
15
|
|
16
16
|
Add this line to your application's Gemfile:
|
17
17
|
|
18
|
-
gem 'acfs', '~> 0.
|
18
|
+
gem 'acfs', '~> 0.21.0'
|
19
19
|
|
20
20
|
**Note:** Acfs is under development. I'll try to avoid changes to the public API but internal APIs may change quite often.
|
21
21
|
|
@@ -212,10 +212,6 @@ Removed in 0.20.0. See [jgraichen/msgr](https://github.com/jgraichen/msgr) for a
|
|
212
212
|
* Rails responders providing REST operations with integrated ETag,
|
213
213
|
Modified Headers, conflict detection, ...
|
214
214
|
* Pagination? Filtering? (If service API provides such features.)
|
215
|
-
* Messaging Queue support for services and models
|
216
|
-
* Allow triggering messages on resource events (CRUD)
|
217
|
-
* Abstract messages into objects
|
218
|
-
* Middleware stack for messages?
|
219
215
|
* Documentation
|
220
216
|
|
221
217
|
## Contributing
|
data/acfs.gemspec
CHANGED
data/lib/acfs.rb
CHANGED
@@ -4,35 +4,30 @@ require 'active_support/core_ext/class'
|
|
4
4
|
require 'active_support/core_ext/string'
|
5
5
|
require 'active_support/core_ext/module'
|
6
6
|
|
7
|
-
require 'acfs/version'
|
8
|
-
require 'acfs/errors'
|
9
|
-
require 'acfs/global'
|
10
|
-
|
11
7
|
module Acfs
|
12
8
|
extend ActiveSupport::Autoload
|
9
|
+
require 'acfs/version'
|
10
|
+
require 'acfs/errors'
|
11
|
+
require 'acfs/global'
|
12
|
+
|
13
|
+
require 'acfs/collection'
|
14
|
+
require 'acfs/configuration'
|
15
|
+
require 'acfs/model'
|
16
|
+
require 'acfs/operation'
|
17
|
+
require 'acfs/request'
|
18
|
+
require 'acfs/resource'
|
19
|
+
require 'acfs/response'
|
20
|
+
require 'acfs/runner'
|
21
|
+
require 'acfs/service'
|
22
|
+
|
13
23
|
extend Global
|
14
24
|
|
15
|
-
autoload :Collection
|
16
|
-
autoload :Model
|
17
|
-
autoload :Request
|
18
|
-
autoload :Response
|
19
|
-
autoload :Service
|
20
25
|
autoload :Stub
|
21
|
-
autoload :Operation
|
22
|
-
autoload :Runner
|
23
|
-
autoload :Configuration
|
24
|
-
|
25
|
-
module Messaging
|
26
|
-
extend ActiveSupport::Autoload
|
27
|
-
|
28
|
-
autoload :Client
|
29
|
-
autoload :Receiver
|
30
|
-
end
|
31
26
|
|
32
27
|
module Middleware
|
33
28
|
extend ActiveSupport::Autoload
|
29
|
+
require 'acfs/middleware/base'
|
34
30
|
|
35
|
-
autoload :Base
|
36
31
|
autoload :Print
|
37
32
|
autoload :Logger
|
38
33
|
autoload :JsonDecoder
|
@@ -42,10 +37,8 @@ module Acfs
|
|
42
37
|
end
|
43
38
|
|
44
39
|
module Adapter
|
45
|
-
|
46
|
-
|
47
|
-
autoload :Base
|
48
|
-
autoload :Typhoeus
|
40
|
+
require 'acfs/adapter/base'
|
41
|
+
require 'acfs/adapter/typhoeus'
|
49
42
|
end
|
50
43
|
end
|
51
44
|
|
data/lib/acfs/errors.rb
CHANGED
@@ -3,46 +3,52 @@ module Acfs
|
|
3
3
|
# Acfs base error.
|
4
4
|
#
|
5
5
|
class Error < StandardError
|
6
|
+
def initialize(opts = {}, message = nil)
|
7
|
+
opts.merge! message: message if message
|
8
|
+
super opts[:message]
|
9
|
+
end
|
6
10
|
end
|
7
11
|
|
8
12
|
# Response error containing the responsible response object.
|
9
13
|
#
|
10
14
|
class ErroneousResponse < Error
|
11
|
-
|
15
|
+
attr_reader :response
|
12
16
|
|
13
|
-
def initialize(
|
14
|
-
|
15
|
-
message = ''
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
17
|
+
def initialize(opts = {})
|
18
|
+
@response = opts[:response]
|
19
|
+
message = 'Received erroneous response'
|
20
|
+
if response
|
21
|
+
message << ": #{response.code}"
|
22
|
+
if response.data
|
23
|
+
message << "\n with content:\n "
|
24
|
+
message << response.data.map{|k,v| "#{k.inspect}: #{v.inspect}"}.join("\n ")
|
25
|
+
end
|
26
|
+
if response.headers.any?
|
27
|
+
message << "\n with headers:\n "
|
28
|
+
message << response.headers.map{|k,v| "#{k}: #{v}"}.join("\n ")
|
29
|
+
end
|
30
|
+
message << "\nbased on request: #{response.request.method.upcase} #{response.request.url} #{response.request.format}"
|
31
|
+
if response.request.data
|
32
|
+
message << "\n with content:\n "
|
33
|
+
message << response.request.data.map{|k,v| "#{k.inspect}: #{v.inspect}"}.join("\n ")
|
34
|
+
end
|
35
|
+
if response.request.headers.any?
|
36
|
+
message << "\n with headers:\n "
|
37
|
+
message << response.request.headers.map{|k,v| "#{k}: #{v}"}.join("\n ")
|
38
|
+
end
|
29
39
|
end
|
30
|
-
|
31
|
-
message << "\n with headers:\n "
|
32
|
-
message << response.request.headers.map{|k,v| "#{k}: #{v}"}.join("\n ")
|
33
|
-
end
|
34
|
-
super message
|
40
|
+
super opts, message
|
35
41
|
end
|
36
42
|
end
|
37
43
|
|
38
44
|
class AmbiguousStubError < Error
|
39
45
|
attr_reader :stubs, :operation
|
40
46
|
|
41
|
-
def initialize(
|
42
|
-
@stubs = stubs
|
43
|
-
@operation = operation
|
47
|
+
def initialize(opts = {})
|
48
|
+
@stubs = opts.delete :stubs
|
49
|
+
@operation = opts.delete :operation
|
44
50
|
|
45
|
-
super 'Ambiguous stubs.'
|
51
|
+
super opts, 'Ambiguous stubs.'
|
46
52
|
end
|
47
53
|
|
48
54
|
end
|
@@ -53,10 +59,27 @@ module Acfs
|
|
53
59
|
end
|
54
60
|
|
55
61
|
class InvalidResource < ErroneousResponse
|
56
|
-
|
62
|
+
attr_reader :errors, :resource
|
63
|
+
|
64
|
+
def initialize(opts = {})
|
65
|
+
@errors = opts.delete :errors
|
66
|
+
@resource = opts.delete :resource
|
67
|
+
super
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# A ResourceNotLoaded error will be thrown when calling some
|
72
|
+
# modifing methods on not loaded resources as it is usally
|
73
|
+
# unwanted to call e.g. `update_attributes` on a not loaded
|
74
|
+
# resource.
|
75
|
+
# Correct solution is to first run `Acfs.run` to fetch the
|
76
|
+
# resource and then update the resource.
|
77
|
+
#
|
78
|
+
class ResourceNotLoaded < Error
|
79
|
+
attr_reader :resource
|
57
80
|
|
58
|
-
def initialize(
|
59
|
-
|
81
|
+
def initialize(opts = {})
|
82
|
+
@resource = opts.delete :resource
|
60
83
|
super
|
61
84
|
end
|
62
85
|
end
|
data/lib/acfs/model.rb
CHANGED
@@ -1,44 +1,43 @@
|
|
1
1
|
require 'active_model'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
require 'acfs/model/
|
7
|
-
require 'acfs/model/
|
8
|
-
require 'acfs/model/
|
9
|
-
require 'acfs/model/
|
10
|
-
require 'acfs/model/
|
11
|
-
require 'acfs/model/
|
3
|
+
# @api public
|
4
|
+
#
|
5
|
+
module Acfs::Model
|
6
|
+
require 'acfs/model/attributes'
|
7
|
+
require 'acfs/model/dirty'
|
8
|
+
require 'acfs/model/loadable'
|
9
|
+
require 'acfs/model/locatable'
|
10
|
+
require 'acfs/model/operational'
|
11
|
+
require 'acfs/model/persistence'
|
12
|
+
require 'acfs/model/query_methods'
|
13
|
+
require 'acfs/model/relations'
|
14
|
+
require 'acfs/model/service'
|
15
|
+
require 'acfs/model/validation'
|
12
16
|
|
13
|
-
|
17
|
+
extend ActiveSupport::Concern
|
14
18
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
+
included do
|
20
|
+
if ActiveModel::VERSION::MAJOR >= 4
|
21
|
+
include ActiveModel::Model
|
22
|
+
else
|
23
|
+
extend ActiveModel::Naming
|
24
|
+
extend ActiveModel::Translation
|
25
|
+
include ActiveModel::Conversion
|
26
|
+
include ActiveModel::Validations
|
19
27
|
|
20
|
-
|
21
|
-
|
22
|
-
include ActiveModel::Model
|
23
|
-
else
|
24
|
-
extend ActiveModel::Naming
|
25
|
-
extend ActiveModel::Translation
|
26
|
-
include ActiveModel::Conversion
|
27
|
-
include ActiveModel::Validations
|
28
|
-
|
29
|
-
require 'acfs/model/initialization'
|
30
|
-
include Model::Initialization
|
31
|
-
end
|
32
|
-
|
33
|
-
include Model::Attributes
|
34
|
-
include Model::Loadable
|
35
|
-
include Model::Persistence
|
36
|
-
include Model::Locatable
|
37
|
-
include Model::Operational
|
38
|
-
include Model::QueryMethods
|
39
|
-
include Model::Relations
|
40
|
-
include Model::Service
|
41
|
-
include Model::Dirty
|
28
|
+
require 'acfs/model/initialization'
|
29
|
+
include Initialization
|
42
30
|
end
|
31
|
+
|
32
|
+
include Attributes
|
33
|
+
include Loadable
|
34
|
+
include Persistence
|
35
|
+
include Locatable
|
36
|
+
include Operational
|
37
|
+
include QueryMethods
|
38
|
+
include Relations
|
39
|
+
include Service
|
40
|
+
include Dirty
|
41
|
+
include Validation
|
43
42
|
end
|
44
43
|
end
|
@@ -187,7 +187,7 @@ module Acfs::Model
|
|
187
187
|
# @return [ Hash{ String => Object, Proc } ] Attributes with default values.
|
188
188
|
#
|
189
189
|
def attributes
|
190
|
-
@attributes ||= {}
|
190
|
+
@attributes ||= {}.merge superclass.respond_to?(:attributes) ? superclass.attributes : {}
|
191
191
|
end
|
192
192
|
|
193
193
|
# @api public
|
@@ -205,7 +205,7 @@ module Acfs::Model
|
|
205
205
|
# @return [ Hash{ Symbol => Class } ] Attributes and their types.
|
206
206
|
#
|
207
207
|
def attribute_types
|
208
|
-
@attribute_types ||= {}
|
208
|
+
@attribute_types ||= {}.merge superclass.respond_to?(:attribute_types) ? superclass.attribute_types : {}
|
209
209
|
end
|
210
210
|
|
211
211
|
private
|
@@ -26,7 +26,7 @@ module Acfs
|
|
26
26
|
# user2.save
|
27
27
|
# user2.persisted? # => true
|
28
28
|
#
|
29
|
-
# @return [
|
29
|
+
# @return [Boolean] True if resource has no changes and is not newly created, false otherwise.
|
30
30
|
#
|
31
31
|
def persisted?
|
32
32
|
!new? && !changed?
|
@@ -36,7 +36,7 @@ module Acfs
|
|
36
36
|
#
|
37
37
|
# Return true if model is a new record and was not saved yet.
|
38
38
|
#
|
39
|
-
# @return [
|
39
|
+
# @return [Boolean] True if resource is newly created, false otherwise.
|
40
40
|
#
|
41
41
|
def new?
|
42
42
|
read_attribute(:id).nil?
|
@@ -52,7 +52,7 @@ module Acfs
|
|
52
52
|
#
|
53
53
|
# Saving a resource is a synchronous operation.
|
54
54
|
#
|
55
|
-
# @return [
|
55
|
+
# @return [Boolean] True if save operation was successful, false otherwise.
|
56
56
|
# @see #save! See #save! for available options.
|
57
57
|
#
|
58
58
|
def save(*args)
|
@@ -79,8 +79,6 @@ module Acfs
|
|
79
79
|
# @see #save
|
80
80
|
#
|
81
81
|
def save!(opts = {})
|
82
|
-
#raise ::Acfs::InvalidResource errors: errors.to_a unless valid?
|
83
|
-
|
84
82
|
opts[:data] = attributes unless opts[:data]
|
85
83
|
|
86
84
|
operation (new? ? :create : :update), opts do |data|
|
@@ -88,13 +86,60 @@ module Acfs
|
|
88
86
|
end
|
89
87
|
end
|
90
88
|
|
89
|
+
# @api public
|
90
|
+
#
|
91
|
+
# Update attributes with given data and save resource.
|
92
|
+
#
|
93
|
+
# Saving a resource is a synchronous operation.
|
94
|
+
#
|
95
|
+
# @param [Hash] attrs Hash with attributes to write.
|
96
|
+
# @param [Hash] opts Options passed to `save`.
|
97
|
+
#
|
98
|
+
# @return [Boolean] True if save operation was successful, false otherwise.
|
99
|
+
#
|
100
|
+
# @see #save
|
101
|
+
# @see #attributes=
|
102
|
+
# @see #update_attributes!
|
103
|
+
#
|
104
|
+
def update_attributes(attrs, opts = {})
|
105
|
+
check_loaded! opts
|
106
|
+
|
107
|
+
self.attributes = attrs
|
108
|
+
save opts
|
109
|
+
end
|
110
|
+
|
111
|
+
# @api public
|
112
|
+
#
|
113
|
+
# Update attributes with given data and save resource.
|
114
|
+
#
|
115
|
+
# Saving a resource is a synchronous operation.
|
116
|
+
#
|
117
|
+
# @param [Hash] attrs Hash with attributes to write.
|
118
|
+
# @param [Hash] opts Options passed to `save!`.
|
119
|
+
#
|
120
|
+
# @raise [Acfs::InvalidResource]
|
121
|
+
# If remote services respond with 422 response. Will fill errors with data from response
|
122
|
+
# @raise [Acfs::ErroneousResponse]
|
123
|
+
# If remote service respond with not successful response.
|
124
|
+
#
|
125
|
+
# @see #save!
|
126
|
+
# @see #attributes=
|
127
|
+
# @see #update_attributes
|
128
|
+
#
|
129
|
+
def update_attributes!(attrs, opts = {})
|
130
|
+
check_loaded! opts
|
131
|
+
|
132
|
+
self.attributes = attrs
|
133
|
+
save! opts
|
134
|
+
end
|
135
|
+
|
91
136
|
# @api public
|
92
137
|
#
|
93
138
|
# Destroy resource by sending a DELETE request.
|
94
139
|
#
|
95
140
|
# Deleting a resource is a synchronous operation.
|
96
141
|
#
|
97
|
-
# @return [
|
142
|
+
# @return [Boolean]
|
98
143
|
# @see #delete!
|
99
144
|
#
|
100
145
|
def delete(opts = {})
|
@@ -186,6 +231,10 @@ module Acfs
|
|
186
231
|
self.attributes = data
|
187
232
|
loaded!
|
188
233
|
end
|
234
|
+
|
235
|
+
def check_loaded!(opts = {})
|
236
|
+
raise ResourceNotLoaded, resource: self unless loaded? or opts[:force]
|
237
|
+
end
|
189
238
|
end
|
190
239
|
end
|
191
240
|
end
|
data/lib/acfs/stub.rb
CHANGED
@@ -98,7 +98,7 @@ module Acfs
|
|
98
98
|
|
99
99
|
accepted_stubs = stubs.select { |stub| stub.accept? op }
|
100
100
|
|
101
|
-
raise AmbiguousStubError.new accepted_stubs, op if accepted_stubs.size > 1
|
101
|
+
raise AmbiguousStubError.new stubs: accepted_stubs, operation: op if accepted_stubs.size > 1
|
102
102
|
|
103
103
|
accepted_stubs.first
|
104
104
|
end
|
data/lib/acfs/version.rb
CHANGED
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
describe Acfs::Model::Persistence do
|
4
4
|
let(:model_class) { MyUser }
|
5
5
|
before do
|
6
|
-
@get_stub = stub_request(:get, 'http://users.example.org/users/1').to_return response({ id: 1, name:
|
6
|
+
@get_stub = stub_request(:get, 'http://users.example.org/users/1').to_return response({ id: 1, name: 'Anon', age: 12 })
|
7
7
|
|
8
8
|
@patch_stub = stub_request(:put, 'http://users.example.org/users/1')
|
9
9
|
.with(body: '{"id":1,"name":"Idefix","age":12}')
|
@@ -71,6 +71,20 @@ describe Acfs::Model::Persistence do
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
+
context 'unloaded model' do
|
75
|
+
let!(:model) { model_class.find 1 }
|
76
|
+
|
77
|
+
describe '#update_attributes' do
|
78
|
+
subject { -> { model.update_attributes name: 'John' } }
|
79
|
+
it { expect{ subject.call }.to raise_error Acfs::ResourceNotLoaded }
|
80
|
+
end
|
81
|
+
|
82
|
+
describe '#update_attributes!' do
|
83
|
+
subject { -> { model.update_attributes! name: 'John' } }
|
84
|
+
it { expect{ subject.call }.to raise_error Acfs::ResourceNotLoaded }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
74
88
|
context 'loaded model' do
|
75
89
|
context 'without changes' do
|
76
90
|
let(:model) { model_class.find 1 }
|
@@ -102,6 +116,46 @@ describe Acfs::Model::Persistence do
|
|
102
116
|
expect(model).to be_frozen
|
103
117
|
end
|
104
118
|
end
|
119
|
+
|
120
|
+
describe '#update_atributes!' do
|
121
|
+
let(:model) { model_class.find 1 }
|
122
|
+
before { model; Acfs.run }
|
123
|
+
|
124
|
+
it 'should set attributes' do
|
125
|
+
model.update_attributes name: 'Idefix'
|
126
|
+
expect(model.attributes.symbolize_keys).to eq id: 1, name: 'Idefix', age: 12
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should save resource' do
|
130
|
+
expect(model).to receive(:save).with({})
|
131
|
+
model.update_attributes name: 'Idefix'
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'should pass second hash to save' do
|
135
|
+
expect(model).to receive(:save).with({ bla: 'blub' })
|
136
|
+
model.update_attributes({ name: 'Idefix' }, { bla: 'blub' })
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
describe '#update_atributes' do
|
141
|
+
let(:model) { model_class.find 1 }
|
142
|
+
before { model; Acfs.run }
|
143
|
+
|
144
|
+
it 'should set attributes' do
|
145
|
+
model.update_attributes! name: 'Idefix'
|
146
|
+
expect(model.attributes.symbolize_keys).to eq id: 1, name: 'Idefix', age: 12
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'should save resource' do
|
150
|
+
expect(model).to receive(:save!).with({})
|
151
|
+
model.update_attributes! name: 'Idefix'
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'should pass second hash to save' do
|
155
|
+
expect(model).to receive(:save!).with({ bla: 'blub' })
|
156
|
+
model.update_attributes!({ name: 'Idefix' }, { bla: 'blub' })
|
157
|
+
end
|
158
|
+
end
|
105
159
|
end
|
106
160
|
|
107
161
|
describe '.create!' do
|
@@ -125,7 +179,7 @@ describe Acfs::Model::Persistence do
|
|
125
179
|
|
126
180
|
it 'should raise an error' do
|
127
181
|
expect { model_class.create! data }.to raise_error ::Acfs::InvalidResource do |error|
|
128
|
-
expect(error.errors).to be == { name:
|
182
|
+
expect(error.errors).to be == { name: %w(required) }.stringify_keys
|
129
183
|
end
|
130
184
|
end
|
131
185
|
end
|
@@ -157,7 +211,7 @@ describe Acfs::Model::Persistence do
|
|
157
211
|
|
158
212
|
it 'should contain error hash' do
|
159
213
|
model = model_class.create data
|
160
|
-
expect(model.errors.to_hash).to be == { name:
|
214
|
+
expect(model.errors.to_hash).to be == { name: %w(required) }.stringify_keys
|
161
215
|
end
|
162
216
|
end
|
163
217
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Acfs::Model::Validation do
|
4
|
+
let(:params) { {} }
|
5
|
+
let(:model) { MyUserWithValidations.new params }
|
6
|
+
|
7
|
+
describe '#valid?' do
|
8
|
+
context 'with valid attributes' do
|
9
|
+
let(:params) { {name: 'john smith', age: 24} }
|
10
|
+
subject { model }
|
11
|
+
|
12
|
+
it { should be_valid }
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'with invalid attributes' do
|
16
|
+
let(:params) { {name: 'invname'} }
|
17
|
+
subject { model }
|
18
|
+
|
19
|
+
it { should_not be_valid }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#errors' do
|
24
|
+
context 'with valid attributes' do
|
25
|
+
let(:params) { {name: 'john smith', age: 24} }
|
26
|
+
before { model.valid? }
|
27
|
+
subject { model.errors }
|
28
|
+
|
29
|
+
it { should be_empty }
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'with invalid attributes' do
|
33
|
+
let(:params) { {name: 'john'} }
|
34
|
+
before { model.valid? }
|
35
|
+
subject { model.errors }
|
36
|
+
|
37
|
+
it { should_not be_empty }
|
38
|
+
it { should have(2).items }
|
39
|
+
|
40
|
+
it 'should contain a list of error messages' do
|
41
|
+
expect(subject.to_hash).to eq age: ["can't be blank"], name: ['is invalid']
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '#save!' do
|
47
|
+
context 'with invalid attributes' do
|
48
|
+
let(:params) { {name: 'john'} }
|
49
|
+
subject { -> { model.save! } }
|
50
|
+
|
51
|
+
it { expect { subject.call }.to raise_error Acfs::InvalidResource }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -21,7 +21,7 @@ RSpec.configure do |config|
|
|
21
21
|
# order dependency and want to debug it, you can fix the order by providing
|
22
22
|
# the seed, which is printed after each run.
|
23
23
|
# --seed 1234
|
24
|
-
config.order =
|
24
|
+
config.order = 'random'
|
25
25
|
|
26
26
|
config.expect_with :rspec do |c|
|
27
27
|
# Only allow expect syntax
|
data/spec/support/service.rb
CHANGED
@@ -16,8 +16,7 @@ class CommentService < Acfs::Service
|
|
16
16
|
use Acfs::Middleware::JsonDecoder
|
17
17
|
end
|
18
18
|
|
19
|
-
class MyUser
|
20
|
-
include Acfs::Model
|
19
|
+
class MyUser < Acfs::Resource
|
21
20
|
service UserService, path: 'users'
|
22
21
|
|
23
22
|
attribute :id, :integer
|
@@ -25,16 +24,23 @@ class MyUser
|
|
25
24
|
attribute :age, :integer
|
26
25
|
end
|
27
26
|
|
28
|
-
class
|
29
|
-
|
27
|
+
class MyUserInherited < MyUser
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
class MyUserWithValidations < MyUser
|
32
|
+
validates_presence_of :name, :age
|
33
|
+
validates_format_of :name, with: /\A\w+\s+\w+.?\z/
|
34
|
+
end
|
35
|
+
|
36
|
+
class Session < Acfs::Resource
|
30
37
|
service UserService
|
31
38
|
|
32
39
|
attribute :id, :string
|
33
40
|
attribute :user, :integer
|
34
41
|
end
|
35
42
|
|
36
|
-
class Comment
|
37
|
-
include Acfs::Model
|
43
|
+
class Comment < Acfs::Resource
|
38
44
|
service CommentService
|
39
45
|
|
40
46
|
attribute :id, :integer
|
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.21.0.b185
|
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-08-
|
11
|
+
date: 2013-08-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -160,6 +160,7 @@ files:
|
|
160
160
|
- lib/acfs/model/query_methods.rb
|
161
161
|
- lib/acfs/model/relations.rb
|
162
162
|
- lib/acfs/model/service.rb
|
163
|
+
- lib/acfs/model/validation.rb
|
163
164
|
- lib/acfs/operation.rb
|
164
165
|
- lib/acfs/request.rb
|
165
166
|
- lib/acfs/request/callbacks.rb
|
@@ -187,6 +188,7 @@ files:
|
|
187
188
|
- spec/acfs/model/locatable_spec.rb
|
188
189
|
- spec/acfs/model/persistance_spec.rb
|
189
190
|
- spec/acfs/model/query_methods_spec.rb
|
191
|
+
- spec/acfs/model/validation_spec.rb
|
190
192
|
- spec/acfs/request/callbacks_spec.rb
|
191
193
|
- spec/acfs/request_spec.rb
|
192
194
|
- spec/acfs/response/formats_spec.rb
|
@@ -214,9 +216,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
214
216
|
version: '0'
|
215
217
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
216
218
|
requirements:
|
217
|
-
- - '
|
219
|
+
- - '>'
|
218
220
|
- !ruby/object:Gem::Version
|
219
|
-
version:
|
221
|
+
version: 1.3.1
|
220
222
|
requirements: []
|
221
223
|
rubyforge_project:
|
222
224
|
rubygems_version: 2.0.3
|
@@ -237,6 +239,7 @@ test_files:
|
|
237
239
|
- spec/acfs/model/locatable_spec.rb
|
238
240
|
- spec/acfs/model/persistance_spec.rb
|
239
241
|
- spec/acfs/model/query_methods_spec.rb
|
242
|
+
- spec/acfs/model/validation_spec.rb
|
240
243
|
- spec/acfs/request/callbacks_spec.rb
|
241
244
|
- spec/acfs/request_spec.rb
|
242
245
|
- spec/acfs/response/formats_spec.rb
|
@@ -249,4 +252,3 @@ test_files:
|
|
249
252
|
- spec/spec_helper.rb
|
250
253
|
- spec/support/response.rb
|
251
254
|
- spec/support/service.rb
|
252
|
-
has_rdoc:
|