arrest 0.0.21 → 0.0.23
Sign up to get free protection for your applications and to get access to all the features.
- 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
|