jsonapi-resources 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +4 -5
- data/lib/jsonapi-resources.rb +2 -1
- data/lib/jsonapi/association.rb +19 -8
- data/lib/jsonapi/formatter.rb +2 -0
- data/lib/jsonapi/request.rb +9 -9
- data/lib/jsonapi/resource.rb +52 -28
- data/lib/jsonapi/resource_controller.rb +10 -2
- data/lib/jsonapi/resource_for.rb +2 -0
- data/lib/jsonapi/resource_serializer.rb +11 -10
- data/lib/jsonapi/resources/version.rb +1 -1
- data/lib/jsonapi/routing_ext.rb +5 -0
- data/test/controllers/controller_test.rb +2 -2
- data/test/fixtures/active_record.rb +6 -5
- data/test/helpers/hash_helpers.rb +3 -1
- data/test/integration/routes/routes_test.rb +6 -0
- data/test/unit/serializer/serializer_test.rb +1 -1
- 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: 3e063aecb3183d3a1862dc4fd88f0f06ddc921dd
|
4
|
+
data.tar.gz: 40b0476410fe269a08f16791f8b927d2aee02156
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f4135619c0ad660679b93ea9dcde314991134824e0d01540705b4a3055e0acccfab76d74b0e49cf94d969d949063a51c50328165265b90b2057065ec34b13eb3
|
7
|
+
data.tar.gz: 335f3f2b30251c07b2286dbdcd176d3f199fd844d99f6c9619a0b54e598b66e0fe07b1386cddb1c18106b3e1d968e6a6a1f5eaabb11e3cc72d75d08bf54581ae
|
data/README.md
CHANGED
@@ -145,13 +145,13 @@ end
|
|
145
145
|
|
146
146
|
The system will lookup a value formatter named `DateWithTimezoneValueFormatter` and will use this when serializing and updating the attribute. See the [Value Formatters](#value-formatters) section for more details.
|
147
147
|
|
148
|
-
#### Key
|
148
|
+
#### Primary Key
|
149
149
|
|
150
|
-
|
150
|
+
Resources are always represented using a key of `id`. If the underlying model does not use `id` as the primary key you can use the `primary_key` method to tell the resource which field on the model to use as the primary key. Note: this doesn't have to be the actual primary key of the model. For example you may wish to use integers internally and a different scheme publicly.
|
151
151
|
|
152
152
|
```ruby
|
153
153
|
class CurrencyResource < JSONAPI::Resource
|
154
|
-
|
154
|
+
primary_key :code
|
155
155
|
attributes :code, :name
|
156
156
|
|
157
157
|
has_many :expense_entries
|
@@ -199,8 +199,7 @@ end
|
|
199
199
|
|
200
200
|
The association methods support the following options:
|
201
201
|
* `class_name` - a string specifying the underlying class for the related resource
|
202
|
-
* `
|
203
|
-
* `key` - the key in the resource that identifies the related resource, if different than `<resource_name>_id`
|
202
|
+
* `foreign_key` - the method on the resource used to fetch the related resource. Defaults to `<resource_name>_id` for has_one and `<resource_name>_ids` for has_many relationships.
|
204
203
|
* `acts_as_set` - allows the entire set of related records to be replaced in one operation. Defaults to false if not set.
|
205
204
|
|
206
205
|
Examples:
|
data/lib/jsonapi-resources.rb
CHANGED
data/lib/jsonapi/association.rb
CHANGED
@@ -1,13 +1,24 @@
|
|
1
1
|
module JSONAPI
|
2
2
|
class Association
|
3
|
-
attr_reader :
|
3
|
+
attr_reader :acts_as_set, :foreign_key, :type, :options, :name, :class_name
|
4
4
|
|
5
5
|
def initialize(name, options={})
|
6
|
-
@name
|
7
|
-
@options
|
8
|
-
@
|
9
|
-
@
|
10
|
-
|
6
|
+
@name = name.to_s
|
7
|
+
@options = options
|
8
|
+
@acts_as_set = options.fetch(:acts_as_set, false) == true
|
9
|
+
@key = options[:key] ? options[:key].to_sym : nil
|
10
|
+
|
11
|
+
if @key.nil?
|
12
|
+
@foreign_key = options[:foreign_key ] ? options[:foreign_key ].to_sym : nil
|
13
|
+
else
|
14
|
+
# :nocov:
|
15
|
+
warn '[DEPRECATION] `key` is deprecated in associations. Please use `foreign_key` instead.'
|
16
|
+
# :nocov:
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def primary_key
|
21
|
+
@primary_key ||= Resource.resource_for(@name)._primary_key
|
11
22
|
end
|
12
23
|
|
13
24
|
class HasOne < Association
|
@@ -15,7 +26,7 @@ module JSONAPI
|
|
15
26
|
super
|
16
27
|
@class_name = options.fetch(:class_name, name.to_s.capitalize)
|
17
28
|
@type = class_name.underscore.pluralize.to_sym
|
18
|
-
@
|
29
|
+
@foreign_key ||= @key.nil? ? "#{name}_id".to_sym : @key
|
19
30
|
end
|
20
31
|
end
|
21
32
|
|
@@ -24,7 +35,7 @@ module JSONAPI
|
|
24
35
|
super
|
25
36
|
@class_name = options.fetch(:class_name, name.to_s.capitalize.singularize)
|
26
37
|
@type = class_name.underscore.pluralize.to_sym
|
27
|
-
@key
|
38
|
+
@foreign_key ||= @key.nil? ? "#{name.to_s.singularize}_ids".to_sym : @key
|
28
39
|
end
|
29
40
|
end
|
30
41
|
end
|
data/lib/jsonapi/formatter.rb
CHANGED
@@ -9,6 +9,7 @@ module JSONAPI
|
|
9
9
|
arg
|
10
10
|
end
|
11
11
|
|
12
|
+
# :nocov:
|
12
13
|
if RUBY_VERSION >= '2.0'
|
13
14
|
def formatter_for(format)
|
14
15
|
formatter_class_name = "#{format.to_s.camelize}Formatter"
|
@@ -20,6 +21,7 @@ module JSONAPI
|
|
20
21
|
formatter_class_name.safe_constantize if formatter_class_name
|
21
22
|
end
|
22
23
|
end
|
24
|
+
# :nocov:
|
23
25
|
end
|
24
26
|
end
|
25
27
|
|
data/lib/jsonapi/request.rb
CHANGED
@@ -298,31 +298,31 @@ module JSONAPI
|
|
298
298
|
def parse_replace_operation(params)
|
299
299
|
object_params_raw = params.require(format_key(@resource_klass._type))
|
300
300
|
|
301
|
-
keys = params[@resource_klass.
|
301
|
+
keys = params[@resource_klass._primary_key]
|
302
302
|
if object_params_raw.is_a?(Array)
|
303
303
|
if keys.count != object_params_raw.count
|
304
304
|
raise JSONAPI::Exceptions::CountMismatch
|
305
305
|
end
|
306
306
|
|
307
307
|
object_params_raw.each do |object_params|
|
308
|
-
if object_params[@resource_klass.
|
308
|
+
if object_params[@resource_klass._primary_key].nil?
|
309
309
|
raise JSONAPI::Exceptions::MissingKey.new
|
310
310
|
end
|
311
311
|
|
312
|
-
if !keys.include?(object_params[@resource_klass.
|
313
|
-
raise JSONAPI::Exceptions::KeyNotIncludedInURL.new(object_params[@resource_klass.
|
312
|
+
if !keys.include?(object_params[@resource_klass._primary_key])
|
313
|
+
raise JSONAPI::Exceptions::KeyNotIncludedInURL.new(object_params[@resource_klass._primary_key])
|
314
314
|
end
|
315
315
|
@operations.push JSONAPI::ReplaceFieldsOperation.new(@resource_klass,
|
316
|
-
object_params[@resource_klass.
|
316
|
+
object_params[@resource_klass._primary_key],
|
317
317
|
parse_params(object_params, @resource_klass.updateable_fields(@context)))
|
318
318
|
end
|
319
319
|
else
|
320
|
-
if !object_params_raw[@resource_klass.
|
321
|
-
raise JSONAPI::Exceptions::KeyNotIncludedInURL.new(object_params_raw[@resource_klass.
|
320
|
+
if !object_params_raw[@resource_klass._primary_key].nil? && keys != object_params_raw[@resource_klass._primary_key]
|
321
|
+
raise JSONAPI::Exceptions::KeyNotIncludedInURL.new(object_params_raw[@resource_klass._primary_key])
|
322
322
|
end
|
323
323
|
|
324
324
|
@operations.push JSONAPI::ReplaceFieldsOperation.new(@resource_klass,
|
325
|
-
params[@resource_klass.
|
325
|
+
params[@resource_klass._primary_key],
|
326
326
|
parse_params(object_params_raw, @resource_klass.updateable_fields(@context)))
|
327
327
|
end
|
328
328
|
|
@@ -333,7 +333,7 @@ module JSONAPI
|
|
333
333
|
end
|
334
334
|
|
335
335
|
def parse_remove_operation(params)
|
336
|
-
keys = parse_key_array(params.permit(@resource_klass.
|
336
|
+
keys = parse_key_array(params.permit(@resource_klass._primary_key)[@resource_klass._primary_key])
|
337
337
|
|
338
338
|
keys.each do |key|
|
339
339
|
@operations.push JSONAPI::RemoveResourceOperation.new(@resource_klass, key)
|
data/lib/jsonapi/resource.rb
CHANGED
@@ -20,6 +20,10 @@ module JSONAPI
|
|
20
20
|
@model.destroy
|
21
21
|
end
|
22
22
|
|
23
|
+
def id
|
24
|
+
model.send(self.class._primary_key)
|
25
|
+
end
|
26
|
+
|
23
27
|
def create_has_many_link(association_type, association_key_value)
|
24
28
|
association = self.class._associations[association_type]
|
25
29
|
related_resource = self.class.resource_for(association.type).find_by_key(association_key_value, @context)
|
@@ -36,16 +40,16 @@ module JSONAPI
|
|
36
40
|
def replace_has_many_links(association_type, association_key_values)
|
37
41
|
association = self.class._associations[association_type]
|
38
42
|
|
39
|
-
|
43
|
+
send("#{association.foreign_key}=", association_key_values)
|
40
44
|
end
|
41
45
|
|
42
46
|
def create_has_one_link(association_type, association_key_value)
|
43
47
|
association = self.class._associations[association_type]
|
44
48
|
|
45
49
|
# ToDo: Add option to skip relations that already exist instead of returning an error?
|
46
|
-
relation = @model.send("#{association.
|
50
|
+
relation = @model.send("#{association.foreign_key}")
|
47
51
|
if relation.nil?
|
48
|
-
|
52
|
+
send("#{association.foreign_key}=", association_key_value)
|
49
53
|
else
|
50
54
|
raise JSONAPI::Exceptions::HasOneRelationExists.new
|
51
55
|
end
|
@@ -54,7 +58,7 @@ module JSONAPI
|
|
54
58
|
def replace_has_one_link(association_type, association_key_value)
|
55
59
|
association = self.class._associations[association_type]
|
56
60
|
|
57
|
-
|
61
|
+
send("#{association.foreign_key}=", association_key_value)
|
58
62
|
end
|
59
63
|
|
60
64
|
def remove_has_many_link(association_type, key)
|
@@ -66,12 +70,18 @@ module JSONAPI
|
|
66
70
|
def remove_has_one_link(association_type)
|
67
71
|
association = self.class._associations[association_type]
|
68
72
|
|
69
|
-
|
73
|
+
send("#{association.foreign_key}=", nil)
|
70
74
|
end
|
71
75
|
|
72
76
|
def replace_fields(field_data)
|
73
77
|
field_data[:attributes].each do |attribute, value|
|
74
|
-
|
78
|
+
begin
|
79
|
+
send "#{attribute}=", value
|
80
|
+
rescue ArgumentError
|
81
|
+
# :nocov: Will be thrown if an enum value isn't allowed for an enum. Currently not tested as enums are a rails 4.1 and higher feature
|
82
|
+
raise JSONAPI::Exceptions::InvalidFieldValue.new(attribute, value)
|
83
|
+
# :nocov:
|
84
|
+
end
|
75
85
|
end
|
76
86
|
|
77
87
|
field_data[:has_one].each do |association_type, value|
|
@@ -184,7 +194,14 @@ module JSONAPI
|
|
184
194
|
end
|
185
195
|
|
186
196
|
def key(key)
|
187
|
-
|
197
|
+
# :nocov:
|
198
|
+
warn '[DEPRECATION] `key` is deprecated. Please use `primary_key` instead.'
|
199
|
+
@_primary_key = key.to_sym
|
200
|
+
# :nocov:
|
201
|
+
end
|
202
|
+
|
203
|
+
def primary_key(key)
|
204
|
+
@_primary_key = key.to_sym
|
188
205
|
end
|
189
206
|
|
190
207
|
# Override in your resource to filter the updateable keys
|
@@ -212,7 +229,7 @@ module JSONAPI
|
|
212
229
|
includes.push(filter)
|
213
230
|
where_filters["#{filter}.#{_associations[filter].primary_key}"] = value
|
214
231
|
else
|
215
|
-
where_filters["#{_associations[filter].
|
232
|
+
where_filters["#{_associations[filter].foreign_key}"] = value
|
216
233
|
end
|
217
234
|
else
|
218
235
|
where_filters[filter] = value
|
@@ -228,7 +245,7 @@ module JSONAPI
|
|
228
245
|
end
|
229
246
|
|
230
247
|
def find_by_key(key, context = nil)
|
231
|
-
model = _model_class.where({
|
248
|
+
model = _model_class.where({_primary_key => key}).first
|
232
249
|
if model.nil?
|
233
250
|
raise JSONAPI::Exceptions::RecordNotFound.new(key)
|
234
251
|
end
|
@@ -305,15 +322,22 @@ module JSONAPI
|
|
305
322
|
end
|
306
323
|
|
307
324
|
def _key
|
308
|
-
|
325
|
+
# :nocov:
|
326
|
+
warn '[DEPRECATION] `_key` is deprecated. Please use `_primary_key` instead.'
|
327
|
+
_primary_key
|
328
|
+
# :nocov:
|
329
|
+
end
|
330
|
+
|
331
|
+
def _primary_key
|
332
|
+
@_primary_key ||= :id
|
309
333
|
end
|
310
334
|
|
311
335
|
def _as_parent_key
|
312
|
-
@_as_parent_key ||= "#{_type.to_s.singularize}_#{
|
336
|
+
@_as_parent_key ||= "#{_type.to_s.singularize}_#{_primary_key}"
|
313
337
|
end
|
314
338
|
|
315
339
|
def _allowed_filters
|
316
|
-
!@_allowed_filters.nil? ? @_allowed_filters : Set.new([
|
340
|
+
!@_allowed_filters.nil? ? @_allowed_filters : Set.new([_primary_key])
|
317
341
|
end
|
318
342
|
|
319
343
|
def _resource_name_from_type(type)
|
@@ -325,15 +349,17 @@ module JSONAPI
|
|
325
349
|
return class_name
|
326
350
|
end
|
327
351
|
|
352
|
+
# :nocov:
|
328
353
|
if RUBY_VERSION >= '2.0'
|
329
354
|
def _model_class
|
330
|
-
@model ||= Object.const_get(_model_name)
|
355
|
+
@model ||= Object.const_get(_model_name.to_s)
|
331
356
|
end
|
332
357
|
else
|
333
358
|
def _model_class
|
334
359
|
@model ||= _model_name.to_s.safe_constantize
|
335
360
|
end
|
336
361
|
end
|
362
|
+
# :nocov:
|
337
363
|
|
338
364
|
def _allowed_filter?(filter)
|
339
365
|
_allowed_filters.include?(filter)
|
@@ -347,29 +373,27 @@ module JSONAPI
|
|
347
373
|
attrs.each do |attr|
|
348
374
|
@_associations[attr] = klass.new(attr, options)
|
349
375
|
|
350
|
-
|
351
|
-
|
376
|
+
foreign_key = @_associations[attr].foreign_key
|
377
|
+
|
378
|
+
define_method foreign_key do
|
379
|
+
@model.method(foreign_key).call
|
380
|
+
end unless method_defined?(foreign_key)
|
352
381
|
|
353
|
-
|
354
|
-
|
355
|
-
|
382
|
+
define_method "#{foreign_key}=" do |value|
|
383
|
+
@model.method("#{foreign_key}=").call(value)
|
384
|
+
end unless method_defined?("#{foreign_key}=")
|
356
385
|
|
357
|
-
|
386
|
+
if @_associations[attr].is_a?(JSONAPI::Association::HasOne)
|
387
|
+
define_method attr do
|
358
388
|
type_name = self.class._associations[attr].type
|
359
389
|
resource_class = self.class.resource_for(type_name)
|
360
390
|
if resource_class
|
361
391
|
associated_model = @model.send attr
|
362
392
|
return resource_class.new(associated_model, @context)
|
363
393
|
end
|
364
|
-
end unless method_defined?(
|
394
|
+
end unless method_defined?(attr)
|
365
395
|
elsif @_associations[attr].is_a?(JSONAPI::Association::HasMany)
|
366
|
-
|
367
|
-
|
368
|
-
define_method key do
|
369
|
-
@model.method(key).call
|
370
|
-
end unless method_defined?(key)
|
371
|
-
|
372
|
-
define_method "_#{attr}_resources" do
|
396
|
+
define_method attr do
|
373
397
|
type_name = self.class._associations[attr].type
|
374
398
|
resource_class = self.class.resource_for(type_name)
|
375
399
|
resources = []
|
@@ -380,7 +404,7 @@ module JSONAPI
|
|
380
404
|
end
|
381
405
|
end
|
382
406
|
return resources
|
383
|
-
end unless method_defined?(
|
407
|
+
end unless method_defined?(attr)
|
384
408
|
end
|
385
409
|
end
|
386
410
|
end
|
@@ -27,7 +27,7 @@ module JSONAPI
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def show
|
30
|
-
keys = parse_key_array(params[resource_klass.
|
30
|
+
keys = parse_key_array(params[resource_klass._primary_key])
|
31
31
|
|
32
32
|
if keys.length > 1
|
33
33
|
resources = []
|
@@ -56,9 +56,11 @@ module JSONAPI
|
|
56
56
|
parent_resource = resource_klass.find_by_key(parent_key, context)
|
57
57
|
|
58
58
|
association = resource_klass._association(association_type)
|
59
|
-
render json: { association_type => parent_resource.send(association.
|
59
|
+
render json: { association_type => parent_resource.send(association.foreign_key)}
|
60
60
|
rescue => e
|
61
|
+
# :nocov:
|
61
62
|
handle_exceptions(e)
|
63
|
+
# :nocov:
|
62
64
|
end
|
63
65
|
|
64
66
|
def create
|
@@ -91,6 +93,7 @@ module JSONAPI
|
|
91
93
|
end
|
92
94
|
|
93
95
|
private
|
96
|
+
# :nocov:
|
94
97
|
if RUBY_VERSION >= '2.0'
|
95
98
|
def resource_klass
|
96
99
|
@resource_klass ||= Object.const_get resource_klass_name
|
@@ -100,6 +103,7 @@ module JSONAPI
|
|
100
103
|
@resource_klass ||= resource_klass_name.safe_constantize
|
101
104
|
end
|
102
105
|
end
|
106
|
+
# :nocov:
|
103
107
|
|
104
108
|
def resource_klass_name
|
105
109
|
@resource_klass_name ||= "#{self.class.name.demodulize.sub(/Controller$/, '').singularize}Resource"
|
@@ -112,7 +116,9 @@ module JSONAPI
|
|
112
116
|
})
|
113
117
|
render_errors(@request.errors) unless @request.errors.empty?
|
114
118
|
rescue => e
|
119
|
+
# :nocov:
|
115
120
|
handle_exceptions(e)
|
121
|
+
# :nocov:
|
116
122
|
end
|
117
123
|
|
118
124
|
def parse_key_array(raw)
|
@@ -187,7 +193,9 @@ module JSONAPI
|
|
187
193
|
when JSONAPI::Exceptions::Error
|
188
194
|
render_errors(e.errors)
|
189
195
|
else # raise all other exceptions
|
196
|
+
# :nocov:
|
190
197
|
raise e
|
198
|
+
# :nocov:
|
191
199
|
end
|
192
200
|
end
|
193
201
|
end
|
data/lib/jsonapi/resource_for.rb
CHANGED
@@ -5,6 +5,7 @@ module JSONAPI
|
|
5
5
|
end
|
6
6
|
|
7
7
|
module ClassMethods
|
8
|
+
# :nocov:
|
8
9
|
if RUBY_VERSION >= '2.0'
|
9
10
|
def resource_for(type)
|
10
11
|
resource_name = JSONAPI::Resource._resource_name_from_type(type)
|
@@ -18,6 +19,7 @@ module JSONAPI
|
|
18
19
|
resource_name.safe_constantize if resource_name
|
19
20
|
end
|
20
21
|
end
|
22
|
+
# :nocov:
|
21
23
|
end
|
22
24
|
end
|
23
25
|
end
|
@@ -91,16 +91,17 @@ module JSONAPI
|
|
91
91
|
# The fields options controls both fields and included links references.
|
92
92
|
def process_primary(source, requested_associations)
|
93
93
|
if source.respond_to?(:to_ary)
|
94
|
-
source.each do |
|
95
|
-
id =
|
94
|
+
source.each do |resource|
|
95
|
+
id = resource.id
|
96
96
|
if already_serialized?(@primary_class_name, id)
|
97
97
|
set_primary(@primary_class_name, id)
|
98
98
|
end
|
99
99
|
|
100
|
-
add_linked_object(@primary_class_name, id, object_hash(
|
100
|
+
add_linked_object(@primary_class_name, id, object_hash(resource, requested_associations), true)
|
101
101
|
end
|
102
102
|
else
|
103
|
-
|
103
|
+
resource = source
|
104
|
+
id = resource.id
|
104
105
|
# ToDo: See if this is actually needed
|
105
106
|
# if already_serialized?(@primary_class_name, id)
|
106
107
|
# set_primary(@primary_class_name, id)
|
@@ -151,10 +152,10 @@ module JSONAPI
|
|
151
152
|
included_associations = source.fetchable_fields & associations.keys
|
152
153
|
associations.each_with_object({}) do |(name, association), hash|
|
153
154
|
if included_associations.include? name
|
154
|
-
|
155
|
+
foreign_key = association.foreign_key
|
155
156
|
|
156
157
|
if field_set.include?(name)
|
157
|
-
hash[format_key(name)] = source.send(
|
158
|
+
hash[format_key(name)] = source.send(foreign_key)
|
158
159
|
end
|
159
160
|
|
160
161
|
ia = requested_associations.is_a?(Hash) ? requested_associations[name] : nil
|
@@ -169,9 +170,9 @@ module JSONAPI
|
|
169
170
|
# through the associations.
|
170
171
|
if include_linked_object || include_linked_children
|
171
172
|
if association.is_a?(JSONAPI::Association::HasOne)
|
172
|
-
resource = source.send(
|
173
|
+
resource = source.send(name)
|
173
174
|
if resource
|
174
|
-
id = resource.
|
175
|
+
id = resource.id
|
175
176
|
associations_only = already_serialized?(type, id)
|
176
177
|
if include_linked_object && !associations_only
|
177
178
|
add_linked_object(type, id, object_hash(resource, ia[:include_related]))
|
@@ -180,9 +181,9 @@ module JSONAPI
|
|
180
181
|
end
|
181
182
|
end
|
182
183
|
elsif association.is_a?(JSONAPI::Association::HasMany)
|
183
|
-
resources = source.send(
|
184
|
+
resources = source.send(name)
|
184
185
|
resources.each do |resource|
|
185
|
-
id = resource.
|
186
|
+
id = resource.id
|
186
187
|
associations_only = already_serialized?(type, id)
|
187
188
|
if include_linked_object && !associations_only
|
188
189
|
add_linked_object(type, id, object_hash(resource, ia[:include_related]))
|
data/lib/jsonapi/routing_ext.rb
CHANGED
@@ -7,6 +7,7 @@ module ActionDispatch
|
|
7
7
|
options = resources.extract_options!.dup
|
8
8
|
|
9
9
|
res = JSONAPI::Resource.resource_for(resource_type)
|
10
|
+
|
10
11
|
resource resource_type, options.merge(res.routing_resource_options) do
|
11
12
|
@scope[:jsonapi_resource] = resource_type
|
12
13
|
|
@@ -29,6 +30,10 @@ module ActionDispatch
|
|
29
30
|
options = resources.extract_options!.dup
|
30
31
|
|
31
32
|
res = JSONAPI::Resource.resource_for(resource_type)
|
33
|
+
|
34
|
+
# Route using the primary_key. Can be overridden using routing_resource_options
|
35
|
+
options.merge!(param: res._primary_key)
|
36
|
+
|
32
37
|
resources resource_type, options.merge(res.routing_resource_options) do
|
33
38
|
@scope[:jsonapi_resource] = resource_type
|
34
39
|
|
@@ -1001,7 +1001,7 @@ class ExpenseEntriesControllerTest < ActionController::TestCase
|
|
1001
1001
|
|
1002
1002
|
def test_expense_entries_show_fields_type_many
|
1003
1003
|
get :show, {id: 1, include: 'isoCurrency,employee', 'fields' => {'expenseEntries' => 'transactionDate',
|
1004
|
-
'isoCurrencies' => '
|
1004
|
+
'isoCurrencies' => 'id,name'}}
|
1005
1005
|
assert_response :success
|
1006
1006
|
assert json_response['expenseEntries'].is_a?(Hash)
|
1007
1007
|
assert json_response['expenseEntries'].has_key?('transactionDate')
|
@@ -1009,7 +1009,7 @@ class ExpenseEntriesControllerTest < ActionController::TestCase
|
|
1009
1009
|
refute json_response['expenseEntries'].has_key?('links')
|
1010
1010
|
assert_equal 1, json_response['linked']['isoCurrencies'].size
|
1011
1011
|
assert_equal 1, json_response['linked']['people'].size
|
1012
|
-
assert json_response['linked']['isoCurrencies'][0].has_key?('
|
1012
|
+
assert json_response['linked']['isoCurrencies'][0].has_key?('id')
|
1013
1013
|
assert json_response['linked']['isoCurrencies'][0].has_key?('name')
|
1014
1014
|
refute json_response['linked']['isoCurrencies'][0].has_key?('countryName')
|
1015
1015
|
end
|
@@ -398,17 +398,15 @@ class PostResource < JSONAPI::Resource
|
|
398
398
|
end
|
399
399
|
|
400
400
|
class IsoCurrencyResource < JSONAPI::Resource
|
401
|
-
|
402
|
-
attributes :
|
403
|
-
|
404
|
-
routing_options :param => :code
|
401
|
+
primary_key :code
|
402
|
+
attributes :id, :name, :country_name, :minor_unit
|
405
403
|
end
|
406
404
|
|
407
405
|
class ExpenseEntryResource < JSONAPI::Resource
|
408
406
|
attributes :id, :cost
|
409
407
|
attribute :transaction_date, format: :date
|
410
408
|
|
411
|
-
has_one :iso_currency,
|
409
|
+
has_one :iso_currency, foreign_key: 'currency_code'
|
412
410
|
has_one :employee, class_name: 'Person'
|
413
411
|
end
|
414
412
|
|
@@ -416,6 +414,9 @@ class BreedResource < JSONAPI::Resource
|
|
416
414
|
attribute :id, format_misspelled: :does_not_exist
|
417
415
|
attribute :name, format: :title
|
418
416
|
|
417
|
+
# This is unneeded, just here for testing
|
418
|
+
routing_options :param => :id
|
419
|
+
|
419
420
|
def self.find(attrs, context = nil)
|
420
421
|
breeds = []
|
421
422
|
$breed_data.breeds.values.each do |breed|
|
@@ -1,5 +1,6 @@
|
|
1
1
|
module Helpers
|
2
2
|
module HashHelpers
|
3
|
+
# :nocov:
|
3
4
|
def assert_hash_contains(exp, act, msg = nil)
|
4
5
|
msg = message(msg, '') { diff exp, act }
|
5
6
|
assert(matches_hash?(exp, act), msg)
|
@@ -9,5 +10,6 @@ module Helpers
|
|
9
10
|
msg = message(msg, '') { diff exp, act }
|
10
11
|
assert(matches_hash?(exp, act, {exact: true}), msg)
|
11
12
|
end
|
13
|
+
# :nocov:
|
12
14
|
end
|
13
|
-
end
|
15
|
+
end
|
@@ -111,6 +111,12 @@ class RoutesTest < ActionDispatch::IntegrationTest
|
|
111
111
|
{action: 'show', controller: 'api/v3/posts', id: '1'})
|
112
112
|
end
|
113
113
|
|
114
|
+
#primary_key
|
115
|
+
def test_routing_primary_key_jsonapi_resources
|
116
|
+
assert_routing({path: '/iso_currencies/USD', method: :get},
|
117
|
+
{action: 'show', controller: 'iso_currencies', code: 'USD'})
|
118
|
+
end
|
119
|
+
|
114
120
|
# ToDo: Refute routing
|
115
121
|
# def test_routing_v3_posts_delete
|
116
122
|
# assert_routing({ path: '/api/v3/posts/1', method: :delete },
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jsonapi-resources
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dan Gebhardt
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-10-
|
12
|
+
date: 2014-10-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|