jsonapi_mapper 0.1.3 → 0.1.4
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 +48 -0
- data/lib/jsonapi_mapper/version.rb +1 -1
- data/lib/jsonapi_mapper.rb +66 -10
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9883b69c0cc95639ba89dd3437199363426fb85a
|
4
|
+
data.tar.gz: a76c19f1d15ad85f037f30d3bac31f669b2774f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 304d9fb7484f3a7c405afe014cfc159bc0a3c25f94983e00de6bd9264ed2aa25b724891e46707fd01931393696dcad64162226bfe693ea0194d310b67e1bf280
|
7
|
+
data.tar.gz: 7556af75805a07a6fc8acefdf303b0355d2bd1ed830169baf37695876bb1aa30be7a70c5e824d7a5f5cc624620f613a247286dfda73b29aefb3e88dcb5cb8cce
|
data/README.md
CHANGED
@@ -146,6 +146,54 @@ See the specs directory for more examples.
|
|
146
146
|
pets: {nickname: :name},
|
147
147
|
}
|
148
148
|
}).save_all
|
149
|
+
|
150
|
+
|
151
|
+
# If any resource in your document has errors, you can get a collection
|
152
|
+
# with pointers to the specific fields and the type and id of the resource
|
153
|
+
# that has the error.
|
154
|
+
document = {
|
155
|
+
data: [
|
156
|
+
{ type: 'pets', attributes: { age: 3 } },
|
157
|
+
{ type: 'pets', attributes: { age: 6 } },
|
158
|
+
],
|
159
|
+
included: [
|
160
|
+
{ type: 'pets', id: '@1', attributes: { age: 4 } }
|
161
|
+
]
|
162
|
+
}
|
163
|
+
mapper = JsonapiMapper.doc(document,
|
164
|
+
{ pets: [:nickname, country: 'uruguay'] },
|
165
|
+
{ types: { pets: PetDog }, attributes: { pets: {nickname: :name} } }
|
166
|
+
)
|
167
|
+
|
168
|
+
# all_valid? triggers all validations and sets up errors.
|
169
|
+
mapper.all_valid?.should be_falsey
|
170
|
+
|
171
|
+
# Then all errors are presented like so, honoring remapped names too.
|
172
|
+
mapper.all_errors.should == {
|
173
|
+
errors: [
|
174
|
+
{ status: 422,
|
175
|
+
title: "can't be blank",
|
176
|
+
detail: "can't be blank",
|
177
|
+
code: "can_t_be_blank",
|
178
|
+
meta: {type: "pets"},
|
179
|
+
source: {pointer: "/data/0/attributes/nickname"}
|
180
|
+
},
|
181
|
+
{ status: 422,
|
182
|
+
title: "can't be blank",
|
183
|
+
detail: "can't be blank",
|
184
|
+
code: "can_t_be_blank",
|
185
|
+
meta: {type: "pets"},
|
186
|
+
source: {pointer: "/data/1/attributes/nickname"}
|
187
|
+
},
|
188
|
+
{ status: 422,
|
189
|
+
title: "can't be blank",
|
190
|
+
detail: "can't be blank",
|
191
|
+
code: "can_t_be_blank",
|
192
|
+
meta: {type: "pets"},
|
193
|
+
source: {pointer: "/included/0/attributes/nickname"}
|
194
|
+
}
|
195
|
+
]
|
196
|
+
}
|
149
197
|
```
|
150
198
|
|
151
199
|
## Development
|
data/lib/jsonapi_mapper.rb
CHANGED
@@ -66,15 +66,14 @@ module JsonapiMapper
|
|
66
66
|
attrs = attrs.map(&:to_sym)
|
67
67
|
scope.symbolize_keys!
|
68
68
|
|
69
|
-
danger = scope.keys.to_set & attrs.map{|a|
|
69
|
+
danger = scope.keys.to_set & attrs.map{|a| renamed_attr(type_name, a) }.to_set
|
70
70
|
if danger.count > 0
|
71
71
|
raise RulesError.new("Don't let user set the scope: #{danger.to_a}")
|
72
72
|
end
|
73
73
|
|
74
|
-
cls =
|
75
|
-
type_name.to_s.singularize.camelize.constantize
|
74
|
+
cls = renamed_type(type_name)
|
76
75
|
|
77
|
-
attrs.map{|a|
|
76
|
+
attrs.map{|a| renamed_attr(type_name, a) }.each do |attr|
|
78
77
|
unless cls.new.respond_to?(attr)
|
79
78
|
raise NoMethodError.new("undefined method #{attr} for #{cls}")
|
80
79
|
end
|
@@ -103,18 +102,17 @@ module JsonapiMapper
|
|
103
102
|
relationships = {}
|
104
103
|
json.fetch(:relationships, {}).each do |name, value|
|
105
104
|
next unless type.rule.attributes.include?(name)
|
106
|
-
relationships[
|
105
|
+
relationships[renamed_attr(type.name, name)] = if value[:data].is_a?(Array)
|
107
106
|
value[:data].map{|v| build_id(v) }
|
108
107
|
else
|
109
108
|
build_id(value[:data])
|
110
109
|
end
|
111
110
|
end
|
112
111
|
|
113
|
-
if
|
112
|
+
if new_values = json[:attributes]
|
114
113
|
type.rule.attributes.each do |name|
|
115
|
-
|
116
|
-
|
117
|
-
end
|
114
|
+
next unless new_values.has_key?(name)
|
115
|
+
object.send("#{renamed_attr(type.name, name)}=", new_values[name])
|
118
116
|
end
|
119
117
|
end
|
120
118
|
|
@@ -149,10 +147,25 @@ module JsonapiMapper
|
|
149
147
|
.new("Couldn't find #{id.type} with id=#{id.raw}")
|
150
148
|
end
|
151
149
|
|
152
|
-
def
|
150
|
+
def renamed_type(type_name)
|
151
|
+
renames.fetch(:types, {})[type_name] ||
|
152
|
+
type_name.to_s.singularize.camelize.constantize
|
153
|
+
end
|
154
|
+
|
155
|
+
def unrenamed_type(type)
|
156
|
+
type_name = type.to_s.underscore.pluralize
|
157
|
+
renames.fetch(:types, {}).find{|k,v| v == type }.try(:first) || type_name
|
158
|
+
end
|
159
|
+
|
160
|
+
def renamed_attr(type, attr)
|
153
161
|
renames.fetch(:attributes, {}).fetch(type, {}).fetch(attr, attr)
|
154
162
|
end
|
155
163
|
|
164
|
+
def unrenamed_attr(type_name, attr)
|
165
|
+
renames.fetch(:attributes, {}).fetch(type_name, {})
|
166
|
+
.find{|k,v| v == attr }.try(:first) || attr
|
167
|
+
end
|
168
|
+
|
156
169
|
def all
|
157
170
|
(data_mappable + included)
|
158
171
|
end
|
@@ -163,6 +176,10 @@ module JsonapiMapper
|
|
163
176
|
true
|
164
177
|
end
|
165
178
|
|
179
|
+
def all_valid?
|
180
|
+
all.map(&:valid?).all? # This does not short-circuit, to get all errors.
|
181
|
+
end
|
182
|
+
|
166
183
|
def collection?
|
167
184
|
data.is_a?(Array)
|
168
185
|
end
|
@@ -182,5 +199,44 @@ module JsonapiMapper
|
|
182
199
|
def data_mappable
|
183
200
|
collection? ? data : [data].compact
|
184
201
|
end
|
202
|
+
|
203
|
+
def all_errors
|
204
|
+
errors = []
|
205
|
+
|
206
|
+
if collection?
|
207
|
+
data.each_with_index do |resource, i|
|
208
|
+
errors << serialize_errors_for("/data/#{i}", resource)
|
209
|
+
end
|
210
|
+
else
|
211
|
+
errors << serialize_errors_for("/data", data)
|
212
|
+
end
|
213
|
+
|
214
|
+
included.each_with_index do |resource, i|
|
215
|
+
errors << serialize_errors_for("/included/#{i}", resource)
|
216
|
+
end
|
217
|
+
|
218
|
+
{ errors: errors.flatten.compact }
|
219
|
+
end
|
220
|
+
|
221
|
+
private
|
222
|
+
|
223
|
+
def serialize_errors_for(prefix, model)
|
224
|
+
return if model.errors.empty?
|
225
|
+
model.errors.collect do |attr, value|
|
226
|
+
type_name = unrenamed_type(model.class)
|
227
|
+
meta = { type: type_name.to_s }
|
228
|
+
meta[:id] = model.id if model.id
|
229
|
+
{
|
230
|
+
status: 422,
|
231
|
+
title: value,
|
232
|
+
detail: value,
|
233
|
+
code: value.parameterize.underscore,
|
234
|
+
meta: meta,
|
235
|
+
source: {
|
236
|
+
pointer: "#{prefix}/attributes/#{unrenamed_attr(type_name, attr)}"
|
237
|
+
}
|
238
|
+
}
|
239
|
+
end
|
240
|
+
end
|
185
241
|
end
|
186
242
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jsonapi_mapper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- nubis
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-01-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|