jsonapi_mapper 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 47223d6620e9fc3fff6740ffc29ab2667b18e2b8
4
- data.tar.gz: a8453219e94d3fb0f412f4c64256ce8e563fb399
3
+ metadata.gz: 9883b69c0cc95639ba89dd3437199363426fb85a
4
+ data.tar.gz: a76c19f1d15ad85f037f30d3bac31f669b2774f5
5
5
  SHA512:
6
- metadata.gz: 54fe745ec69e3012480a44b5a05eb67b764727a3c19be1beb45632962dcb4cf2e1ed4329dbc13e130e6d582bdd1d69775ca029600c9ea06cc23f7e2043ce69ae
7
- data.tar.gz: 3b11530b50b1159e272e7b4d6957acef70c539a3a37390bccfb5ea5f80b2ef6217adc6e39300b02da68fbed33ab4639112458e15867a56acbf5e0730a43ade72
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
@@ -1,3 +1,3 @@
1
1
  module JsonapiMapper
2
- VERSION = "0.1.3"
2
+ VERSION = "0.1.4"
3
3
  end
@@ -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| renamed(type_name, a) }.to_set
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 = renames.fetch(:types, {})[type_name] ||
75
- type_name.to_s.singularize.camelize.constantize
74
+ cls = renamed_type(type_name)
76
75
 
77
- attrs.map{|a| renamed(type_name, a) }.each do |attr|
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[renamed(type.name, name)] = if value[:data].is_a?(Array)
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 attributes_to_be_set = json[:attributes]
112
+ if new_values = json[:attributes]
114
113
  type.rule.attributes.each do |name|
115
- if value = attributes_to_be_set[name]
116
- object.send("#{renamed(type.name, name)}=", value)
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 renamed(type, attr)
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.3
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: 2017-11-30 00:00:00.000000000 Z
11
+ date: 2018-01-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport