-
Notifications
You must be signed in to change notification settings - Fork 143
/
Copy pathmanager.rb
142 lines (125 loc) · 4.8 KB
/
manager.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
module Api
class BaseController
module Manager
def update_collection(type, id)
if @req.method == :put || @req.method == :patch
return send("#{@req.method}_resource", type, id)
end
action = @req.action
target = target_resource_method(type, action)
raise BadRequestError,
"Unimplemented Action #{action} for #{type} resources" unless respond_to?(target)
if id
get_and_update_one_collection(@req.subcollection?, target, type, id)
else
get_and_update_multiple_collections(@req.subcollection?, target, type)
end
end
def parent_resource_obj
type = @req.collection.to_sym
resource_search(@req.collection_id, type, collection_class(type))
end
def collection_class(type)
@collection_klasses[type.to_sym] || collection_config.klass(type)
end
def put_resource(type, id)
edit_resource(type, id, @req.json_body)
end
#
# Patching a resource, post syntax
#
# [
# {
# "action" : "add" | "edit" | "remove"
# "path" : "attribute_name",
# "value" : "value to add or edit"
# }
# ...
# ]
#
def patch_resource(type, id)
patched_attrs = {}
@req.json_body.each do |patch_cmd|
action = patch_cmd["action"]
path = patch_cmd["path"]
value = patch_cmd["value"]
if action.nil?
api_log_info("Must specify an attribute action for each path command for the resource #{type}/#{id}")
elsif path.nil?
api_log_info("Must specify an attribute path for each patch method action for the resource #{type}/#{id}")
elsif path.split('/').size > 1
api_log_info("Can only patch attributes of the resource #{type}/#{id}")
else
attr = path.split('/')[0]
patched_attrs[attr] = value if %w(edit add).include?(action)
patched_attrs[attr] = nil if action == "remove"
end
end
edit_resource(type, id, patched_attrs)
end
def delete_subcollection_resource(type, id)
parent_resource = parent_resource_obj
typed_target = "delete_resource_#{type}"
raise BadRequestError,
"Cannot delete subcollection resources of type #{type}" unless respond_to?(typed_target)
resource = @req.json_body["resource"]
resource = {"href" => "#{@req.base}#{@req.path}"} if !resource || resource.empty?
send(typed_target, parent_resource, type, id.to_i, resource)
end
private
def target_resource_method(type, action)
if @req.subcollection?
"#{type}_#{action}_resource"
else
target = "#{action}_resource"
return target if respond_to?(target)
collection_config.custom_actions?(type) ? "custom_action_resource" : "undefined_api_method"
end
end
def get_and_update_one_collection(is_subcollection, target, type, id)
resource = json_body_resource
update_one_collection(is_subcollection, target, type, id, resource)
end
def get_and_update_multiple_collections(is_subcollection, target, type)
resources = []
if @req.json_body.key?("resources")
resources += @req.json_body["resources"]
else
resources << json_body_resource
end
update_multiple_collections(is_subcollection, target, type, resources)
end
def json_body_resource
@req.json_body["resource"] || @req.json_body.except("action")
end
def update_one_collection(is_subcollection, target, type, id, resource)
id = id.to_i if id =~ /\A\d+\z/
parent_resource = parent_resource_obj if is_subcollection
if is_subcollection
send(target, parent_resource, type, id, resource)
else
send(target, type, id, resource)
end
end
def update_multiple_collections(is_subcollection, target, type, resources)
action = @req.action
processed = 0
results = resources.each.collect do |r|
next if r.blank?
rid = parse_id(r, type)
create_or_add_action = %w(create add).include?(action)
if rid && create_or_add_action
raise BadRequestError, "Resource id or href should not be specified for creating a new #{type}"
elsif !rid && !create_or_add_action
rid = parse_by_attr(r, type)
end
r.except!(*ID_ATTRS) if rid
processed += 1
update_one_collection(is_subcollection, target, type, rid, r)
end.flatten
raise BadRequestError, "No #{type} resources were specified for the #{action} action" if processed == 0
{"results" => results}
end
end
end
end