fast_jsonapi 1.3 → 1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +23 -5
- data/lib/fast_jsonapi/object_serializer.rb +26 -8
- data/lib/fast_jsonapi/relationship.rb +17 -9
- data/lib/fast_jsonapi/serialization_core.rb +20 -7
- data/lib/fast_jsonapi/version.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: 759626d247d6cc39f75b0080a9c09493e9fcc93b
|
4
|
+
data.tar.gz: 57dc5e3a5fd9014d3a7f276f3c9d353bb9f328f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 390b6f6df1591307f33afd1996d563ead9f04294a6e9670a82263388c9ae408b94d5321bce265c2ed3336f714999496525fd2a3866e8d710c27791bbfd42193b
|
7
|
+
data.tar.gz: 69e7198dea45b109c630555328ea8847af80a2ea4938fc743f862f4f8eb1e8513af090ee537c55ac79b202c1724483ea5b9574567f81fe0ef6d83efb55fb8c7d
|
data/README.md
CHANGED
@@ -221,7 +221,7 @@ end
|
|
221
221
|
```
|
222
222
|
|
223
223
|
### Links Per Object
|
224
|
-
Links are defined in FastJsonapi using the `link` method. By default, link are read directly from the model property of the same name.In this example, `public_url` is expected to be a property of the object being serialized.
|
224
|
+
Links are defined in FastJsonapi using the `link` method. By default, link are read directly from the model property of the same name. In this example, `public_url` is expected to be a property of the object being serialized.
|
225
225
|
|
226
226
|
You can configure the method to use on the object for example a link with key `self` will get set to the value returned by a method called `url` on the movie object.
|
227
227
|
|
@@ -245,6 +245,23 @@ class MovieSerializer
|
|
245
245
|
end
|
246
246
|
```
|
247
247
|
|
248
|
+
### Meta Per Resource
|
249
|
+
|
250
|
+
For every resource in the collection, you can include a meta object containing non-standard meta-information about a resource that can not be represented as an attribute or relationship.
|
251
|
+
|
252
|
+
|
253
|
+
```ruby
|
254
|
+
class MovieSerializer
|
255
|
+
include FastJsonapi::ObjectSerializer
|
256
|
+
|
257
|
+
meta do |movie|
|
258
|
+
{
|
259
|
+
years_since_release: Date.current.year - movie.year
|
260
|
+
}
|
261
|
+
end
|
262
|
+
end
|
263
|
+
```
|
264
|
+
|
248
265
|
### Compound Document
|
249
266
|
|
250
267
|
Support for top-level and nested included associations through ` options[:include] `.
|
@@ -351,15 +368,15 @@ class MovieSerializer
|
|
351
368
|
include FastJsonapi::ObjectSerializer
|
352
369
|
|
353
370
|
attributes :name, :year
|
354
|
-
attribute :release_year, if: Proc.new
|
371
|
+
attribute :release_year, if: Proc.new { |record|
|
355
372
|
# Release year will only be serialized if it's greater than 1990
|
356
373
|
record.release_year > 1990
|
357
|
-
|
374
|
+
}
|
358
375
|
|
359
|
-
attribute :director, if: Proc.new
|
376
|
+
attribute :director, if: Proc.new { |record, params|
|
360
377
|
# The director will be serialized only if the :admin key of params is true
|
361
378
|
params && params[:admin] == true
|
362
|
-
|
379
|
+
}
|
363
380
|
end
|
364
381
|
|
365
382
|
# ...
|
@@ -409,6 +426,7 @@ serializer.serializable_hash
|
|
409
426
|
Option | Purpose | Example
|
410
427
|
------------ | ------------- | -------------
|
411
428
|
set_type | Type name of Object | ```set_type :movie ```
|
429
|
+
key | Key of Object | ```belongs_to :owner, key: :user ```
|
412
430
|
set_id | ID of Object | ```set_id :owner_id ```
|
413
431
|
cache_options | Hash to enable caching and set cache length | ```cache_options enabled: true, cache_length: 12.hours, race_condition_ttl: 10.seconds```
|
414
432
|
id_method_name | Set custom method name to get ID of an object | ```has_many :locations, id_method_name: :place_ids ```
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'active_support/
|
3
|
+
require 'active_support/json'
|
4
4
|
require 'active_support/concern'
|
5
5
|
require 'active_support/inflector'
|
6
6
|
require 'fast_jsonapi/attribute'
|
@@ -65,7 +65,7 @@ module FastJsonapi
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def serialized_json
|
68
|
-
|
68
|
+
ActiveSupport::JSON.encode(serializable_hash)
|
69
69
|
end
|
70
70
|
|
71
71
|
private
|
@@ -120,6 +120,7 @@ module FastJsonapi
|
|
120
120
|
subclass.data_links = data_links
|
121
121
|
subclass.cached = cached
|
122
122
|
subclass.set_type(subclass.reflected_record_type) if subclass.reflected_record_type
|
123
|
+
subclass.meta_to_serialize = meta_to_serialize
|
123
124
|
end
|
124
125
|
|
125
126
|
def reflected_record_type
|
@@ -194,7 +195,7 @@ module FastJsonapi
|
|
194
195
|
self.relationships_to_serialize = {} if relationships_to_serialize.nil?
|
195
196
|
self.cachable_relationships_to_serialize = {} if cachable_relationships_to_serialize.nil?
|
196
197
|
self.uncachable_relationships_to_serialize = {} if uncachable_relationships_to_serialize.nil?
|
197
|
-
|
198
|
+
|
198
199
|
if !relationship.cached
|
199
200
|
self.uncachable_relationships_to_serialize[relationship.name] = relationship
|
200
201
|
else
|
@@ -218,6 +219,10 @@ module FastJsonapi
|
|
218
219
|
add_relationship(relationship)
|
219
220
|
end
|
220
221
|
|
222
|
+
def meta(&block)
|
223
|
+
self.meta_to_serialize = block
|
224
|
+
end
|
225
|
+
|
221
226
|
def create_relationship(base_key, relationship_type, options, block)
|
222
227
|
name = base_key.to_sym
|
223
228
|
if relationship_type == :has_many
|
@@ -232,7 +237,11 @@ module FastJsonapi
|
|
232
237
|
Relationship.new(
|
233
238
|
key: options[:key] || run_key_transform(base_key),
|
234
239
|
name: name,
|
235
|
-
id_method_name:
|
240
|
+
id_method_name: compute_id_method_name(
|
241
|
+
options[:id_method_name],
|
242
|
+
"#{base_serialization_key}#{id_postfix}".to_sym,
|
243
|
+
block
|
244
|
+
),
|
236
245
|
record_type: options[:record_type] || run_key_transform(base_key_sym),
|
237
246
|
object_method_name: options[:object_method_name] || name,
|
238
247
|
object_block: block,
|
@@ -240,10 +249,19 @@ module FastJsonapi
|
|
240
249
|
relationship_type: relationship_type,
|
241
250
|
cached: options[:cached],
|
242
251
|
polymorphic: fetch_polymorphic_option(options),
|
243
|
-
conditional_proc: options[:if]
|
252
|
+
conditional_proc: options[:if],
|
253
|
+
transform_method: @transform_method
|
244
254
|
)
|
245
255
|
end
|
246
256
|
|
257
|
+
def compute_id_method_name(custom_id_method_name, id_method_name_from_relationship, block)
|
258
|
+
if block.present?
|
259
|
+
custom_id_method_name || :id
|
260
|
+
else
|
261
|
+
custom_id_method_name || id_method_name_from_relationship
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
247
265
|
def compute_serializer_name(serializer_key)
|
248
266
|
return serializer_key unless serializer_key.is_a? Symbol
|
249
267
|
namespace = self.name.gsub(/()?\w+Serializer$/, '')
|
@@ -275,10 +293,10 @@ module FastJsonapi
|
|
275
293
|
includes.detect do |include_item|
|
276
294
|
klass = self
|
277
295
|
parse_include_item(include_item).each do |parsed_include|
|
278
|
-
|
296
|
+
relationships_to_serialize = klass.relationships_to_serialize || {}
|
297
|
+
relationship_to_include = relationships_to_serialize[parsed_include]
|
279
298
|
raise ArgumentError, "#{parsed_include} is not specified as a relationship on #{klass.name}" unless relationship_to_include
|
280
|
-
|
281
|
-
klass = relationship_to_include.serializer.to_s.constantize
|
299
|
+
klass = relationship_to_include.serializer.to_s.constantize unless relationship_to_include.polymorphic.is_a?(Hash)
|
282
300
|
end
|
283
301
|
end
|
284
302
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module FastJsonapi
|
2
2
|
class Relationship
|
3
|
-
attr_reader :key, :name, :id_method_name, :record_type, :object_method_name, :object_block, :serializer, :relationship_type, :cached, :polymorphic, :conditional_proc
|
3
|
+
attr_reader :key, :name, :id_method_name, :record_type, :object_method_name, :object_block, :serializer, :relationship_type, :cached, :polymorphic, :conditional_proc, :transform_method
|
4
4
|
|
5
5
|
def initialize(
|
6
6
|
key:,
|
@@ -13,7 +13,8 @@ module FastJsonapi
|
|
13
13
|
relationship_type:,
|
14
14
|
cached: false,
|
15
15
|
polymorphic:,
|
16
|
-
conditional_proc
|
16
|
+
conditional_proc:,
|
17
|
+
transform_method:
|
17
18
|
)
|
18
19
|
@key = key
|
19
20
|
@name = name
|
@@ -26,6 +27,7 @@ module FastJsonapi
|
|
26
27
|
@cached = cached
|
27
28
|
@polymorphic = polymorphic
|
28
29
|
@conditional_proc = conditional_proc
|
30
|
+
@transform_method = transform_method
|
29
31
|
end
|
30
32
|
|
31
33
|
def serialize(record, serialization_params, output_hash)
|
@@ -68,7 +70,7 @@ module FastJsonapi
|
|
68
70
|
|
69
71
|
def id_hash_from_record(record, record_types)
|
70
72
|
# memoize the record type within the record_types dictionary, then assigning to record_type:
|
71
|
-
associated_record_type = record_types[record.class] ||= record.class.name.underscore
|
73
|
+
associated_record_type = record_types[record.class] ||= run_key_transform(record.class.name.demodulize.underscore)
|
72
74
|
id_hash(record.id, associated_record_type)
|
73
75
|
end
|
74
76
|
|
@@ -86,14 +88,20 @@ module FastJsonapi
|
|
86
88
|
end
|
87
89
|
|
88
90
|
def fetch_id(record, params)
|
89
|
-
|
91
|
+
if object_block.present?
|
90
92
|
object = object_block.call(record, params)
|
91
|
-
|
92
|
-
return object.
|
93
|
-
return object.try(:id)
|
93
|
+
return object.map { |item| item.public_send(id_method_name) } if object.respond_to? :map
|
94
|
+
return object.try(id_method_name)
|
94
95
|
end
|
95
|
-
|
96
96
|
record.public_send(id_method_name)
|
97
97
|
end
|
98
|
+
|
99
|
+
def run_key_transform(input)
|
100
|
+
if self.transform_method.present?
|
101
|
+
input.to_s.send(*self.transform_method).to_sym
|
102
|
+
else
|
103
|
+
input.to_sym
|
104
|
+
end
|
105
|
+
end
|
98
106
|
end
|
99
|
-
end
|
107
|
+
end
|
@@ -21,7 +21,8 @@ module FastJsonapi
|
|
21
21
|
:cache_length,
|
22
22
|
:race_condition_ttl,
|
23
23
|
:cached,
|
24
|
-
:data_links
|
24
|
+
:data_links,
|
25
|
+
:meta_to_serialize
|
25
26
|
end
|
26
27
|
end
|
27
28
|
|
@@ -57,6 +58,10 @@ module FastJsonapi
|
|
57
58
|
end
|
58
59
|
end
|
59
60
|
|
61
|
+
def meta_hash(record, params = {})
|
62
|
+
meta_to_serialize.call(record, params)
|
63
|
+
end
|
64
|
+
|
60
65
|
def record_hash(record, fieldset, params = {})
|
61
66
|
if cached
|
62
67
|
record_hash = Rails.cache.fetch(record.cache_key, expires_in: cache_length, race_condition_ttl: race_condition_ttl) do
|
@@ -67,13 +72,15 @@ module FastJsonapi
|
|
67
72
|
temp_hash[:links] = links_hash(record, params) if data_links.present?
|
68
73
|
temp_hash
|
69
74
|
end
|
70
|
-
record_hash[:relationships] = record_hash[:relationships].merge(relationships_hash(record, uncachable_relationships_to_serialize, params)) if uncachable_relationships_to_serialize.present?
|
75
|
+
record_hash[:relationships] = record_hash[:relationships].merge(relationships_hash(record, uncachable_relationships_to_serialize, fieldset, params)) if uncachable_relationships_to_serialize.present?
|
76
|
+
record_hash[:meta] = meta_hash(record, params) if meta_to_serialize.present?
|
71
77
|
record_hash
|
72
78
|
else
|
73
79
|
record_hash = id_hash(id_from_record(record), record_type, true)
|
74
80
|
record_hash[:attributes] = attributes_hash(record, fieldset, params) if attributes_to_serialize.present?
|
75
81
|
record_hash[:relationships] = relationships_hash(record, nil, fieldset, params) if relationships_to_serialize.present?
|
76
82
|
record_hash[:links] = links_hash(record, params) if data_links.present?
|
83
|
+
record_hash[:meta] = meta_hash(record, params) if meta_to_serialize.present?
|
77
84
|
record_hash
|
78
85
|
end
|
79
86
|
end
|
@@ -112,9 +119,10 @@ module FastJsonapi
|
|
112
119
|
next unless relationships_to_serialize && relationships_to_serialize[item]
|
113
120
|
relationship_item = relationships_to_serialize[item]
|
114
121
|
next unless relationship_item.include_relationship?(record, params)
|
115
|
-
|
116
|
-
|
117
|
-
|
122
|
+
unless relationship_item.polymorphic.is_a?(Hash)
|
123
|
+
record_type = relationship_item.record_type
|
124
|
+
serializer = relationship_item.serializer.to_s.constantize
|
125
|
+
end
|
118
126
|
relationship_type = relationship_item.relationship_type
|
119
127
|
|
120
128
|
included_objects = relationship_item.fetch_associated_object(record, params)
|
@@ -122,12 +130,17 @@ module FastJsonapi
|
|
122
130
|
included_objects = [included_objects] unless relationship_type == :has_many
|
123
131
|
|
124
132
|
included_objects.each do |inc_obj|
|
133
|
+
if relationship_item.polymorphic.is_a?(Hash)
|
134
|
+
record_type = inc_obj.class.name.demodulize.underscore
|
135
|
+
serializer = self.compute_serializer_name(inc_obj.class.name.demodulize.to_sym).to_s.constantize
|
136
|
+
end
|
137
|
+
|
125
138
|
if remaining_items(items)
|
126
|
-
serializer_records = serializer.get_included_records(inc_obj, remaining_items(items), known_included_objects, fieldsets)
|
139
|
+
serializer_records = serializer.get_included_records(inc_obj, remaining_items(items), known_included_objects, fieldsets, params)
|
127
140
|
included_records.concat(serializer_records) unless serializer_records.empty?
|
128
141
|
end
|
129
142
|
|
130
|
-
code = "#{record_type}_#{inc_obj
|
143
|
+
code = "#{record_type}_#{serializer.id_from_record(inc_obj)}"
|
131
144
|
next if known_included_objects.key?(code)
|
132
145
|
|
133
146
|
known_included_objects[code] = inc_obj
|
data/lib/fast_jsonapi/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fast_jsonapi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '1.
|
4
|
+
version: '1.4'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shishir Kakaraddi
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2018-
|
13
|
+
date: 2018-09-20 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|