netflix / fast_jsonapi Goto Github PK
View Code? Open in Web Editor NEWNo Longer Maintained - A lightning fast JSON:API serializer for Ruby Objects.
License: Apache License 2.0
No Longer Maintained - A lightning fast JSON:API serializer for Ruby Objects.
License: Apache License 2.0
Would be awesome if it was possible to choose what keys will be used to generate json. So that depending on context, using the same serializer, we could render light-version of the model. This is what we used a lot in AMS. If this makes sense, I can provide a PR.
Given the following model:
class Foo
attr_accessor :id, :name
def initialize(opts = {})
@id = opts[:id]
@name = opts[:name]
end
end
and the following serializer:
module Api
module V1
class FooSerializer
include FastJsonapi::ObjectSerializer
set_type :foo
cache_options enabled: true, cache_length: 12.hours
attributes :id, :name
end
end
end
an error is raised when called with:
module Api
module V1
class FoosController < ApiController
def show
foo = Foo.new(id: 1 , name: 'foo')
render json: FooSerializer.new(foo).serialized_json, status: :ok
end
end
end
#=> undefined method `cache_key' for #<Foo:0x00007f94d880b500>
we need to add documentation that this is required for caching or we need to not require it, and I would prefer the later. If cache_key is not defined we should assume a cache_key
of the object name and id (in this case "foo:#{object.id}"
).
This issue is an extraction of the conversations in #49 and #67.
Right now, it is difficult to differentiate between what functionality belongs on the class and what belongs on the instance. Currently they both kinda act as singletons. It poses potential problems, currently and most notably when trying to implement AMS-style custom attribute methods, e.g.:
class MovieSerializer
include FastJsonapi::ObjectSerializer
attributes :name, :year, :name_with_year
def name_with_year
"#{object.name} (#{object.year})"
end
end
In what context is name_with_year
executed? What is its scope? How is the object
property available within this method? And how do we avoid the performance pitfalls of AMS, that instantiates new serializers for every object being serialized?
I believe an ideal solution would be the following:
The serializer class is responsible for containing the definition of the serializer: attributes, relationships, key transformation, etc. Basically, anything built into the serializer DSL would be stored at the class.
The serializer instance is responsible for serializing a single object at one time. Its job is to take an object as an input and output the object's serialized representation. This way, additional methods defined on the serializer (custom attributes, custom relationships, etc.) will naturally have an object
within the context of the serialization process.
The serializer class will have methods to serialize one object or a collection of objects. The class will then create the necessary instance(s). In most cases, developers will be calling class methods to perform the serialization, and they will not be instantiating serializers themselves.
We can achieve performance levels comparable to today by reusing the serializer instances within the serialization process, as opposed to generating new instances for every object. Prior to each iteration, we simply set the new object
and clear any instance variables that custom methods may have set. From the developer's point of view, it will feel like the serializer is new each time, but without the performance cost.
Examples:
class MovieSerializer
include FastJsonapi::ObjectSerializer
attributes :name, :year, :name_with_year
def name_with_year
"#{object.name} (#{object.year})"
end
end
MovieSerializer.to_hash(movie, options)
MovieSerializer.to_hash([ movie1, movie2 ], options)
MovieSerializer.to_json(movie, options)
MovieSerializer.to_json([ movie1, movie2 ], options)
Making some decisions along these lines will help set us up for success as we continue to build support for the entire JSON:API 1.0 spec.
I was wondering how can I use fast_jsonapi with jbuilder. I Probably need new adapter in multijson,
problem is that multijson is fast_jsonapi dependency. It's somehow possible?
The benchmarks use underlying models that are fundamentally different. The models used by fast_jsonapi
in the benchmarks are plain Ruby classes, whereas the models used in the ams
parts of the benchmarks inherit from ActiveModelSerializers::Model
.
This difference skews the benchmarks significantly in favor of fast_jsonapi
, after updating the models for the fast_jsonapi
parts of the benchmark to also inherit from ActiveModelSerializers::Model
several of the benchmark specs fail:
Failures:
1) FastJsonapi::ObjectSerializer when comparing with AMS 0.10.x and with includes and meta should serialize 25 records atleast 25 times faster than AMS
Failure/Error: expect { our_serializer.serialized_json }.to perform_faster_than { ams_serializer.to_json }.at_least(speed_factor).times
expected given block to perform faster than comparison block by at_least 25 times, but performed faster by 14.87 times
# ./spec/lib/object_serializer_performance_spec.rb:105:in `block (4 levels) in <top (required)>'
2) FastJsonapi::ObjectSerializer when comparing with AMS 0.10.x and with includes and meta should serialize 250 records atleast 25 times faster than AMS
Failure/Error: expect { our_serializer.serialized_json }.to perform_faster_than { ams_serializer.to_json }.at_least(speed_factor).times
expected given block to perform faster than comparison block by at_least 25 times, but performed faster by 14.78 times
# ./spec/lib/object_serializer_performance_spec.rb:105:in `block (4 levels) in <top (required)>'
3) FastJsonapi::ObjectSerializer when comparing with AMS 0.10.x and with includes and meta should serialize 1000 records atleast 25 times faster than AMS
Failure/Error: expect { our_serializer.serialized_json }.to perform_faster_than { ams_serializer.to_json }.at_least(speed_factor).times
expected given block to perform faster than comparison block by at_least 25 times, but performed by the same time
# ./spec/lib/object_serializer_performance_spec.rb:105:in `block (4 levels) in <top (required)>'
AMS benchmarks:
class AMSActor < ActiveModelSerializers::Model
attr_accessor :id, :name, :email
end
fast_jsonapi benchmarks:
class Actor
attr_accessor :id, :name, :email
end
We're looking at json serializers specifically for serializing a PORO.
One of the core requirements for serialization is that the snake_cased attribute keys be transformed into CamelCased ones to support the json standards being followed by our organization and also some others like Google, w3resource, schema.org, etc.
Will such a request be considered for this gem? It can be a special configuration item. If yes, I am open to putting a tech design of sorts
hi,can support rails 3.2?
I get the following error on bundle update
Bundler could not find compatible versions for gem "activesupport":
In snapshot (Gemfile.lock):
activesupport (= 4.2.3)
In Gemfile:
fast_jsonapi was resolved to 1.0.17, which depends on
activesupport (~> 5.0)
rails (= 4.2.3) was resolved to 4.2.3, which depends on
activesupport (= 4.2.3)
It would be great to allow to include nested of nested associations... example:
class Post < ApplicationRecord
has_many :post_tags, dependent: :destroy
has_many :tags, through: :post_tags
belongs_to :author, touch: true
end
class Author < ApplicationRecord
has_many :posts, dependent: :nullify
has_one :profile, dependent: :destroy
end
class Profile < ApplicationRecord
belongs_to :author, touch: true
end
In Post serializer, to include author's profile something like:
PostSerializer.new @post, {include: [:author, :'author.profile', :tags]}
could be very useful.
Will it be possible to add custom attributes to serializers that will delegate to a function within the serializer class. E.g.:
attributes :fullname
def fullname
"#{object.firstname} #{object.lastname}"
end
Are you guys willing to accept a pull request implementing such a feature?
Hey, a brief example :
class User < ApplicationRecord
has_many :reports, as: :reportable, inverse_of: :reportable
end
class Report < ApplicationRecord
belongs_to :reportable, polymorphic: true
end
class Group < ApplicationRecord
has_many :reports, as: :reportable, inverse_of: :reportable
end
serializer :
class ReportSerializer
include FastJsonapi::ObjectSerializer
has_one :reportable
end
output : (the type of data not relative to reportable_type
)
:relationships=> {
:reportable=> {
:data=> {
:id=>"bd729369-6ece-454c-8269-437d1e2ed474",
:type=>:reportable
}
}
}
type is reportable
, not user
or group
and Fast_JSONAPI fetch a ReportableSerializer
not UserSerializer
ou GroupSerializer
Implementation of polymorphic association is a great feature 👍
According to the JSON API specifications there must be an id
field. But I do not want to expose the id
column of my DB and I have a friendly_id
column (which is unique as well).
How do I instruct fast_jsonapi to use my friendly_id
column instead ?
I wonder how can I use it to return an error message with HTTP error?
Jsonapi-rb was written by @beauby, who also used to work on AMS (i did too). It's also way faster than AMS.
I saw the medium blog post, and i think more details about the benchmark woulld be good, too.
For example, in my own benchmarks, with 200 records with 2 included relationships each,. I found that jsonapi-rb is 5 to 6 times faster than AMS. I can share the benchmarrk files with you if it'd help.
I have some doubts about the speed increase mentioned in the medium article, which is why i bring this up.
I could do my own benchmarks, but i'm in the car right now. :)
Thanks for supporting/making-more-known the jsonapi spec. :D
I just did my own benchmarks, and I'm suuuuper open to others checking my work.
But this is what I got (using default settings):
GET /api/users/:id?include=posts
Comparison:
fast_jsonapi eager: 547.9 i/s
jsonapi-rb eager: 521.4 i/s - 1.05x (± 0.01) slower
ams eager: 219.0 i/s - 2.50x (± 0.02) slower
with 95.0% confidence
Comparison:
fast_jsonapi eager: 96234 allocated
jsonapi-rb eager: 109874 allocated - 1.14x more
ams eager: 249662 allocated - 2.59x more
that memory allocation is pretty good though. :-D
Here is the repo where I made the benchmark:
https://github.com/NullVoxPopuli/ruby-jsonapi-benchmarks
Something that needs to be benchmarked is nested includes performance...
AMS and jsonapi-rb both support nested includes. (and this is where jsonapi-rb beats the pants of AMS). :-)
For example:
1 User, 20 Posts, 20 Comments per Post - including 'posts.comments'
Comparison:
jsonapi-rb eager: 22.6 i/s
ams eager: 4.6 i/s - 4.91x (± 0.04) slower
with 95.0% confidence
Comparison:
jsonapi-rb eager: 3979876 allocated
ams eager: 12287098 allocated - 3.09x more
It's possible to serialize object/hash with dynamic keys?
Hey,
Thanks for this gem !
I haven't see this yet in documentation but do you plan to add the src
when you create an object e.g. :
HTTP/1.1 201 Created
Location: http://example.com/photos/550e8400-e29b-41d4-a716-446655440000
Content-Type: application/vnd.api+json
{
"data": {
"type": "photos",
"id": "550e8400-e29b-41d4-a716-446655440000",
"attributes": {
"title": "Ember Hamster",
"src": "http://example.com/images/productivity.png"
},
"links": {
"self": "http://example.com/photos/550e8400-e29b-41d4-a716-446655440000"
}
}
}
Same for links e.g.:
"links": {
"self": "http://example.com/articles/1"
}
I'm all for having it available to those who need it, but it adds a lot of noise otherwise for those that don't.
Looking at the code, there's no real difference for an association being belongs_to
and has_one
. Instead, is a source for problems (two places with the same code are two places you can forget to place a fix.. have you noticed the default serializer is obtained differently?). Both do the same thing, and both cause the same consequences in the serialization core.
Also, the jsonapi doesn't care about the direction of a 1-to-1 association.
How about:
belongs_to
method in object_serializer.rb
belongs_to
as an alias of has_one
, so it is backwards-compatible.Hi!
Dunno if this is more of a concern of http://jsonapi.org/, but:
it is unclear whether the items contained in :relationships
can/should have richer keys than just id
and type
.
"relationships":{"foos":{"data":[{"id":"2","type":"foo"}]},"bars":{"data":[{"id":"8","type":"bar"}]}}
When one sees this generated json, may wonder "can I have more fields there?"
I am aware that there's included
, but ideally one would avoid generating bloated representations. Particularly for a performance-sensitive lib :)
Cheers - Victor
An error is perform when includes an associations has_one
class Cluster::LocationSerializer
include FastJsonapi::ObjectSerializer
attributes :begin_at, :end_at
has_one :workspace, serializer: Cluster::WorkspaceSerializer
has_one :user, serializer: Cluster::UserSerializer
end
class Cluster::UserSerializer
include FastJsonapi::ObjectSerializer
attributes :uid, :login, :nickname, :avatar_url
end
class Cluster::WorkspaceSerializer
include FastJsonapi::ObjectSerializer
attributes :identifier, :campus_id
end
call:
active_locations = Location.active.includes(:workspace, :user).references(:workspace, :user)
Cluster::LocationSerializer.new(active_locations, include: [:workspace, :user]).serializable_hash
Error :
NameError - uninitialized constant Cluster::Cluster
Part of the JSON API is to support links but it doesn't appear like there's any way to achieve this right now.
Sample output of this:
{
"links": {
"self": "http://example.com/articles",
"next": "http://example.com/articles?page[offset]=2",
"last": "http://example.com/articles?page[offset]=10"
},
"data": [{
"type": "articles",
"id": "1",
"attributes": {
"title": "JSON API paints my bikeshed!"
}
}]
}
When working with AMS, I find it very useful to be able to deserialize my incoming Json API requests. After looking through the library, it looks like this is not an option. Am I missing something, or is there a reason that deserialization is left out?
This library looks great! I'm using this on my next project, will just need AMS in tandem to deserialize for now. Thanks!
Mistakenly made issue
Hi there,
First thanks for your this awesome gem. :)
Is it somehow possible to customize the json structure from #serialized_json
in order to have a different structure?
{
"data": {
...
"relationships": {
...
}
}
}
So for example I want to get rid of 'data' and would like to rename relationships to a customname and so on.
I noticed 2 issues with how benchmarks are set up.
build_ams_movies
builds owner, movie_type and actor objects while build_movies
only sets up ids and builds objects just in time when serializing the movies array (and not building owner object at all). It looks like AMS serialization will use more memory and trigger more GC (be slower) because of the way it is set up. Both test setups should initialize same amout of objects/object typesserializable_hash
of both gems or using OJ with both gems should be fairer comparison.could these 2 issue cause some problems with "fairness" of the benchmark?
Hello everyone!
I recently started using fast_jsonapi in my rails API and I have to say that the performance improvement is amazing!
I just have a suggestion to make. At the moment, in order to serialise "has_many" relationships, the gem is looking for relationship_model_name_ids and queries on that. With active record serializers, it would be enough to have a method to fetch the relationship data, named after the rails convention.
e.g.
Actor has_many :movies could have a method movies and the relationship data would be serialised.
I mention this because I have some models that are Elasticsearch models and I was not storing the relationship ids, instead I had a method to fetch the relationship data ( I was caching the data as well ) and after I switched to fast_jsonapi the relationship was empty! :)
For now, I store the ids in the mode, but I think It's an easy addition for the gem, if it makes sense to you as well.
It's not clear that the following won't work as might be expected:
class UserSerializer
include FastJsonapi::ObjectSerializer
attribute :first_name
attribute :last_name
end
class FullUserSerializer < UserSerializer
attribute :birthday
attribute :email
end
Workaround:
class UserSerializer
include FastJsonapi::ObjectSerializer
def self.inherited(subclass)
subclass.attributes_to_serialize ||= {}
subclass.attributes_to_serialize.merge!(attributes_to_serialize)
end
attribute :first_name
attribute :last_name
end
Hello!
Prompt, I can not understand, whether there is a possibility to select necessary attributes for the specified association?
class MovieSerializer
include FastJsonapi::ObjectSerializer
set_type :movie
attributes :name
belongs_to :owner, attributes: [:name]
end
{
"data": {
"id": "232",
"type": "movie",
"attributes": {
"name": "test movie"
},
"relationships": {
"owner": {
"data": {
"id": "3",
"type": "user",
"name": "Owner name example"
}
}
}
}
}
Is it possible to do this?
example:
"fast_jsonapi"
{
:data => {
:id => "1",
:type => :users,
:attributes => {
:first_name => "Diana",
:last_name => "Prince",
:birthday => -0982-02-05 03:36:03 UTC,
:created_at => 2018-02-14 02:51:25 UTC,
:updated_at => 2018-02-14 02:51:25 UTC
},
:relationships => {
:posts => {
:data => [
[0] {
:id => "1",
:type => :post
},
[1] {
:id => "2",
:type => :post
}
]
}
}
},
:included => [
[0] {
:id => "1",
:type => :posts,
:attributes => {
:title => "Some Post",
:body => "awesome content",
:created_at => 2018-02-14 02:51:25 UTC,
:updated_at => 2018-02-14 02:51:25 UTC
},
:relationships => {
:user => {
:data => {
:id => "1",
:type => :user
}
},
:comments => {
:data => [
[0] {
:id => "1",
:type => :comment
},
[1] {
:id => "2",
:type => :comment
}
]
}
}
},
[1] {
:id => "2",
:type => :posts,
:attributes => {
:title => "Some Post",
:body => "awesome content",
:created_at => 2018-02-14 02:51:25 UTC,
:updated_at => 2018-02-14 02:51:25 UTC
},
:relationships => {
:user => {
:data => {
:id => "1",
:type => :user
}
},
:comments => {
:data => [
[0] {
:id => "3",
:type => :comment
},
[1] {
:id => "4",
:type => :comment
}
]
}
}
}
]
}
I'm working on a reproduction repo. will post results soon.
After documenting #64, I felt a little odd about the polymorphic
option I added to the has_many
| belongs_to
| has_one
methods:
class ProjectSerializer
include FastJsonapi::ObjectSerializer
belongs_to :owner, polymorphic: { User => :user, Administrator => :administrator }
end
I think the polymorphic
option describes an ORM feature (specially when working with relational databases) rather than an object serialization aspect.
Actually, I think the jsonapi spec doesn't even care if an association is polymorphic or not, as long as the associated object has the type
key in it, it's all good. I think this should be reflected in the serializer DSL.
So, how about replacing the polymorphic
option with being able to use the record_type
option with either a symbol (as it is right now) or the Hash
object polymorphic
receives now?
class ProjectSerializer
include FastJsonapi::ObjectSerializer
belongs_to :owner, record_type: { User => :user, Administrator => :administrator }
end
As a matter of fact, since we're memoizing the associated object => record_type with #64 when the Hash
isn't provided (Thanks @christophersansone for the tip), I think we can make pretty much the same (performance wise) to not need to specify a record_type
at all:
class ProjectSerializer
include FastJsonapi::ObjectSerializer
belongs_to :owner # The auto-detect fallback + memoization added in #64 would kick in
end
(You could still define a Hash
for record_type
, but that would give just a very marginal performance gain when serializing 1 object, I think)
Your thoughts @shishirmk @christophersansone @AtomGrafiks ?
Rails.cache.fetch might need a race_condition_ttl option?
Setting :race_condition_ttl is very useful in situations where a cache entry is used very frequently and is under heavy load. If a cache expires and due to heavy load several different processes will try to read data natively and then they all will try to write to cache. To avoid that case the first process to find an expired cache entry will bump the cache expiration time by the value set in :race_condition_ttl. Yes, this process is extending the time for a stale value by another few seconds. Because of extended life of the previous cache, other processes will continue to use slightly stale data for a just a bit longer. In the meantime that first process will go ahead and will write into cache the new value. After that all the processes will start getting the new value. The key is to keep :race_condition_ttl small.
Is there any possibility to use attribute definitions of one Serializer in another?
Like i have:
class SimpleDataSerializer
attributes :a, :b, :c
end
class FullDataSerializer
attributes :a, :b, :c, :d, :e
end
#Scopes
scope :simple
...
scope full, -> do
merge(x.simple).select(additionalData)
end
for many Objects. so it would be nice to include simple in full Serializer and avoid double writing work. Especially to avoid dopple work when attributes in simple change.
Currently, if a class that is being serialized does not have an attribute id
an error undefined method 'id'
is thrown. IMO we should not have an opinion about what attributes are in the class at all. This will allow for non-ActiveRecord classes to also be serialized. At the very least, however, we should document that this is a required field.
The gemspec of juwelier
is a mess. What are the advantages of it and running rake gemspec
every time vs the regular Bundler gemspec?
My serializer
module Api
module V4
class EmployeeSerializer
include FastJsonapi::ObjectSerializer
...
end
end
end
My Controller
module Api
module V4
class EmployeesController < ApiController
...
def index
...
...
render json: Api::V4::EmployeeSerializer.new(employees), status: :ok
end
end
end
end
got this:
uninitialized constant Api::V4::EmployeeSerializer::FastJsonapi
but it's working well if calling it from console.
was looked at this: #16
but it's different. CMIIW
As one of the lead developers on Skylight it's awesome to see you integrating it!
This is probably a bit counter to our own self-interest, but I think it would probably make a bit more sense if, instead of using Skylight::Helpers
you just use ActiveSupport::Notifications
. You could then set up a Skylight::Normalizer
to consume the events if Skylight was present or other libraries could use them as well. We haven't really flushed out a public API for adding Normalizers so this is definitely something I'd be happy to discuss with you if you're interested.
Hi,
We works with AMS, and we have many options to customize the serialization output.
Actually the serialization object with fast_jsonapi
are imposed.
{
"data": {
"id": "232",
"type": "movie",
"attributes": {
"name": "test movie",
"year": null
},
...
}
So, do you have any ideas if you wants add more options to changes structure of data, example if I want build :
GET /movies/:id
{
"movie": {
"id": "232",
"name": "test movie",
"year": null
}
}
GET /movies
{
"movies": [
{
"id": "232",
"name": "test movie",
"year": null
},
{
"id": "233",
"name": "another test movie",
"year": null
}
],
"meta": { ... }
}
Thanks
Attempt to serialize model with has_one
association fails if association is nil:
NoMethodError (undefined method 'id' for nil:NilClass)
(fast_jsonapi-1.0.16/lib/extensions/has_one.rb:12)
If associated model exists, it gets serialized correctly.
Example:
class User < ApplicationRecord
has_one :profile
end
class Profile < ApplicationRecord
belongs_to :user
end
class UserSerializer
include FastJsonapi::ObjectSerializer
attributes :id, :name
has_one :profile
end
UserSerializer.new(User.create(name: "John")).serialized_json
NoMethodError (undefined method 'id' for nil:NilClass)
In some cases, the id
column or attribute is hard coded in. It might make more sense to use the primary key or something similar to derive the actual primary key.
I’m the creator of JSONAPI Suite which currently uses jsonapi-rb for the serialization layer. Have you benchmarked against jsonapi-rb?
JSONAPI Suite supports deeply nested reads and writes, integration spec helpers, automatic documentation, and clients that provide a friendly ActiveRecord-like interface. I'd love to get a sense of your roadmap to see if we could use this as an alternate serialization layer.
According to this PR #36, OJ is enabled for AMS
Now causing the benchmark spec randomly failed, looks like the speed factor is not quite consistent since it's random. I might look into this later anyway.
1) FastJsonapi::ObjectSerializer when comparing with AMS 0.10.x should serialize 1 records atleast 25 times faster than AMS
Failure/Error: expect { our_serializer.serialized_json }.to perform_faster_than { ams_serializer.to_json }.at_least(speed_factor).times
expected given block to perform faster than comparison block by at_least 25 times, but performed faster by 22.81 times
# ./spec/lib/object_serializer_performance_spec.rb:77:in `block (4 levels) in <top (required)>'
2) FastJsonapi::ObjectSerializer when comparing with AMS 0.10.x and with includes and meta should serialize 25 records atleast 25 times faster than AMS
Failure/Error: expect { our_serializer.serialized_json }.to perform_faster_than { ams_serializer.to_json }.at_least(speed_factor).times
expected given block to perform faster than comparison block by at_least 25 times, but performed faster by 19.94 times
# ./spec/lib/object_serializer_performance_spec.rb:102:in `block (4 levels) in <top (required)>'
3) FastJsonapi::ObjectSerializer when comparing with AMS 0.10.x and with includes and meta should serialize 250 records atleast 25 times faster than AMS
Failure/Error: expect { our_serializer.serialized_json }.to perform_faster_than { ams_serializer.to_json }.at_least(speed_factor).times
expected given block to perform faster than comparison block by at_least 25 times, but performed faster by 19.44 times
# ./spec/lib/object_serializer_performance_spec.rb:102:in `block (4 levels) in <top (required)>'
Finished in 25.31 seconds (files took 0.74305 seconds to load)
49 examples, 3 failures
rspec './spec/lib/object_serializer_performance_spec.rb[1:2:1]' # FastJsonapi::ObjectSerializer when comparing with AMS 0.10.x should serialize 1 records atleast 25 times faster than AMS
rspec './spec/lib/object_serializer_performance_spec.rb[1:3:2]' # FastJsonapi::ObjectSerializer when comparing with AMS 0.10.x and with includes and meta should serialize 25 records atleast 25 times faster than AMS
rspec './spec/lib/object_serializer_performance_spec.rb[1:3:3]' # FastJsonapi::ObjectSerializer when comparing with AMS 0.10.x and with includes and meta should serialize 250 records atleast 25 times faster than AMS
Interested in using this gem. Any conflict with having existing active_model_serializers in app already?
I'm kind of courious where exactly or what makes fast_jsonapi 25x faster than AMS. Could you provide me some information on this?
It is clear that AMS probably generates some overhead due to a variety of features such as
custom attributes, adapters, conditionals and others. Eventhough the benchmark tests are only using the non-default adapter. E.g.: Only by removing this line of code and using the default adapter the execution times of AWS are dropping almost by 50%
ActiveModel::Serializer.config.adapter = :json_api
Serializer Records Time
AMS serializer 1 1.25 ms
Fast serializer 1 0.14 ms
Serializer Records Time
AMS serializer 25 7.98 ms
Fast serializer 25 0.57 ms
Serializer Records Time
AMS serializer 250 73.46 ms
Fast serializer 250 2.64 ms
Serializer Records Time
AMS serializer 1000 322.16 ms
Fast serializer 1000 15.85 ms
Serializer Records Time
AMS serializer 1 0.55 ms
Fast serializer 1 0.13 ms
Serializer Records Time
AMS serializer 25 5.49 ms
Fast serializer 25 0.55 ms
Serializer Records Time
AMS serializer 250 63.45 ms
Fast serializer 250 4.77 ms
Serializer Records Time
AMS serializer 1000 282.82 ms
Fast serializer 1000 32.25 ms
I think this suggestion is distinct from #47, but it's similar and could possibly be developed at the same time, if others agree and would find this valuable. Alternatively, if there is already a solution to this that would be even better 😄
Scenario is as follows. This is for boxing/UFC fights where there are two athletes (fighters) in each bout, and many bouts in an event.
Serializers:
class FighterSerializer
include FastJsonapi::ObjectSerializer
attributes :first_name, :last_name
has_many :fighter_bouts
end
class FighterBoutSerializer
include FastJsonapi::ObjectSerializer
attributes :date_of_event, :name_of_event, :result
end
Models:
class Fighter < ActiveRecord::Base
has_many :fighter_bouts
def custom_method_with_scoping_and_eager_loading
fighter_bouts.includes(<nested relationships>).where(<scoping of records>).order(<detailed ordering>)
end
end
class FighterBout < ActiveRecord::Base
belongs_to :fighter
belongs_to :bout
end
class Bout < ActiveRecord::Base
has_many :fighter_bouts
belongs_to :event
belongs_to :weight_class
end
What I would like to be able to do is have an endpoint for a Fighter which is a compound document with included fighter_bouts. Such as:
fighter = Fighter.find(1)
opts = {include: [:fighter_bouts]}
payload = FighterSerializer.new(fighter, opts).serialized_json
render json: payload
However, I want to use the custom method defined on the Fighter class, because it will eager load everything needed from a series of nested associations. Data from these nested associations will be "flattened" and presented as attributes on the included fighter_bouts. For example, the event name will be returned as an attribute of a fighter_bout, even though in actuality this value is 2 associations away in the database.
Therefore I was thinking it would be very useful to be able to either pass an additional method name or value along with the options hash being given to the serializer. Or, allow for a custom-named "association method" in the serializer. Extremely roughly conceptualized as:
opts = {include: [:fighter_bouts_custom]}
payload = FighterSerializer.new(fighter, opts).serialized_json
class FighterSerializer
include FastJsonapi::ObjectSerializer
attributes :first_name, :last_name
has_many :fighter_bouts
def fighter_bouts_custom
<reference to custom method on the Fighter class>
end
end
Thanks for reading!
Having a Series
serializer with has_many :episodes
SeriesSerializer.new(series, include: ['episodes'])
Throws an ArgumentError
.
I would expect it to work, since includes are often pulled from a controller's params, which are always strings.
Having .to_sym
the strings would also be a memory issue in Ruby before 2.2.
As mentioned in title, how can I integrate this with DynamoDB using aws-record gem?
For example, I have this Project
model
class Project
include Aws::Record
include ActiveModel::Validations
string_attr :id, hash_key: true
string_attr :state
string_attr :title
string_attr :description
datetime_attr :start_date
string_attr :status
string_attr :company
string_attr :created_by
end
and then I have this Company
model
class Company
include Aws::Record
include ActiveModel::Validations
string_attr :id, hash_key: true
string_attr :name
end
and then I have the serializer for Project
class ProjectSerializer
include FastJsonapi::ObjectSerializer
set_type :project
attributes :id, :state, :title,
:description, :start_date, :status,
:company, :created_by
has_one :company
end
it return me error as follow:
{"message":"undefined method `company_id' for #\u003cProject:0x00007fbbeac09dd0\u003e\nDid you mean? company\n company=\n company_was"}
I have no idea how to fix this. Please help.
Would you accept a PR for removing Oj
as a dependency? Since this is a C gem, it prevents non-MRI VMs from using this gem. With MultiJson
, just having Oj
loaded in the host app is enough to make to_json
use it.
insolent lie
Active Model Serializer serialized 250 records in 138.71 ms
Fast JSON API serialized 250 records in 3.01 ms
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.