Skip to content

Commit f4ad6bc

Browse files
committed
Changes for version 1.2 (#220)
params support in blocks, nested includes etc
1 parent 5543a5c commit f4ad6bc

28 files changed

+1423
-353
lines changed

README.md

Lines changed: 84 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Fast JSON API serialized 250 records in 3.01 ms
2929
* [Key Transforms](#key-transforms)
3030
* [Collection Serialization](#collection-serialization)
3131
* [Caching](#caching)
32+
* [Params](#params)
3233
* [Contributing](#contributing)
3334

3435

@@ -173,7 +174,7 @@ By default, attributes are read directly from the model property of the same nam
173174
```ruby
174175
class MovieSerializer
175176
include FastJsonapi::ObjectSerializer
176-
177+
177178
attribute :name
178179
end
179180
```
@@ -183,9 +184,9 @@ Custom attributes that must be serialized but do not exist on the model can be d
183184
```ruby
184185
class MovieSerializer
185186
include FastJsonapi::ObjectSerializer
186-
187+
187188
attributes :name, :year
188-
189+
189190
attribute :name_with_year do |object|
190191
"#{object.name} (#{object.year})"
191192
end
@@ -197,33 +198,69 @@ The block syntax can also be used to override the property on the object:
197198
```ruby
198199
class MovieSerializer
199200
include FastJsonapi::ObjectSerializer
200-
201+
201202
attribute :name do |object|
202203
"#{object.name} Part 2"
203204
end
204205
end
205206
```
206207

208+
### Links Per Object
209+
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.
210+
211+
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.
212+
213+
You can also use a block to define a url as shown in `custom_url`. You can access params in these blocks as well as shown in `personalized_url`
214+
215+
```ruby
216+
class MovieSerializer
217+
include FastJsonapi::ObjectSerializer
218+
219+
link :public_url
220+
221+
link :self, :url
222+
223+
link :custom_url do |object|
224+
"http://movies.com/#{object.name}-(#{object.year})"
225+
end
226+
227+
link :personalized_url do |object, params|
228+
"http://movies.com/#{object.name}-#{params[:user].reference_code}"
229+
end
230+
end
231+
```
232+
207233
### Compound Document
208234

209-
Support for top-level included member through ` options[:include] `.
235+
Support for top-level and nested included associations through ` options[:include] `.
210236

211237
```ruby
212238
options = {}
213239
options[:meta] = { total: 2 }
214-
options[:include] = [:actors]
240+
options[:links] = {
241+
self: '...',
242+
next: '...',
243+
prev: '...'
244+
}
245+
options[:include] = [:actors, :'actors.agency', :'actors.agency.state']
215246
MovieSerializer.new([movie, movie], options).serialized_json
216247
```
217248

218249
### Collection Serialization
219250

220251
```ruby
221252
options[:meta] = { total: 2 }
253+
options[:links] = {
254+
self: '...',
255+
next: '...',
256+
prev: '...'
257+
}
222258
hash = MovieSerializer.new([movie, movie], options).serializable_hash
223259
json_string = MovieSerializer.new([movie, movie], options).serialized_json
224260
```
225261

226262
### Caching
263+
Requires a `cache_key` method be defined on model:
227264

228265
```ruby
229266
class MovieSerializer
@@ -234,17 +271,56 @@ class MovieSerializer
234271
end
235272
```
236273

274+
### Params
275+
276+
In some cases, attribute values might require more information than what is
277+
available on the record, for example, access privileges or other information
278+
related to a current authenticated user. The `options[:params]` value covers these
279+
cases by allowing you to pass in a hash of additional parameters necessary for
280+
your use case.
281+
282+
Leveraging the new params is easy, when you define a custom attribute or relationship with a
283+
block you opt-in to using params by adding it as a block parameter.
284+
285+
```ruby
286+
class MovieSerializer
287+
class MovieSerializer
288+
include FastJsonapi::ObjectSerializer
289+
290+
attributes :name, :year
291+
attribute :can_view_early do |movie, params|
292+
# in here, params is a hash containing the `:current_user` key
293+
params[:current_user].is_employee? ? true : false
294+
end
295+
296+
belongs_to :primary_agent do |movie, params|
297+
# in here, params is a hash containing the `:current_user` key
298+
params[:current_user].is_employee? ? true : false
299+
end
300+
end
301+
302+
# ...
303+
current_user = User.find(cookies[:current_user_id])
304+
serializer = MovieSerializer.new(movie, {params: {current_user: current_user}})
305+
serializer.serializable_hash
306+
```
307+
308+
Custom attributes and relationships that only receive the resource are still possible by defining
309+
the block to only receive one argument.
310+
237311
### Customizable Options
238312

239313
Option | Purpose | Example
240314
------------ | ------------- | -------------
241315
set_type | Type name of Object | ```set_type :movie ```
242316
set_id | ID of Object | ```set_id :owner_id ```
243-
cache_options | Hash to enable caching and set cache length | ```cache_options enabled: true, cache_length: 12.hours```
317+
cache_options | Hash to enable caching and set cache length | ```cache_options enabled: true, cache_length: 12.hours, race_condition_ttl: 10.seconds```
244318
id_method_name | Set custom method name to get ID of an object | ```has_many :locations, id_method_name: :place_ids ```
245319
object_method_name | Set custom method name to get related objects | ```has_many :locations, object_method_name: :places ```
246320
record_type | Set custom Object Type for a relationship | ```belongs_to :owner, record_type: :user```
247-
serializer | Set custom Serializer for a relationship | ```has_many :actors, serializer: :custom_actor```
321+
serializer | Set custom Serializer for a relationship | ```has_many :actors, serializer: :custom_actor``` or ```has_many :actors, serializer: MyApp::Api::V1::ActorSerializer```
322+
polymorphic | Allows different record types for a polymorphic association | ```has_many :targets, polymorphic: true```
323+
polymorphic | Sets custom record types for each object class in a polymorphic association | ```has_many :targets, polymorphic: { Person => :person, Group => :group }```
248324

249325
### Instrumentation
250326

@@ -304,4 +380,3 @@ rspec spec --tag performance:true
304380
Join the Netflix Studio Engineering team and help us build gems like this!
305381

306382
* [Senior Ruby Engineer](https://jobs.netflix.com/jobs/864893)
307-
* [Senior Platform Engineer](https://jobs.netflix.com/jobs/865783)

fast_jsonapi.gemspec

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1+
lib = File.expand_path('lib', __dir__)
2+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3+
4+
require "fast_jsonapi/version"
5+
16
Gem::Specification.new do |gem|
27
gem.name = "fast_jsonapi"
3-
gem.version = "1.1.1"
8+
gem.version = FastJsonapi::VERSION
49

10+
gem.required_ruby_version = '>= 2.0.0' if gem.respond_to? :required_ruby_version=
511
gem.required_rubygems_version = Gem::Requirement.new(">= 0") if gem.respond_to? :required_rubygems_version=
612
gem.metadata = { "allowed_push_host" => "https://rubygems.org" } if gem.respond_to? :metadata=
713
gem.require_paths = ["lib"]
814
gem.authors = ["Shishir Kakaraddi", "Srinivas Raghunathan", "Adam Gross"]
9-
gem.date = "2018-02-01"
1015
gem.description = "JSON API(jsonapi.org) serializer that works with rails and can be used to serialize any kind of ruby objects"
1116
gem.email = ""
1217
gem.extra_rdoc_files = [

lib/extensions/has_one.rb

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
# frozen_string_literal: true
22

3-
begin
4-
require 'active_record'
5-
3+
if defined?(::ActiveRecord)
64
::ActiveRecord::Associations::Builder::HasOne.class_eval do
75
# Based on
86
# https://github.com/rails/rails/blob/master/activerecord/lib/active_record/associations/builder/collection_association.rb#L50
@@ -12,11 +10,11 @@ def self.define_accessors(mixin, reflection)
1210
name = reflection.name
1311
mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
1412
def #{name}_id
13+
# if an attribute is already defined with this methods name we should just use it
14+
return read_attribute(__method__) if has_attribute?(__method__)
1515
association(:#{name}).reader.try(:id)
1616
end
1717
CODE
1818
end
1919
end
20-
rescue LoadError
21-
# active_record can't be loaded so we shouldn't try to monkey-patch it.
2220
end
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
require 'skylight'
2+
3+
SKYLIGHT_NORMALIZER_BASE_CLASS = begin
4+
::Skylight::Core::Normalizers::Normalizer
5+
rescue NameError
6+
::Skylight::Normalizers::Normalizer
7+
end

lib/fast_jsonapi/instrumentation/skylight/normalizers/serializable_hash.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
require 'skylight'
1+
require 'fast_jsonapi/instrumentation/skylight/normalizers/base'
22
require 'fast_jsonapi/instrumentation/serializable_hash'
33

44
module FastJsonapi
55
module Instrumentation
66
module Skylight
77
module Normalizers
8-
class SerializableHash < Skylight::Normalizers::Normalizer
8+
class SerializableHash < SKYLIGHT_NORMALIZER_BASE_CLASS
99

1010
register FastJsonapi::ObjectSerializer::SERIALIZABLE_HASH_NOTIFICATION
1111

lib/fast_jsonapi/instrumentation/skylight/normalizers/serialized_json.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
require 'skylight'
1+
require 'fast_jsonapi/instrumentation/skylight/normalizers/base'
22
require 'fast_jsonapi/instrumentation/serializable_hash'
33

44
module FastJsonapi
55
module Instrumentation
66
module Skylight
77
module Normalizers
8-
class SerializedJson < Skylight::Normalizers::Normalizer
8+
class SerializedJson < SKYLIGHT_NORMALIZER_BASE_CLASS
99

1010
register FastJsonapi::ObjectSerializer::SERIALIZED_JSON_NOTIFICATION
1111

lib/fast_jsonapi/multi_to_json.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# frozen_string_literal: true
22

3+
require 'logger'
4+
35
# Usage:
46
# class Movie
57
# def to_json(payload)

0 commit comments

Comments
 (0)