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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ad201aff3dee102a9760daee3777a225d73bcfcb
4
- data.tar.gz: a6e4f0f7840f27c95f3530b68542eae6422d8975
3
+ metadata.gz: 759626d247d6cc39f75b0080a9c09493e9fcc93b
4
+ data.tar.gz: 57dc5e3a5fd9014d3a7f276f3c9d353bb9f328f4
5
5
  SHA512:
6
- metadata.gz: c9503ec4e6d642f72b2a5ccb34f4b33bc68e6fda067e1a16e43d6f30f0f5b95f7e86626d608ab38fbe277ff778dae908e71252e354a1834121b013219cd77e0c
7
- data.tar.gz: 069b1ac282d7b2a3f559f398c4090f188c72f8120f4bfeff01f7126a57fbc789725ef3f2e6cf1c88c541a99681914c4f32bb5855655b9f65a7c55262c02f449e
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 do |record|
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
- end
374
+ }
358
375
 
359
- attribute :director, if: Proc.new do |record, params|
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
- end
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/core_ext/object'
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
- self.class.to_json(serializable_hash)
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: options[:id_method_name] || "#{base_serialization_key}#{id_postfix}".to_sym,
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
- relationship_to_include = klass.relationships_to_serialize[parsed_include]
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
- raise NotImplementedError if relationship_to_include.polymorphic.is_a?(Hash)
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.to_sym
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
- unless object_block.nil?
91
+ if object_block.present?
90
92
  object = object_block.call(record, params)
91
-
92
- return object.map(&:id) if object.respond_to? :map
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
- raise NotImplementedError if relationship_item.polymorphic.is_a?(Hash)
116
- record_type = relationship_item.record_type
117
- serializer = relationship_item.serializer.to_s.constantize
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.id}"
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
@@ -1,3 +1,3 @@
1
1
  module FastJsonapi
2
- VERSION = "1.3"
2
+ VERSION = "1.4"
3
3
  end
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.3'
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-07-17 00:00:00.000000000 Z
13
+ date: 2018-09-20 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport