### Install Panko Gem Source: https://context7.com/yosiat/panko_serializer/llms.txt Add Panko to your Gemfile and run bundle install to install the library. ```ruby # Gemfile gem "panko_serializer" ``` ```bash bundle install ``` -------------------------------- ### Define a Panko Serializer for User Source: https://github.com/yosiat/panko_serializer/wiki/Design-Choices Define a serializer for a User model, specifying attributes and custom method fields. This is the Ruby part of Panko's setup. ```ruby class UserSerializer < Panko::Serializer attributes :name, :age, :email def name "#{object.first_name} #{object.last_name}" end end ``` -------------------------------- ### Render JSON with Panko::Response in Rails Controller Source: https://context7.com/yosiat/panko_serializer/llms.txt Use `Panko::Response` to construct complex JSON payloads in a Rails controller's index action. This example includes paginated users and their associated posts, along with total count and page number. ```ruby class UsersController < ApplicationController def index users = User.includes(:posts).page(params[:page]).per(25) render json: Panko::Response.new( users: Panko::ArraySerializer.new(users, each_serializer: UserSerializer, scope: current_user), total: users.total_count, page: users.current_page ) end def show user = User.includes(:posts, :profile).find(params[:id]) render json: Panko::Response.create { |r| { user: r.serializer(user, UserSerializer) } } end end ``` -------------------------------- ### Recursive Nested Filtering in Panko Source: https://github.com/yosiat/panko_serializer/blob/master/docs/associations.md Nested filters are recursive, allowing filtering of associations within associations. This example filters comments by ID and author by name. ```ruby posts = Post.all Panko::ArraySerializer.new(posts, only: { instance: [:title, :body, :author, :comments], author: [:id], comments: { instance: [:id, :author], author: [:name] } }) ``` -------------------------------- ### ActiveModelSerializers 0.9.7 Benchmark Results Source: https://github.com/yosiat/panko_serializer/wiki/Design-Choices Benchmark results for ActiveModelSerializers 0.9.7, showing iterations per second and memory allocations for various serialization scenarios. ```text +-------------------------+--------+-----------------+ | Benchmark | ip/s | allocs/retained | +-------------------------+--------+-----------------+ | AMS_HasOne_Posts_14000 | 0.68 | 574009/112001 | | AMS_HasOne_Posts_50 | 206.98 | 2057/400 | | AMS_Simple_Posts_14000 | 1.89 | 280007/84000 | | AMS_Simple_Posts_50 | 579.98 | 1007/300 | | AMS_Except_Posts_14000 | 0.62 | 560007/70000 | | AMS_Except_Posts_50 | 209.31 | 2007/250 | | AMS_Include_Posts_14000 | 0.66 | 574007/112000 | | AMS_Include_Posts_50 | 202.88 | 2057/400 | +-------------------------+--------+-----------------+ ``` -------------------------------- ### Serialize a User Object with Panko Source: https://github.com/yosiat/panko_serializer/wiki/Design-Choices Demonstrates how to instantiate and use a Panko serializer to convert an ActiveRecord object into a JSON string. Ensure the serializer class is defined before use. ```ruby # fetch user from database user = User.first # create serializer, with empty options serializer = UserSerilizer.new # serialize to JSON serializer.serialize_to_json(user) ``` -------------------------------- ### Panko Serializer Benchmark Results Source: https://github.com/yosiat/panko_serializer/wiki/Design-Choices Benchmark results for Panko serializer, demonstrating its performance in terms of iterations per second and memory allocations compared to ActiveModelSerializers. ```text +----------------------------------------+----------+-----------------+ | Benchmark | ip/s | allocs/retained | +----------------------------------------+----------+-----------------+ | Panko_HasOne_Posts_14000 | 5.16 | 28322/34 | | Panko_HasOne_Posts_50 | 1,921.92 | 108/0 | | Panko_Simple_Posts_14000 | 14.7 | 28/9 | | Panko_Simple_Posts_50 | 4,983.11 | 8/0 | | Panko_SimpleWithMethodCall_Posts_14000 | 10.18 | 51/19 | | Panko_SimpleWithMethodCall_Posts_50 | 3,122.25 | 8/0 | | Panko_Except_Posts_14000 | 5.94 | 28059/18 | | Panko_Except_Posts_50 | 2,000.76 | 108/0 | | Panko_Include_Posts_14000 | 5.08 | 28008/0 | | Panko_Include_Posts_50 | 1,621.86 | 108/0 | +----------------------------------------+----------+-----------------+ ``` -------------------------------- ### Define Default Filters with 'filters_for' Source: https://github.com/yosiat/panko_serializer/blob/master/docs/attributes.md Implement `self.filters_for` class method to define default filtering logic based on context and scope, reducing duplication of filtering code. ```ruby class UserSerializer < Panko::Serializer attributes :id, :name, :email def self.filters_for(context, scope) { only: [:name] } end end # this line will return { 'name': '..' } UserSerializer.serialize(User.first) ``` -------------------------------- ### Pass Data with `context` and `scope` Options Source: https://context7.com/yosiat/panko_serializer/llms.txt Pass arbitrary data into a serializer via `context:` (read as `context`) and `scope:` (read as `scope`). This is useful for injecting current user, feature flags, or request-specific data. ```ruby class ArticleSerializer < Panko::Serializer attributes :id, :title, :body, :secret_notes def secret_notes # Only include secret notes for admin users return Panko::Serializer::SKIP unless context[:current_user]&.admin? object.secret_notes end end serializer = ArticleSerializer.new( context: { current_user: current_user }, scope: current_user ) serializer.serialize_to_json(Article.find(1)) # Admin: => '{"id":1,"title":"...","body":"...","secret_notes":"confidential"}' # Non-admin: => '{"id":1,"title":"...","body":"..."}' ``` -------------------------------- ### ActiveRecord Type Casting Benchmark Results Source: https://github.com/yosiat/panko_serializer/wiki/Design-Choices Benchmark results for ActiveRecord type casting, comparing performance with and without type casting across various data types. ```text +--------------------------------------------------------------------------------------+--------------+-----------------+ | Benchmark | ip/s | allocs/retained | +--------------------------------------------------------------------------------------+--------------+-----------------+ | ActiveRecord::Type::String_TypeCast | 1,370,916.18 | 3/0 | | ActiveRecord::Type::String_NoTypeCast | 1,870,203.17 | 1/0 | | ActiveRecord::Type::Text_TypeCast | 1,367,229.05 | 3/0 | | ActiveRecord::Type::Text_NoTypeCast | 1,984,543.45 | 1/0 | | ActiveRecord::Type::Integer_TypeCast | 4,345,258.52 | 0/0 | | ActiveRecord::Type::Integer_NoTypeCast | 5,334,606.31 | 0/0 | | ActiveRecord::Type::Float_TypeCast | 963,485.73 | 0/0 | | ActiveRecord::Type::Float_NoTypeCast | 1,977,545.76 | 0/0 | | ActiveRecord::Type::Float_TypeCast | 975,807.08 | 0/0 | | ActiveRecord::Type::Float_NoTypeCast | 1,946,103.12 | 0/0 | | ActiveRecord::Type::Boolean_TypeCast | 2,688,596.35 | 1/0 | | ActiveRecord::Type::Boolean_NoTypeCast | 3,148,371.25 | 1/0 | | ActiveRecord::Type::Boolean_TypeCast | 2,710,408.13 | 1/0 | | ActiveRecord::Type::Boolean_NoTypeCast | 3,198,979.65 | 1/0 | | ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Integer_TypeCast | 4,342,172.01 | 0/0 | | ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Integer_NoTypeCast | 5,390,684.35 | 0/0 | | ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Float_TypeCast | 804,805.92 | 0/0 | | ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Float_NoTypeCast | 1,853,420.47 | 0/0 | | ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Float_TypeCast | 916,967.77 | 0/0 | +--------------------------------------------------------------------------------------+--------------+-----------------+ ``` -------------------------------- ### Define a User Serializer Source: https://github.com/yosiat/panko_serializer/blob/master/docs/design-choices.md Define a serializer for a User object, specifying attributes and custom method fields. This sets up how the object will be serialized. ```ruby class UserSerializer < Panko::Serializer attributes :name, :age, :email def name "#{object.first_name} #{object.last_name}" end end ``` -------------------------------- ### Admin Context Serialization Source: https://context7.com/yosiat/panko_serializer/llms.txt Serializes a user object including all fields when the context role is 'admin'. ```ruby UserSerializer.new(context: { role: "admin" }).serialize_to_json(User.first) ``` -------------------------------- ### Define Default Filters with `filters_for` Source: https://context7.com/yosiat/panko_serializer/llms.txt Centralize repeated filtering logic by defining a class method `filters_for(context, scope)` on the serializer. These filters are combined with instantiation options like `only:`/`except:`. ```ruby class UserSerializer < Panko::Serializer attributes :id, :name, :email, :admin_notes def self.filters_for(context, scope) if context&.dig(:role) == "admin" {} # admins see everything else { except: [:admin_notes] } end end end # Non-admin context — admin_notes excluded automatically UserSerializer.new(context: { role: "user" }).serialize_to_json(User.first) ``` -------------------------------- ### Define Panko Serializers Source: https://github.com/yosiat/panko_serializer/blob/master/docs/getting-started.md Create serializer classes by inheriting from Panko::Serializer and defining attributes and associations. ```ruby class PostSerializer < Panko::Serializer attributes :title end class UserSerializer < Panko::Serializer attributes :id, :name, :age has_many :posts, serializer: PostSerializer end ``` -------------------------------- ### Serializer Inheritance Source: https://context7.com/yosiat/panko_serializer/llms.txt Demonstrates how child serializers inherit attributes and associations from parent serializers, promoting code reuse. Child serializers can add their own attributes and associations. ```ruby class BaseSerializer < Panko::Serializer attributes :id, :created_at, :updated_at end class PostSerializer < BaseSerializer attributes :title, :body has_many :comments, each_serializer: CommentSerializer end # PostSerializer serializes: id, created_at, updated_at, title, body, comments PostSerializer.new.serialize_to_json(Post.includes(:comments).first) ``` -------------------------------- ### Define Field and Method Attributes Source: https://github.com/yosiat/panko_serializer/blob/master/docs/attributes.md Use `attributes` to declare fields for serialization. Define methods with the same name as attributes to include computed or virtual properties. ```ruby class UserSerializer < Panko::Serializer attributes :full_name def full_name "#{object.first_name} #{object.last_name}" end end ``` ```ruby class PostSerializer < Panko::Serializer attributes :author_name def author_name "#{object.author.first_name} #{object.author.last_name}" end end ``` -------------------------------- ### Serialize a User Object to JSON Source: https://github.com/yosiat/panko_serializer/blob/master/docs/design-choices.md Instantiate and use a serializer to convert an ActiveRecord object into a JSON string. Ensure the serializer class is defined before use. ```ruby # fetch user from database user = User.first # create serializer, with empty options serializer = UserSerializer.new # serialize to JSON serializer.serialize_to_json(user) ``` -------------------------------- ### Serialize Single Object with Panko::Response.create Source: https://github.com/yosiat/panko_serializer/blob/master/docs/response-bag.md Utilize Panko::Response.create with a block to serialize a single object. This method is suitable when you need more control over the serialization process for individual items. ```ruby class PostsController < ApplicationController def show post = Post.find(params[:id]) render( json: Panko::Response.create do |r| { success: true, post: r.serializer(post, PostSerializer) } end ) end end ``` -------------------------------- ### Alias Attributes for Different Client Names Source: https://github.com/yosiat/panko_serializer/blob/master/docs/attributes.md Use `aliases` to map an internal attribute name to a different client-facing name, preserving Panko's type casting for performance. ```ruby class PostSerializer < Panko::Serializer aliases created_at: :published_at end ``` -------------------------------- ### Serialize Collections with `Panko::ArraySerializer` Source: https://context7.com/yosiat/panko_serializer/llms.txt Serialize any enumerable of objects in a single pass using `Panko::ArraySerializer`. It requires `each_serializer:` and supports standard filtering options like `only:`, `except:`, `context:`, and `scope:`. ```ruby class UsersController < ApplicationController def index users = User.includes(:posts).all render json: Panko::ArraySerializer.new( users, each_serializer: UserSerializer, context: { current_user: current_user } ).to_json end end # Standalone usage json = Panko::ArraySerializer.new(User.all, each_serializer: UserSerializer).to_json # As a Ruby array of hashes array = Panko::ArraySerializer.new(User.limit(2), each_serializer: UserSerializer).to_a ``` -------------------------------- ### filters_for Source: https://context7.com/yosiat/panko_serializer/llms.txt Define a class method `filters_for(context, scope)` on the serializer to centralize repeated filtering logic. These filters are combined with any `only:`/`except:` options passed at instantiation. ```APIDOC ## `filters_for` — Serializer-Level Default Filters Define a class method `filters_for(context, scope)` on the serializer to centralize repeated filtering logic. These filters are combined with any `only:`/`except:` options passed at instantiation. ```ruby class UserSerializer < Panko::Serializer attributes :id, :name, :email, :admin_notes def self.filters_for(context, scope) if context&.dig(:role) == "admin" {} # admins see everything else { except: [:admin_notes] } end end end # Non-admin context — admin_notes excluded automatically UserSerializer.new(context: { role: "user" }).serialize_to_json(User.first) # => '{"id":1,"name":"Alice","email":"alice@example.com"}' ``` ``` -------------------------------- ### Nested Filters for Associations Source: https://context7.com/yosiat/panko_serializer/llms.txt Demonstrates recursive filtering of attributes for associated objects using `only:` with nested hashes. Use `instance:` to refer to the current serializer's attributes. ```ruby class CommentSerializer < Panko::Serializer attributes :id, :body has_one :author, serializer: AuthorSerializer # AuthorSerializer has :id, :name, :email end class PostSerializer < Panko::Serializer attributes :id, :title, :body has_many :comments, each_serializer: CommentSerializer end posts = Post.includes(comments: :author).all # Serialize only title + comments with only id + author's name Panko::ArraySerializer.new(posts, each_serializer: PostSerializer, only: { instance: [:title, :comments], comments: { instance: [:id, :author], author: [:name] } }).to_json ``` -------------------------------- ### Serialize a Single Object Source: https://github.com/yosiat/panko_serializer/blob/master/docs/getting-started.md Serialize a single object instance to JSON using the serializer's `serialize_to_json` or `serialize` methods. ```ruby # Using Oj serializer PostSerializer.new.serialize_to_json(Post.first) # or, similar to #serializable_hash PostSerializer.new.serialize(Post.first).to_json ``` -------------------------------- ### Add Panko to Gemfile Source: https://github.com/yosiat/panko_serializer/blob/master/docs/getting-started.md Include Panko Serializer in your project's Gemfile to manage dependencies. ```ruby gem "panko_serializer" ``` -------------------------------- ### Composing Mixed Payloads with Panko::Response (Index Action) Source: https://context7.com/yosiat/panko_serializer/llms.txt Combines scalar values and an ArraySerializer into a single JSON response for an index action. Requires `Panko::Response.new`. ```ruby class PostsController < ApplicationController def index posts = Post.all render json: Panko::Response.new( success: true, total_count: posts.count, posts: Panko::ArraySerializer.new(posts, each_serializer: PostSerializer) ) # => '{"success":true,"total_count":42,"posts":[{"id":1,...},...]} end # Show action — single object via block API def show post = Post.find(params[:id]) render json: Panko::Response.create { |r| { success: true, post: r.serializer(post, PostSerializer) } } # => '{"success":true,"post":{"id":1,"title":"..."}}' end end ``` -------------------------------- ### Define a Basic User Serializer Source: https://context7.com/yosiat/panko_serializer/llms.txt Subclass `Panko::Serializer` to define a serializer. Declare attributes and virtual values by defining instance methods. The serializer instance is single-use. ```ruby class UserSerializer < Panko::Serializer attributes :id, :email, :created_at # Virtual (method) attribute — accesses object via `object` def full_name "#{object.first_name} #{object.last_name}" end end user = User.find(1) # Serialize to a JSON string (fastest path — uses Oj::StringWriter internally) json = UserSerializer.new.serialize_to_json(user) # => '{"id":1,"email":"alice@example.com","created_at":"2024-01-15T10:30:00.000Z","full_name":"Alice Smith"}' # Serialize to a Ruby hash hash = UserSerializer.new.serialize(user) # => { "id" => 1, "email" => "alice@example.com", "full_name" => "Alice Smith", ... } ``` -------------------------------- ### Filter Attributes with 'only' and 'except' Source: https://github.com/yosiat/panko_serializer/blob/master/docs/attributes.md Use `only` to include specific attributes or `except` to exclude specific attributes during serialization. Note that for associations, the filter key is the association name, not a property within it. ```ruby class UserSerializer < Panko::Serializer attributes :id, :name, :email end # this line will return { 'name': '..' } UserSerializer.new(only: [:name]).serialize(User.first) # this line will return { 'id': '..', 'email': ... } UserSerializer.new(except: [:name]).serialize(User.first) ``` -------------------------------- ### Panko::Serializer::SKIP Source: https://context7.com/yosiat/panko_serializer/llms.txt Use the `SKIP` sentinel from a method attribute to omit a key entirely from the JSON output instead of serializing `null`. ```APIDOC ## `Panko::Serializer::SKIP` — Conditionally Omit Fields Return the `SKIP` sentinel from a method attribute to omit that key entirely from the JSON output (rather than serializing `null`). ```ruby class ProfileSerializer < Panko::Serializer attributes :id, :username, :bio, :phone_number def phone_number # Omit the key entirely when the value is blank return Panko::Serializer::SKIP if object.phone_number.blank? object.phone_number end end ProfileSerializer.new.serialize_to_json(User.find(1)) # With phone: => '{"id":1,"username":"alice","bio":"...","phone_number":"+1-555-0100"}' # Without phone: => '{"id":1,"username":"alice","bio":"..."}' ``` ``` -------------------------------- ### Include Context in Serialization Source: https://github.com/yosiat/panko_serializer/blob/master/docs/attributes.md Pass a `context` hash to the serializer to provide additional data, such as feature flags, accessible within serializer methods. ```ruby class UserSerializer < Panko::Serializer attributes :id, :email def feature_flags context[:feature_flags] end end serializer = UserSerializer.new(context: { feature_flags: FeatureFlags.all }) serializer.serialize(User.first) ``` -------------------------------- ### only: and except: Filters Source: https://context7.com/yosiat/panko_serializer/llms.txt Restrict which attributes are serialized at instantiation time. `only:` takes precedence over `except:`. Filters apply to top-level attributes; use a Hash to filter nested associations. ```APIDOC ## `only:` and `except:` Filters Restrict which attributes are serialized at instantiation time. `only:` takes precedence over `except:` when both are provided. Filters apply to top-level attributes; use a Hash to filter nested associations. ```ruby class UserSerializer < Panko::Serializer attributes :id, :name, :email, :address, :phone end user = User.first # Include only :name UserSerializer.new(only: [:name]).serialize(user) # => { "name" => "Alice" } # Exclude :phone and :address UserSerializer.new(except: [:phone, :address]).serialize(user) # => { "id" => 1, "name" => "Alice", "email" => "alice@example.com" } # Nested filter: serialize posts with only :title, comments with only :id Panko::ArraySerializer.new( Post.includes(:comments).all, each_serializer: PostSerializer, only: { instance: [:id, :title, :comments], comments: [:id] } ).to_json # => '[{"id":1,"title":"Hello","comments":[{"id":10},{"id":11}]}]' ``` ``` -------------------------------- ### Compute Derived Values with Virtual Attributes Source: https://context7.com/yosiat/panko_serializer/llms.txt Define instance methods with the same name as a declared attribute to compute derived values. Access the record being serialized using the `object` instance variable. ```ruby class InvoiceSerializer < Panko::Serializer attributes :id, :subtotal, :tax_rate, :total, :customer_label def total (object.subtotal * (1 + object.tax_rate)).round(2) end def customer_label "#{object.customer.first_name} #{object.customer.last_name} <#{object.customer.email}>" end end InvoiceSerializer.new.serialize_to_json(Invoice.includes(:customer).first) # => '{"id":7,"subtotal":"99.0","tax_rate":"0.2","total":118.8,"customer_label":"Bob Jones "}' ``` -------------------------------- ### Serialize Collection with Panko::Response Source: https://github.com/yosiat/panko_serializer/blob/master/docs/response-bag.md Use Panko::Response to serialize a collection of objects, ensuring correct JSON output without nested strings. This is the recommended approach for collections. ```ruby class PostsController < ApplicationController def index posts = Post.all render json: Panko::Response.new( success: true, total_count: posts.count, posts: Panko::ArraySerializer.new(posts, each_serializer: PostSerializer) ) end end ``` -------------------------------- ### Filter Attributes with `only:` and `except:` Source: https://context7.com/yosiat/panko_serializer/llms.txt Restrict which attributes are serialized at instantiation time using `only:` and `except:`. `only:` takes precedence. Filters apply to top-level attributes; use a Hash for nested associations. ```ruby class UserSerializer < Panko::Serializer attributes :id, :name, :email, :address, :phone end user = User.first # Include only :name UserSerializer.new(only: [:name]).serialize(user) # Exclude :phone and :address UserSerializer.new(except: [:phone, :address]).serialize(user) # Nested filter: serialize posts with only :title, comments with only :id Panko::ArraySerializer.new( Post.includes(:comments).all, each_serializer: PostSerializer, only: { instance: [:id, :title, :comments], comments: [:id] } ).to_json ``` -------------------------------- ### Declare Field Attributes with `attributes` Source: https://context7.com/yosiat/panko_serializer/llms.txt List ActiveRecord columns or plain-object attributes to include in the serialized output. Panko performs its own type casting in C for performance. ```ruby class PostSerializer < Panko::Serializer attributes :id, :title, :body, :published_at, :view_count end post = Post.find(42) PostSerializer.new.serialize_to_json(post) # => '{"id":42,"title":"Hello Panko","body":"Fast JSON...","published_at":"2024-03-01T00:00:00.000Z","view_count":1500}' ``` -------------------------------- ### Rename Attributes with `aliases` Source: https://context7.com/yosiat/panko_serializer/llms.txt Expose a column under a different JSON key while maintaining Panko's native type casting. This is more performant than using a method attribute. ```ruby class PostSerializer < Panko::Serializer attributes :id, :body # Expose `created_at` as `published_at` and `updated_at` as `modifiedAt` aliases created_at: :published_at, updated_at: :modifiedAt end PostSerializer.new.serialize_to_json(Post.first) # => '{"id":1,"body":"...","published_at":"2024-03-01T00:00:00.000Z","modifiedAt":"2024-03-02T00:00:00.000Z"}' ``` -------------------------------- ### Serialize Collection Associations with `has_many` Source: https://context7.com/yosiat/panko_serializer/llms.txt Embed an array association using `has_many`. Pass `each_serializer:` (or `serializer:`) to specify the serializer for each element. Use `name:` to alias the JSON key. ```ruby class CommentSerializer < Panko::Serializer attributes :id, :body, :created_at end class PostSerializer < Panko::Serializer attributes :id, :title has_many :comments, each_serializer: CommentSerializer # Inferred: looks for `TagSerializer` has_many :tags # Aliased: `state_transitions` becomes `history` in JSON has_many :state_transitions, each_serializer: TransitionSerializer, name: :history end PostSerializer.new.serialize_to_json(Post.includes(:comments, :tags, :state_transitions).find(1)) ``` -------------------------------- ### Panko::ArraySerializer Source: https://context7.com/yosiat/panko_serializer/llms.txt Serialize any enumerable of objects in a single pass. Requires `each_serializer:` and supports `only:`, `except:`, `context:`, and `scope:` options. ```APIDOC ## `Panko::ArraySerializer` — Serialize Collections Serialize any enumerable of objects in a single highly-optimized pass. Always requires `each_serializer:`. Supports all the same `only:`, `except:`, `context:`, and `scope:` options as `Panko::Serializer`. ```ruby class UsersController < ApplicationController def index users = User.includes(:posts).all render json: Panko::ArraySerializer.new( users, each_serializer: UserSerializer, context: { current_user: current_user } ).to_json end end # Standalone usage json = Panko::ArraySerializer.new(User.all, each_serializer: UserSerializer).to_json # => '[{"id":1,"email":"a@x.com",...},{"id":2,...}]' # As a Ruby array of hashes array = Panko::ArraySerializer.new(User.limit(2), each_serializer: UserSerializer).to_a # => [{"id"=>1, ...}, {"id"=>2, ...}] ``` ``` -------------------------------- ### Alias Association Names in Panko Source: https://github.com/yosiat/panko_serializer/blob/master/docs/associations.md Alias an association's key name using the `name` option. The `actual_author` relationship will be serialized under the key `alias_author`. ```ruby class PostSerializer < Panko::Serializer attributes :title, :body has_one :actual_author, serializer: AuthorSerializer, name: :alias_author has_many :comments, each_serializer: CommentSerializer end ``` -------------------------------- ### Define has_one and has_many Associations in Panko Source: https://github.com/yosiat/panko_serializer/blob/master/docs/associations.md Use `has_one` and `has_many` to declare relationships to other serializers. Specify the serializer class explicitly using the `serializer` or `each_serializer` options. ```ruby class PostSerializer < Panko::Serializer attributes :title, :body has_one :author, serializer: AuthorSerializer has_many :comments, each_serializer: CommentSerializer end ``` -------------------------------- ### Serialize an Array of Objects in Rails Controller Source: https://github.com/yosiat/panko_serializer/blob/master/docs/getting-started.md Render a JSON array of objects using Panko::ArraySerializer within a Rails controller action. ```ruby class UsersController < ApplicationController def index users = User.includes(:posts).all render json: Panko::ArraySerializer.new(users, each_serializer: UserSerializer).to_json end end ``` -------------------------------- ### Serialize Single Associations with `has_one` Source: https://context7.com/yosiat/panko_serializer/llms.txt Embed a has_one (or belongs_to) association using a dedicated serializer. You can pass `serializer:` explicitly or let Panko infer it. Use `name:` to alias the JSON key for the association. ```ruby class AuthorSerializer < Panko::Serializer attributes :id, :name, :email end class ArticleSerializer < Panko::Serializer attributes :id, :title # Explicit serializer has_one :author, serializer: AuthorSerializer # Inferred — looks for `CommentSerializer` has_one :featured_comment # Aliased key: `editor` association becomes `reviewed_by` in JSON has_one :editor, serializer: AuthorSerializer, name: :reviewed_by end ArticleSerializer.new.serialize_to_json(Article.includes(:author, :featured_comment, :editor).first) ``` -------------------------------- ### Embedding Pre-serialized JSON with Panko::JsonValue Source: https://context7.com/yosiat/panko_serializer/llms.txt Wraps an existing JSON string in `Panko::JsonValue` to embed it within a `Panko::Response` without re-parsing or double-encoding. Useful for integrating cached JSON. ```ruby class PostsController < ApplicationController def index # Retrieve cached JSON string cached_posts_json = Rails.cache.fetch("posts_json") do Panko::ArraySerializer.new(Post.all, each_serializer: PostSerializer).to_json end render json: Panko::Response.new( success: true, total_count: Post.count, posts: Panko::JsonValue.from(cached_posts_json) ) # => '{"success":true,"total_count":42,"posts":[{"id":1,...},...]}' (no double-encoding) end end ``` -------------------------------- ### has_many Association Source: https://context7.com/yosiat/panko_serializer/llms.txt Embed an array association. Specify the serializer for each element using `each_serializer:` or `serializer:`. The `name:` option can be used to alias the JSON key. ```APIDOC ## `has_many` — Serialize a Collection Association Embed an array association. Pass `each_serializer:` (or `serializer:`) to specify the serializer for each element. ```ruby class CommentSerializer < Panko::Serializer attributes :id, :body, :created_at end class PostSerializer < Panko::Serializer attributes :id, :title has_many :comments, each_serializer: CommentSerializer # Inferred: looks for `TagSerializer` has_many :tags # Aliased: `state_transitions` becomes `history` in JSON has_many :state_transitions, each_serializer: TransitionSerializer, name: :history end PostSerializer.new.serialize_to_json(Post.includes(:comments, :tags, :state_transitions).find(1)) # => '{"id":1,"title":"Hello","comments":[{"id":10,"body":"Great!","created_at":"..."}],"tags":[...],"history":[...]}' ``` ``` -------------------------------- ### Conditionally Omit Fields with Panko::Serializer::SKIP Source: https://context7.com/yosiat/panko_serializer/llms.txt Return Panko::Serializer::SKIP from a method attribute to omit that key entirely from the JSON output, instead of serializing it as null. This is useful for fields that should not be present when blank. ```ruby class ProfileSerializer < Panko::Serializer attributes :id, :username, :bio, :phone_number def phone_number # Omit the key entirely when the value is blank return Panko::Serializer::SKIP if object.phone_number.blank? object.phone_number end end ProfileSerializer.new.serialize_to_json(User.find(1)) ``` -------------------------------- ### has_one Association Source: https://context7.com/yosiat/panko_serializer/llms.txt Embed a `has_one` (or `belongs_to`) association using a dedicated serializer. Panko can infer the serializer or you can specify it explicitly. Use `name:` to alias the JSON key. ```APIDOC ## `has_one` — Serialize a Single Association Embed a `has_one` (or `belongs_to`) association using a dedicated serializer. Pass `serializer:` explicitly or let Panko infer it from the association name. Use `name:` to alias the JSON key. ```ruby class AuthorSerializer < Panko::Serializer attributes :id, :name, :email end class ArticleSerializer < Panko::Serializer attributes :id, :title # Explicit serializer has_one :author, serializer: AuthorSerializer # Inferred — looks for `CommentSerializer` has_one :featured_comment # Aliased key: `editor` association becomes `reviewed_by` in JSON has_one :editor, serializer: AuthorSerializer, name: :reviewed_by end ArticleSerializer.new.serialize_to_json(Article.includes(:author, :featured_comment, :editor).first) # => '{"id":1,"title":"Panko Tips","author":{"id":3,"name":"Alice","email":"alice@example.com"},"featured_comment":{...},"reviewed_by":{...}}' ``` ``` -------------------------------- ### Wrap Cached JSON with Panko::JsonValue Source: https://github.com/yosiat/panko_serializer/blob/master/docs/response-bag.md Integrate Panko::JsonValue to wrap cached JSON strings when serializing collections. This ensures that cached data is correctly handled within a Panko::Response. ```ruby class PostsController < ApplicationController def index posts = Cache.get("/posts") render json: Panko::Response.new( success: true, total_count: posts.count, posts: Panko::JsonValue.from(posts) ) end end ``` -------------------------------- ### Infer Serializer for Associations in Panko Source: https://github.com/yosiat/panko_serializer/blob/master/docs/associations.md Panko can infer the serializer for an association by looking for a class named after the relationship (singularized and camelized) with a 'Serializer' suffix. This avoids explicit serializer declarations. ```ruby class PostSerializer < Panko::Serializer attributes :title, :body has_one :author has_many :comments end ``` -------------------------------- ### Apply Nested Filters to Associations in Panko Source: https://github.com/yosiat/panko_serializer/blob/master/docs/associations.md Filter attributes of associated objects using the `only` option within `Panko::ArraySerializer`. Specify attributes for the main instance and nested attributes for associations like `author` and `comments`. ```ruby posts = Post.all Panko::ArraySerializer.new(posts, each_serializer: PostSerializer, only: { instance: [:title, :body, :author, :comments], author: [:id], comments: [:id], }) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.