{"id":13878383,"url":"https://github.com/plucker-serializer/plucker_serializer","last_synced_at":"2025-07-16T14:31:59.125Z","repository":{"id":50689485,"uuid":"519847269","full_name":"plucker-serializer/plucker_serializer","owner":"plucker-serializer","description":"A fast JSON serializer for Rails ActiveRecord \u0026 Ruby Objects","archived":false,"fork":false,"pushed_at":"2023-04-12T10:08:39.000Z","size":67,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-11-16T02:50:57.265Z","etag":null,"topics":["activerecord","json-serialization","performance","rails","ruby","serialization","serializer"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/plucker-serializer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-07-31T17:47:43.000Z","updated_at":"2024-04-27T19:56:12.000Z","dependencies_parsed_at":"2022-09-22T15:01:12.843Z","dependency_job_id":null,"html_url":"https://github.com/plucker-serializer/plucker_serializer","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plucker-serializer%2Fplucker_serializer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plucker-serializer%2Fplucker_serializer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plucker-serializer%2Fplucker_serializer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plucker-serializer%2Fplucker_serializer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/plucker-serializer","download_url":"https://codeload.github.com/plucker-serializer/plucker_serializer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226138849,"owners_count":17579496,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["activerecord","json-serialization","performance","rails","ruby","serialization","serializer"],"created_at":"2024-08-06T08:01:47.962Z","updated_at":"2024-11-24T07:30:59.247Z","avatar_url":"https://github.com/plucker-serializer.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"# Plucker Serializer\n\n[![Gem Version](https://badge.fury.io/rb/plucker_serializer.svg)](https://badge.fury.io/rb/plucker_serializer)\n\n## About\n\nPlucker serializer is a fast JSON serializer for ActiveRecord and Ruby objects. It is inspired by ActiveModelSerializers and Panko, and brings performance enhancements for real world Rails APIs. \n\nThe interface is very close to ActiveModelSerializers and Panko.\n\nPlucker was created with performance in mind, and is most suitable for Rails APIs.\n\nIt uses different methods to achieve high throughput and low memory consumption :\n\n- Plucker uses ActiveRecord's `pluck` function when possible to avoid going through ActiveRecord instantiation and to optimize\n  database queries. \n- Serializer metadata is computed ahead of time, when serializer classes are parsed. Serializers have a `_descriptor` class attribute\n  which contains all the information necessary to compute the serialization.\n- Plucker offers built-in caching for single objects, collections and associations. Caching associations and collections can result in great performance enhancements compared to simple single object caching.\n\n\n## Installation\n\nTo install Plucker, add this line to your application's Gemfile:\n\n```\ngem 'plucker_serializer'\n```\n\nAnd then execute:\n\n```\n$ bundle install\n```\n\n## Getting Started\n\nTo create a serializer, create a class that inherits from `Plucker::Base` :\n\n``` ruby\nclass PostSerializer \u003c Plucker::Base\n  attributes :title\nend\n\nclass UserSerializer \u003c Plucker::Base\n  attributes :id, :name, :age\n\n  has_many :posts, serializer: PostSerializer\nend\n```\n\nTo get the hash or JSON output for an object, instantiate your serializer class with an object and call `to_hash`, `to_h`, or `to_json` :\n``` ruby\npost = Post.last\npost_serialized = PostSerializer.new(post).to_json\n```\n``` json\n{ \"title\": \"my-post-title\" }\n```\n\n\nand for a collection of objects, use the `Plucker::Collection` class :\n``` ruby\nposts = Post.all\nposts_serialized = Plucker::Collection.new(posts).to_json\n```\n``` json\n[{ \"title\": \"my-post-title\" }, { \"title\": \"my-second-post-title\" }]\n```\n\n## Describing your objects with Plucker\n\n### Attributes\n\nA serializer can define attributes with the `attribute` and `attributes` functions.\n``` ruby\nclass PostSerializer \u003c Plucker::Base\n  attributes :title, :created_at\n  attribute :description\nend\n```\n\nAttributes must be attributes of the serialized object, or they can come from a serializer method or block.\n``` ruby\nclass PostSerializer \u003c Plucker::Base\n  attribute :method_attribute\n  attribute :block_attribute do |object|\n    object.title.capitalize\n  end\n\n  def method_attribute\n    # object represents the serialized object and is available in the method context\n    object.title.parameterize\n  end\nend\n```\n\nA key option can be passed to an attribute to define a different key in the serialized output :\n``` ruby\nclass PostSerializer \u003c Plucker::Base\n  attributes :title\n  attribute :description, key: :summary\nend\n```\n``` json\n{ \"title\": \"my-post-title\", \"summary\": \"my-post-description\" }\n```\n\n### Associations\n\nA serializer can define `belongs_to`, `has_one` and `has_many` associations to fetch associated objects.\n``` ruby\nclass PostSerializer \u003c Plucker::Base\n    attributes :title, :description\n\n    has_one :author # AuthorSerializer will be used\n    belongs_to :category, key: :section # CategorySerializer will be used\n    has_many :tags, serializer: TagCustomSerializer\nend\n\nclass AuthorSerializer \u003c Plucker::Base\n    attributes :first_name, :last_name\nend\n\nclass CategorySerializer \u003c Plucker::Base\n    attributes :id, :display_name\nend\n\nclass TagCustomSerializer \u003c Plucker::Base\n    attributes :id, :display_name\nend\n```\n\nBy default, Plucker will use the `${MODEL}Serializer` serializer class for associations, but you can pass a custom serializer\nwith the `serializer` option. Plucker will use the name of the model and not the name of the association, so for example if you\nhave an `author` association that links a Post to a User, Plucker will use the `UserSerializer` class by default.\n\nAs for attributes, it is also possible to pass a custom key for an association, and to add a block :\n\n``` ruby\nclass PostSerializer \u003c Plucker::Base\n    attributes :title, :description\n    \n    has_many :tags, serializer: TagCustomSerializer do |object|\n      # block must return an ActiveRecord::Collection\n      object.tags.limit(1)\n    end\nend\n```\n\n### Model and serializer classes\n\nPlucker must know the model name that is represented by the serializer. \nBy default, it will use the beginning of your serializer class name.\nIf your class is called `PostSerializer`, the model used will be `Post`. If your class is called `PostTagSerializer`, the model used will be `PostTag`.\n\nIf you class name is different from the model name, use the `model` option to tell Plucker which model to use :\n``` ruby\nclass PostCustomSerializer \u003c Plucker::Base\n    model Post\n    attributes :title\nend\n```\n\nFor collections, as for associations, Plucker will use the serialized object class to compute the serializer class, but you can pass a custom serializer :\n``` ruby\nposts = Post.all\n# Plucker will use the PostSerializer class by default\nposts_serialized = Plucker::Collection.new(posts).to_json\n\n# Use the serializer option to pass a custom serializer\nposts_serialized_custom = Plucker::Collection.new(posts, serializer: CustomPostSerializer).to_json\n```\n\n## Caching\n\nPlucker has built-in caching for single objects, collections and associations.\nTo enable caching, create an initializer `plucker.rb` and define a cache store :\n``` ruby\nPlucker.configure do |config|\n  config.cache_store = Rails.cache\nend\n```\n\nThen enable caching in each serializer with the `cache` option:\n``` ruby\nclass PostCustomSerializer \u003c Plucker::Base\n    cache\n    attributes :title\nend\n```\n\nPlucker uses ActiveRecord's `cache_key` and `cache_version` for single objects and collections.\n\nWhen caching a collection, ActiveRecord will query the database to get the last updated object. The cache key\nwill include a hash of the SQL query.\nThis can be a performance issue in some cases, depending on your application.\nTo avoid collection caching, use the `cache` option with `multi` when instantiating the collection :\n``` ruby\nposts = Post.all\nposts_serialized = Plucker::Collection.new(posts, cache: :multi)\n```\nThis will tell Plucker to not cache the whole collection but to cache each object separately.\n\n\n## Tests\n\nTests are written with [RSpec](https://rspec.info/).\nTo run tests, run command :\n```\n$ rspec\n```\n\n\n## Benchmarks\n\nBenchmarks are available in the `benchmarks` folder, to compare Plucker with ActiveModelSerializers and Panko.\nTo run benchmarks, use the rake command :\n```\n$ rake benchmarks\n```\n\n### Plucker\n\n| Benchmark                   | ip/s     | allocs/retained |\n|-----------------------------|----------|-----------------|\n| Plucker_Simple_Posts_50     | 1,855.78 | 867/5           |\n| Plucker_Simple_Posts_1000   | 121.4    | 16199/126       |\n| Plucker_HasOne_Posts_50     | 87.53    | 10424/83        |\n| Plucker_HasOne_Posts_1000   | 21.83    | 78779/75        |\n| Plucker_HasMany_Posts_50    | 45.47    | 25023/72        |\n| Plucker_HasMany_Posts_1000  | 2.27     | 497243/2        |\n\n\n### Panko\n\n| Benchmark                              | ip/s     | allocs/retained |\n|----------------------------------------|----------|-----------------|\n| Panko_ActiveRecord_Simple_Posts_50     | 2,306.29 | 721/24          |\n| Panko_ActiveRecord_Simple_Posts_1000   | 39.01    | 30799/81        |\n| Panko_ActiveRecord_HasOne_Posts_50     | 92.5     | 8187/80         |\n| Panko_ActiveRecord_HasOne_Posts_1000   | 39.19    | 31262/22026     |\n| Panko_ActiveRecord_HasMany_Posts_50    | 55.52    | 16893/102       |\n| Panko_ActiveRecord_HasMany_Posts_1000  | 2.63     | 331262/168026   |\n\n\n### ActiveModelSerializers 0.10\n\n| Benchmark               | ip/s   | allocs/retained |\n|-------------------------|--------|-----------------|\n| AMS_Simple_Posts_50     | 291.05 | 4625/162        |\n| AMS_Simple_Posts_1000   | 11.84  | 88838/77        |\n| AMS_HasOne_Posts_50     | 56.93  | 14456/87        |\n| AMS_HasOne_Posts_1000   | 6.02   | 155293/2        |\n| AMS_HasMany_Posts_50    | 20.26  | 45199/109       |\n| AMS_HasMany_Posts_1000  | 1.03   | 895293/2        |\n\n\nPlucker shows significant performance improvements compared to ActiveModelSerializer.\n\nWhen comparing to Panko, we can also see improvements in throughput and memory in some cases, thanks to the plucking strategy. Plucker is especially good in the case of objects with only attributes.\n\nPanko seems to have memory problems for large collections.\n\nThe benchmarks do not use caching, and Plucker would see a huge boost compared to Panko if caching were enabled. We did not add it to the benchmarks because the comparison would not make sense as Panko does not enable caching.\n\n\n## License\n\nThe gem is available as open source under the terms of the MIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplucker-serializer%2Fplucker_serializer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fplucker-serializer%2Fplucker_serializer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplucker-serializer%2Fplucker_serializer/lists"}