Blueprinter Documentation

repository·main·Indexed 23 days ago

https://github.com/procore-oss/blueprinter

A high-performance JSON Object Presenter for Ruby that serializes business objects into JSON using a view-based approach. Designed as a performant alternative to JBuilder and ActiveModelSerializers, Blueprinter allows developers to define blueprints with fields, associations, and multiple views to transform Ruby objects into hashes or JSON strings.

Tokens
6.9K
Snippets
30
Records
48
Agent score
77%

What's inside Blueprinter

  1. What is Blueprinter

    main
    Blueprinter is a JSON Object Presenter for Ruby designed to transform business objects into simple hashes and serialize them to JSON. It is intended to be a simple, direct, and performant alternative to other Ruby serializers like JBuilder or ActiveModelSerializers, particularly within Rails applications. A core concept of Blueprinter is the use of views, which allow you to predefine different output formats for the same data depending on the context.
  2. Transform view output with `Blueprinter::Transformer`

    main

    Transformers allow you to process the resulting hash of a view before it is serialized. Create a class inheriting from Blueprinter::Transformer and implement the transform(hash, object, options) method. Transformers can be applied globally, per-blueprint, or per-view.

    class DynamicFieldTransformer < Blueprinter::Transformer
      def transform(hash, object, _options)
        hash.merge!(object.dynamic_fields)
      end
    end
    
    class UserBlueprint < Blueprinter::Base
      fields :first_name, :last_name
      transform DynamicFieldTransformer
    end
  3. Extend Blueprinter with Hooks

    main

    The extension system allows you to intercept the rendering process. Currently, the pre_render hook is available, which allows you to modify or replace the object before serialization begins. Extensions are executed in the order they are added to Blueprinter.configure.extensions.

    class ObfuscateNameExtension < Blueprinter::Extension
      def pre_render(object, blueprint, view, options)
        return object unless object.respond_to?(:name)
    
        modified_object = object.dup
        modified_object.name = ObsfuscateName.call(modified_object.name)
    
        modified_object
      end
    end
    
    Blueprinter.configure do |config|
      config.extensions << ObfuscateNameExtension.new
    end
  4. Define and use multiple Views

    main

    Views allow you to define different output shapes for the same blueprint. You can use view :name do ... end to define a view and include_view :other_view to compose views by inheriting fields from another.

    class UserBlueprint < Blueprinter::Base
      identifier :uuid
      field :email, name: :login
    
      view :normal do
        fields :first_name, :last_name
      end
    
      view :extended do
        include_view :normal
        field :address
        association :projects
      end
    end
    
    # Usage
    puts UserBlueprint.render(user, view: :extended)
  5. Define associations and pass options

    main

    Associations allow you to include related objects. You can specify the blueprint to use for the association and pass static options or a Proc to derive options from the parent object at runtime.

    class DriverBlueprint < Blueprinter::Base
      identifier :uuid
    
      view :normal do
        fields :first_name, :last_name
        # Passing options via a Proc to derive them from the parent object
        association :vehicles, 
                    blueprint: VehicleBlueprint, 
                    options: ->(driver) { { trim: driver.preferred_trim } }
      end
    end
  6. How identifiers work in Blueprinter

    main

    An identifier specifies the field or method used as the object's unique ID. Identifiers have two unique properties:

    1. They are always rendered and are considered their own view (:identifier).
    2. They are always sorted first in the output JSON.

    If you do not want this behavior, define the ID as a regular field instead.

    class UserBlueprint < Blueprinter::Base
      identifier :uuid
    end
  7. Basic Usage: Serialize an object with a Blueprint

    main

    To serialize an object, create a class inheriting from Blueprinter::Base. Use identifier to specify the unique ID field and fields to list the attributes to be included. Call .render(object) on the blueprint class to get a JSON string.

    class UserBlueprint < Blueprinter::Base
      identifier :uuid
    
      fields :first_name, :last_name, :email
    end
    
    puts UserBlueprint.render(user) # Output is a JSON string
  8. Install Blueprinter

    main

    To install Blueprinter, add it to your application's Gemfile:

    gem 'blueprinter'

    Then run bundle in your terminal. Alternatively, you can install it directly using gem install blueprinter.

    Note: If you are not using Rails or the Oj gem, ensure you have require 'json' in your project.

  9. Handle empty associations with default values

    main
    Blueprinter's AssociationExtractor supports providing fallback values for associations. You can use the :default or :default_if keys within the association options. If the extracted value meets the condition specified by :default_if, the extractor will return the value specified in :default. If :default is not explicitly provided, it falls back to the global Blueprinter.configuration.association_default.
  10. Configure Deprecation reporting levels

    main

    You can control how Blueprinter reports deprecated functionality using the deprecations configuration key. Options are:

    • :stderr (Default): Writes to stderr.
    • :raise: Raises a Blueprinter::BlueprinterError.
    • :silence: Silences all deprecation notices.
    Blueprinter.configure do |config|
      config.deprecations = :raise
    end
  11. Sort fields by definition order

    main

    By default, Blueprinter sorts JSON keys alphabetically. To preserve the order in which fields are defined in your blueprint, configure sort_fields_by = :definition.

    Blueprinter.configure do |config|
      config.sort_fields_by = :definition
    end
  12. Configure Yajl-ruby as the JSON generator

    main

    To use yajl-ruby instead of the default JSON or Oj generators, configure the generator and the method used for encoding.

    _Note: If you are using yajl-ruby via its JSON compatibility API (require 'yajl/json_gem'), JSON.generate is already patched to use Yajl::Encoder.encode, so manual configuration may not be necessary.

    require 'yajl' # you can skip this if yajl has already been required.
    
    Blueprinter.configure do |config|
      config.generator = Yajl::Encoder # default is JSON
      config.method = :encode # default is generate
    end