arrest 0.0.21 → 0.0.23
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.
- data/lib/arrest/abstract_resource.rb +56 -7
- data/lib/arrest/attributes/attribute.rb +2 -2
- data/lib/arrest/attributes/belongs_to.rb +2 -2
- data/lib/arrest/attributes/converter.rb +2 -2
- data/lib/arrest/attributes/has_attributes.rb +5 -2
- data/lib/arrest/attributes/has_many_sub_resource_attribute.rb +2 -2
- data/lib/arrest/attributes/nested_attribute.rb +3 -3
- data/lib/arrest/attributes/polymorphic_attribute.rb +6 -1
- data/lib/arrest/helper/has_many_collection.rb +2 -2
- data/lib/arrest/http_source.rb +21 -16
- data/lib/arrest/mem_source.rb +7 -7
- data/lib/arrest/nested_resource.rb +8 -1
- data/lib/arrest/rest_child.rb +11 -11
- data/lib/arrest/root_resource.rb +18 -18
- data/lib/arrest/version.rb +1 -1
- data/test/context.rb +35 -0
- data/test/nested_resource.rb +10 -9
- data/test/unit.rb +126 -124
- metadata +24 -22
@@ -6,6 +6,45 @@ require 'active_model'
|
|
6
6
|
Scope = Struct.new(:name, :block)
|
7
7
|
|
8
8
|
module Arrest
|
9
|
+
|
10
|
+
class RequestContext
|
11
|
+
attr_accessor :header_decorator
|
12
|
+
end
|
13
|
+
|
14
|
+
class ScopedRoot
|
15
|
+
attr_accessor :context
|
16
|
+
|
17
|
+
def initialize(context = Arrest::RequestContext.new())
|
18
|
+
@context = context
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.register_resource(clazz)
|
22
|
+
send :define_method, ClassUtils.simple_name(clazz) do ||
|
23
|
+
proxy = clazz.mk_proxy(self)
|
24
|
+
proxy
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_context
|
29
|
+
@context
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class ResourceProxy
|
34
|
+
def initialize(resource, context_provider)
|
35
|
+
@resource = resource
|
36
|
+
@context_provider = context_provider
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
def method_missing(*args, &block)
|
41
|
+
params = [@context_provider.get_context]
|
42
|
+
params += args.drop(1)
|
43
|
+
@resource.send(args.first, *params)
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
9
48
|
class AbstractResource
|
10
49
|
extend ActiveModel::Naming
|
11
50
|
include ActiveModel::Validations
|
@@ -13,9 +52,19 @@ module Arrest
|
|
13
52
|
include HasAttributes
|
14
53
|
attribute :id, String
|
15
54
|
|
55
|
+
attr_accessor :context
|
56
|
+
|
16
57
|
class << self
|
17
58
|
attr_reader :scopes
|
18
59
|
|
60
|
+
def inherited(child)
|
61
|
+
ScopedRoot::register_resource(child)
|
62
|
+
end
|
63
|
+
|
64
|
+
def mk_proxy(context_provider)
|
65
|
+
ResourceProxy.new(self, context_provider)
|
66
|
+
end
|
67
|
+
|
19
68
|
def source
|
20
69
|
Arrest::Source::source
|
21
70
|
end
|
@@ -33,8 +82,7 @@ module Arrest
|
|
33
82
|
end
|
34
83
|
|
35
84
|
def build(hash)
|
36
|
-
resource = self.new(hash, true)
|
37
|
-
|
85
|
+
resource = self.new(@context, hash, true)
|
38
86
|
resource
|
39
87
|
end
|
40
88
|
|
@@ -46,7 +94,7 @@ module Arrest
|
|
46
94
|
if @custom_resource_name
|
47
95
|
@custom_resource_name
|
48
96
|
else
|
49
|
-
StringUtils.plural
|
97
|
+
StringUtils.plural(self.name.sub(/.*:/,'').downcase)
|
50
98
|
end
|
51
99
|
end
|
52
100
|
|
@@ -148,7 +196,8 @@ module Arrest
|
|
148
196
|
|
149
197
|
attr_accessor :id
|
150
198
|
|
151
|
-
def initialize(hash={}, from_json = false)
|
199
|
+
def initialize(context, hash={}, from_json = false)
|
200
|
+
@context = context
|
152
201
|
initialize_has_attributes(hash, from_json)
|
153
202
|
end
|
154
203
|
|
@@ -156,14 +205,14 @@ module Arrest
|
|
156
205
|
if Source.skip_validations || self.valid?
|
157
206
|
req_type = new_record? ? :post : :put
|
158
207
|
|
159
|
-
success = !!AbstractResource::source.send(req_type, self)
|
208
|
+
success = !!AbstractResource::source.send(req_type, @context, self)
|
160
209
|
|
161
210
|
if success
|
162
211
|
# check for sub resources in case of n:m relationships
|
163
212
|
self.class.all_fields.find_all{|f| f.is_a?(HasManySubResourceAttribute)}.each do |attr|
|
164
213
|
ids = self.send(attr.name) # get ids_field e.g. for team has_many :users get 'self.user_ids'
|
165
214
|
srifn = attr.sub_resource_field_name
|
166
|
-
result = !!AbstractResource::source.put_sub_resource(self, srifn, ids)
|
215
|
+
result = !!AbstractResource::source.put_sub_resource( self, srifn, ids)
|
167
216
|
return false if !result
|
168
217
|
end
|
169
218
|
return true
|
@@ -177,7 +226,7 @@ module Arrest
|
|
177
226
|
end
|
178
227
|
|
179
228
|
def delete
|
180
|
-
AbstractResource::source().delete self
|
229
|
+
AbstractResource::source().delete(@context, self)
|
181
230
|
true
|
182
231
|
end
|
183
232
|
|
@@ -8,7 +8,7 @@ module Arrest
|
|
8
8
|
@json_name = Source.json_key_converter.key_to_json(name).to_sym
|
9
9
|
end
|
10
10
|
|
11
|
-
def from_hash value
|
11
|
+
def from_hash(parent, value)
|
12
12
|
return if value == nil
|
13
13
|
converter = CONVERTER[@clazz]
|
14
14
|
if converter == nil
|
@@ -28,4 +28,4 @@ module Arrest
|
|
28
28
|
converter.mk_json value
|
29
29
|
end
|
30
30
|
end
|
31
|
-
end
|
31
|
+
end
|
@@ -51,9 +51,9 @@ module Arrest
|
|
51
51
|
|
52
52
|
begin
|
53
53
|
if polymorphic
|
54
|
-
Arrest::Source.mod.const_get(polymorphic[val.type.to_sym]).find(val.id)
|
54
|
+
Arrest::Source.mod.const_get(polymorphic[val.type.to_sym]).find(self.context, val.id)
|
55
55
|
else
|
56
|
-
Arrest::Source.mod.const_get(class_name).find(val)
|
56
|
+
Arrest::Source.mod.const_get(class_name).find(self.context, val)
|
57
57
|
end
|
58
58
|
rescue Errors::DocumentNotFoundError => e
|
59
59
|
raise Errors::DocumentNotFoundError, "Couldnt find a #{class_name} with id #{val}"
|
@@ -9,11 +9,11 @@ module Arrest
|
|
9
9
|
super name, read_only, clazz
|
10
10
|
end
|
11
11
|
|
12
|
-
def from_hash value
|
12
|
+
def from_hash(parent, value)
|
13
13
|
return nil unless value != nil
|
14
14
|
raise "Expected an array but got #{value.class.name}" unless value.is_a?(Array)
|
15
15
|
value.map do |v|
|
16
|
-
@clazz.new v
|
16
|
+
@clazz.new(parent, v)
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
@@ -10,10 +10,12 @@ module Arrest
|
|
10
10
|
else
|
11
11
|
@stubbed = false
|
12
12
|
end
|
13
|
+
raise "hash expected but got #{hash.class}" unless hash.is_a?(Hash)
|
13
14
|
init_from_hash(hash, from_json)
|
14
15
|
end
|
15
16
|
|
16
17
|
def initialize(hash = {}, from_json = false, &blk)
|
18
|
+
raise "hash expected but got #{hash.class}" unless hash.is_a?(Hash)
|
17
19
|
if block_given?
|
18
20
|
@stubbed = true
|
19
21
|
@load_blk = blk
|
@@ -27,6 +29,7 @@ module Arrest
|
|
27
29
|
end
|
28
30
|
|
29
31
|
def init_from_hash(as_i={}, from_json = false)
|
32
|
+
raise "hash expected but got #{as_i.class}" unless as_i.is_a?(Hash)
|
30
33
|
@attribute_values = {} unless @attribute_values != nil
|
31
34
|
as = {}
|
32
35
|
as_i.each_pair do |k,v|
|
@@ -39,7 +42,7 @@ module Arrest
|
|
39
42
|
key = field.name
|
40
43
|
end
|
41
44
|
value = as[key]
|
42
|
-
converted = field.from_hash(value)
|
45
|
+
converted = field.from_hash(self, value)
|
43
46
|
self.send(field.name.to_s + '=', converted) unless converted == nil
|
44
47
|
end
|
45
48
|
end
|
@@ -51,7 +54,7 @@ module Arrest
|
|
51
54
|
matching_fields = fields.find_all{|f| f.name.to_s == k.to_s}
|
52
55
|
field = matching_fields.first
|
53
56
|
if field
|
54
|
-
converted = field.from_hash(v)
|
57
|
+
converted = field.from_hash(self, v)
|
55
58
|
self.send("#{k}=", converted)
|
56
59
|
end
|
57
60
|
end
|
@@ -4,9 +4,9 @@ module Arrest
|
|
4
4
|
super name, read_only, clazz
|
5
5
|
end
|
6
6
|
|
7
|
-
def from_hash value
|
7
|
+
def from_hash(parent, value)
|
8
8
|
return nil unless value != nil
|
9
|
-
@clazz.new value
|
9
|
+
@clazz.new(parent, value)
|
10
10
|
end
|
11
11
|
|
12
12
|
def to_hash val
|
@@ -14,4 +14,4 @@ module Arrest
|
|
14
14
|
val.to_hash
|
15
15
|
end
|
16
16
|
end
|
17
|
-
end
|
17
|
+
end
|
@@ -12,7 +12,7 @@ module Arrest
|
|
12
12
|
|
13
13
|
def build attributes = {}
|
14
14
|
extended_attrs = attributes.merge({@foreign_key_name => @parent.id})
|
15
|
-
resolved_class.new extended_attrs
|
15
|
+
resolved_class.new(@parent.context, extended_attrs)
|
16
16
|
end
|
17
17
|
|
18
18
|
def method_missing(*args, &block)
|
@@ -28,7 +28,7 @@ module Arrest
|
|
28
28
|
def children
|
29
29
|
if @children == nil
|
30
30
|
url = @parent.resource_location + '/' + @url_part.to_s
|
31
|
-
@children = resolved_class.by_url(url)
|
31
|
+
@children = resolved_class.by_url(@parent.context, url)
|
32
32
|
end
|
33
33
|
@children
|
34
34
|
end
|
data/lib/arrest/http_source.rb
CHANGED
@@ -13,16 +13,18 @@ module Arrest
|
|
13
13
|
@base
|
14
14
|
end
|
15
15
|
|
16
|
-
def add_headers(headers)
|
17
|
-
|
16
|
+
def add_headers(context,headers)
|
17
|
+
decorator = context.header_decorator if context
|
18
|
+
decorator ||= Arrest::Source.header_decorator
|
19
|
+
decorator.headers.each_pair do |k,v|
|
18
20
|
headers[k.to_s] = v.to_s
|
19
21
|
end
|
20
22
|
end
|
21
23
|
|
22
|
-
def get_one(sub, filter={})
|
24
|
+
def get_one(context, sub, filter={})
|
23
25
|
response = self.connection().get do |req|
|
24
26
|
req.url(sub, filter)
|
25
|
-
add_headers(req.headers)
|
27
|
+
add_headers(context, req.headers)
|
26
28
|
end
|
27
29
|
rql = RequestLog.new(:get, "#{sub}#{hash_to_query filter}", nil)
|
28
30
|
rsl = ResponseLog.new(response.env[:status], response.body)
|
@@ -33,14 +35,14 @@ module Arrest
|
|
33
35
|
response.body
|
34
36
|
end
|
35
37
|
|
36
|
-
def get_many_other_ids(path)
|
37
|
-
get_one(path)
|
38
|
+
def get_many_other_ids(context, path)
|
39
|
+
get_one(context, path)
|
38
40
|
end
|
39
41
|
|
40
|
-
def get_many(sub, filter={})
|
42
|
+
def get_many(context, sub, filter={})
|
41
43
|
response = self.connection().get do |req|
|
42
44
|
req.url(sub, filter)
|
43
|
-
add_headers(req.headers)
|
45
|
+
add_headers(context, req.headers)
|
44
46
|
end
|
45
47
|
rql = RequestLog.new(:get, "#{sub}#{hash_to_query filter}", nil)
|
46
48
|
rsl = ResponseLog.new(response.env[:status], response.body)
|
@@ -49,10 +51,10 @@ module Arrest
|
|
49
51
|
end
|
50
52
|
|
51
53
|
|
52
|
-
def delete_all(resource_path)
|
54
|
+
def delete_all(context, resource_path)
|
53
55
|
response = self.connection().delete do |req|
|
54
56
|
req.url(resource_path)
|
55
|
-
add_headers(req.headers)
|
57
|
+
add_headers(context, req.headers)
|
56
58
|
end
|
57
59
|
rql = RequestLog.new(:delete, "#{resource_path}", nil)
|
58
60
|
rsl = ResponseLog.new(response.env[:status], response.body)
|
@@ -61,11 +63,11 @@ module Arrest
|
|
61
63
|
response.env[:status] == 200
|
62
64
|
end
|
63
65
|
|
64
|
-
def delete(rest_resource)
|
66
|
+
def delete(context, rest_resource)
|
65
67
|
raise "To delete an object it must have an id" unless rest_resource.respond_to?(:id) && rest_resource.id != nil
|
66
68
|
response = self.connection().delete do |req|
|
67
69
|
req.url(rest_resource.resource_location)
|
68
|
-
add_headers(req.headers)
|
70
|
+
add_headers(context, req.headers)
|
69
71
|
end
|
70
72
|
rql = RequestLog.new(:delete, rest_resource.resource_location, nil)
|
71
73
|
rsl = ResponseLog.new(response.env[:status], response.body)
|
@@ -80,7 +82,7 @@ module Arrest
|
|
80
82
|
internal_put(rest_resource, location, body)
|
81
83
|
end
|
82
84
|
|
83
|
-
def put(rest_resource)
|
85
|
+
def put(context, rest_resource)
|
84
86
|
raise "To change an object it must have an id" unless rest_resource.respond_to?(:id) && rest_resource.id != nil
|
85
87
|
hash = rest_resource.to_jhash
|
86
88
|
hash.delete(:id)
|
@@ -90,10 +92,13 @@ module Arrest
|
|
90
92
|
internal_put(rest_resource, rest_resource.resource_location, body)
|
91
93
|
end
|
92
94
|
|
95
|
+
|
96
|
+
|
97
|
+
|
93
98
|
def internal_put(rest_resource, location, body)
|
94
99
|
response = self.connection().put do |req|
|
95
100
|
req.url(location)
|
96
|
-
add_headers(req.headers)
|
101
|
+
add_headers(rest_resource.context, req.headers)
|
97
102
|
req.body = body
|
98
103
|
end
|
99
104
|
rql = RequestLog.new(:put, location, body)
|
@@ -105,7 +110,7 @@ module Arrest
|
|
105
110
|
response.env[:status] == 200
|
106
111
|
end
|
107
112
|
|
108
|
-
def post(rest_resource)
|
113
|
+
def post(context, rest_resource)
|
109
114
|
raise "new object must have setter for id" unless rest_resource.respond_to?(:id=)
|
110
115
|
raise "new object must not have id" if rest_resource.respond_to?(:id) && rest_resource.id != nil
|
111
116
|
hash = rest_resource.to_jhash
|
@@ -117,7 +122,7 @@ module Arrest
|
|
117
122
|
body = hash.to_json
|
118
123
|
response = self.connection().post do |req|
|
119
124
|
req.url rest_resource.resource_path
|
120
|
-
add_headers req.headers
|
125
|
+
add_headers(context, req.headers)
|
121
126
|
req.body = body
|
122
127
|
end
|
123
128
|
rql = RequestLog.new(:post, rest_resource.resource_path, body)
|
data/lib/arrest/mem_source.rb
CHANGED
@@ -97,7 +97,7 @@ module Arrest
|
|
97
97
|
[]
|
98
98
|
end
|
99
99
|
|
100
|
-
def get_many_other_ids(path)
|
100
|
+
def get_many_other_ids(context,path)
|
101
101
|
matcher = /^.+\/([^\/]+)\/([^\/]+)_ids$/.match(path)
|
102
102
|
return [] unless matcher
|
103
103
|
object_id = matcher[1]
|
@@ -114,7 +114,7 @@ module Arrest
|
|
114
114
|
wrap id_list, id_list.length
|
115
115
|
end
|
116
116
|
|
117
|
-
def get_many(sub, filters = {})
|
117
|
+
def get_many(context,sub, filters = {})
|
118
118
|
Arrest::debug sub + (hash_to_query filters)
|
119
119
|
# filters are ignored by mem impl so far
|
120
120
|
|
@@ -130,7 +130,7 @@ module Arrest
|
|
130
130
|
wrap collection_json(objects), id_list.length
|
131
131
|
end
|
132
132
|
|
133
|
-
def get_one sub, filters = {}
|
133
|
+
def get_one(context, sub, filters = {})
|
134
134
|
Arrest::debug sub + (hash_to_query filters)
|
135
135
|
# filters are ignored by mem impl so far
|
136
136
|
idx = sub.rindex '/'
|
@@ -144,7 +144,7 @@ module Arrest
|
|
144
144
|
wrap val.to_jhash.to_json, 1
|
145
145
|
end
|
146
146
|
|
147
|
-
def delete_all resource_path
|
147
|
+
def delete_all(context, resource_path)
|
148
148
|
id_list = Array.new(@@collections[resource_path] || [])
|
149
149
|
id_list.each do |base_id|
|
150
150
|
@@collections.each_pair do |k,v|
|
@@ -175,7 +175,7 @@ module Arrest
|
|
175
175
|
end
|
176
176
|
|
177
177
|
|
178
|
-
def delete(rest_resource)
|
178
|
+
def delete(context, rest_resource)
|
179
179
|
raise "To change an object it must have an id" unless rest_resource.respond_to?(:id) && rest_resource.id != nil
|
180
180
|
@@all_objects.delete(rest_resource.id)
|
181
181
|
@@collections.each_pair do |k,v|
|
@@ -281,7 +281,7 @@ module Arrest
|
|
281
281
|
true
|
282
282
|
end
|
283
283
|
|
284
|
-
def put(rest_resource)
|
284
|
+
def put(context, rest_resource)
|
285
285
|
raise "To change an object it must have an id" unless rest_resource.respond_to?(:id) && rest_resource.id != nil
|
286
286
|
old = @@all_objects[rest_resource.id]
|
287
287
|
|
@@ -298,7 +298,7 @@ module Arrest
|
|
298
298
|
|
299
299
|
|
300
300
|
|
301
|
-
def post(rest_resource)
|
301
|
+
def post(context, rest_resource)
|
302
302
|
|
303
303
|
Arrest::debug "post -> #{rest_resource.class.name} #{rest_resource.to_hash} #{rest_resource.class.all_fields.map(&:name)}"
|
304
304
|
raise "new object must have setter for id" unless rest_resource.respond_to?(:id=)
|
data/lib/arrest/rest_child.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module Arrest
|
2
2
|
class RestChild < AbstractResource
|
3
3
|
attr_accessor :parent
|
4
|
-
def initialize parent, h
|
5
|
-
super
|
4
|
+
def initialize context, parent, h
|
5
|
+
super(context,h)
|
6
6
|
@parent = parent
|
7
7
|
end
|
8
8
|
|
@@ -17,14 +17,14 @@ module Arrest
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def build parent, hash
|
20
|
-
self.new parent, hash
|
20
|
+
self.new(parent.context, parent, hash)
|
21
21
|
end
|
22
22
|
|
23
23
|
|
24
|
-
def all_for
|
24
|
+
def all_for(parent)
|
25
25
|
raise "Parent has no id yet" unless parent.id
|
26
26
|
begin
|
27
|
-
body_root(source().get_many self.resource_path_for(parent)).map do |h|
|
27
|
+
body_root(source().get_many(parent.context, self.resource_path_for(parent))).map do |h|
|
28
28
|
self.build(parent, h)
|
29
29
|
end
|
30
30
|
rescue Arrest::Errors::DocumentNotFoundError
|
@@ -32,14 +32,14 @@ module Arrest
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
def find id
|
35
|
+
def find(context, id)
|
36
36
|
raise "find cannot be executed for child resources - use find_for with a parent"
|
37
37
|
end
|
38
38
|
|
39
|
-
def find_for parent,id
|
40
|
-
r = source().get_one "#{self.resource_path_for(parent)}/#{id}"
|
39
|
+
def find_for(context, parent,id)
|
40
|
+
r = source().get_one(context, "#{self.resource_path_for(parent)}/#{id}")
|
41
41
|
body = body_root(r)
|
42
|
-
self.build
|
42
|
+
self.build(body)
|
43
43
|
end
|
44
44
|
|
45
45
|
def filter name, &aproc
|
@@ -54,7 +54,7 @@ module Arrest
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
-
def scope
|
57
|
+
def scope(name, &block)
|
58
58
|
super name
|
59
59
|
if block_given?
|
60
60
|
send :define_singleton_method, name do |parent|
|
@@ -63,7 +63,7 @@ module Arrest
|
|
63
63
|
else
|
64
64
|
send :define_singleton_method, name do |parent|
|
65
65
|
raise "Parent has no id yet" unless parent.id
|
66
|
-
body_root(source().get_many self.scoped_path_for(parent, name)).map do |h|
|
66
|
+
body_root(source().get_many(parent.context, self.scoped_path_for(parent, name))).map do |h|
|
67
67
|
self.build(parent, h)
|
68
68
|
end
|
69
69
|
end
|