Class: Blueprinter::Base

Inherits:
Object
  • Object
show all
Extended by:
Reflection
Includes:
BaseHelpers
Defined in:
lib/blueprinter/base.rb

Class Method Summary collapse

Methods included from Reflection

reflections

Methods included from BaseHelpers

included

Class Method Details

.association(method, options = {}) {|object, options| ... } ⇒ Association

Specify an associated object to be included for serialization. Takes a required method and an option.

Examples:

Specifying an association

class UserBlueprint < Blueprinter::Base
  # code
  association :vehicles, view: :extended, blueprint: VehiclesBlueprint
  # code
end

Passing a block to be evaluated as the value.

class UserBlueprint < Blueprinter::Base
  association :vehicles, blueprint: VehiclesBlueprint do |user, opts|
    user.vehicles + opts[:additional_vehicles]
  end
end

Parameters:

  • method (Symbol)

    the association name

  • options (Hash) (defaults to: {})

    options to overide defaults.

Options Hash (options):

  • :blueprint (Symbol)

    Required. Use this to specify the blueprint to use for the associated object.

  • :name (Symbol)

    Use this to rename the association in the JSON output.

  • :view (Symbol)

    Specify the view to use or fall back to to the :default view.

Yields:

  • (object, options)

    The object and the options passed to render are also yielded to the block.

Returns:

Raises:



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/blueprinter/base.rb', line 151

def self.association(method, options = {}, &block)
  raise ArgumentError, ':blueprint must be provided when defining an association' unless options[:blueprint]

  current_view << Association.new(
    method: method,
    name: options.fetch(:name) { method },
    extractor: options.fetch(:extractor) { AssociationExtractor.new },
    blueprint: options.fetch(:blueprint),
    parent_blueprint: self,
    view: options.fetch(:view, :default),
    options: options.except(
      :name,
      :extractor,
      :blueprint,
      :view
    ).merge(block: block)
  )
end

.exclude(field_name) ⇒ Array<Symbol>

Exclude a field that was mixed into the current view.

Examples:

Excluding a field from being included into the current view.

view :normal do
  fields :position, :company
end
view :special do
  include_view :normal
  field :birthday
  exclude :position
end
#=> [:company, :birthday]

Parameters:

  • field_name (Symbol)

    the field to exclude from the current view.

Returns:

  • (Array<Symbol>)

    an array of field names



378
379
380
# File 'lib/blueprinter/base.rb', line 378

def self.exclude(field_name)
  current_view.exclude_field(field_name)
end

.excludes(*field_names) ⇒ Array<Symbol>

When mixing multiple views under a single view, some fields may required to be excluded from current view

Examples:

Excluding mutiple fields from being included into the current view.

view :normal do
  fields :name,:address,:position,
        :company, :contact
end
view :special do
  include_view :normal
  fields :birthday,:joining_anniversary
  excludes :position,:address
end
=> [:name, :company, :contact, :birthday, :joining_anniversary]

Parameters:

  • the (Array<Symbol>)

    fields to exclude from the current view.

Returns:

  • (Array<Symbol>)

    an array of field names



401
402
403
# File 'lib/blueprinter/base.rb', line 401

def self.excludes(*field_names)
  current_view.exclude_fields(field_names)
end

.field(method, options = {}) {|object, options| ... } ⇒ Field

Specify a field or method name to be included for serialization. Takes a required method and an option.

Examples:

Specifying a user’s first_name to be serialized.

class UserBlueprint < Blueprinter::Base
  field :first_name
  # other code
end

Passing a block to be evaluated as the value.

class UserBlueprint < Blueprinter::Base
  field :full_name do |object, options|
    "options[:title_prefix] #{object.first_name} #{object.last_name}"
  end
  # other code
end

Passing an if proc and unless method.

class UserBlueprint < Blueprinter::Base
  def skip_first_name?(_field_name, user, options)
    user.first_name == options[:first_name]
  end

  field :first_name, unless: :skip_first_name?
  field :last_name, if: ->(_field_name, user, options) { user.first_name != options[:first_name] }
  # other code
end

Parameters:

  • method (Symbol)

    the field or method name you want to include for serialization.

  • options (Hash) (defaults to: {})

    options to overide defaults.

Options Hash (options):

  • :extractor (AssociationExtractor, BlockExtractor, HashExtractor, PublicSendExtractor)

    Kind of extractor to use. Either define your own or use Blueprinter’s premade extractors. The Default extractor is AutoExtractor

  • :name (Symbol)

    Use this to rename the method. Useful if if you want your JSON key named differently in the output than your object’s field or method name.

  • :datetime_format (String, Proc)

    Format Date or DateTime object If the option provided is a String, the object will be formatted with given strftime formatting. If this option is a Proc, the object will be formatted by calling the provided Proc on the Date/DateTime object.

  • :if (Symbol, Proc)

    Specifies a method, proc or string to call to determine if the field should be included (e.g. ‘if: :include_first_name?, or if: Proc.new { |_field_name, user, options| options == user }). The method, proc or string should return or evaluate to a true or false value.

  • :unless (Symbol, Proc)

    Specifies a method, proc or string to call to determine if the field should be included (e.g. ‘unless: :include_first_name?, or unless: Proc.new { |_field_name, user, options| options != user }). The method, proc or string should return or evaluate to a true or false value.

Yields:

  • (object, options)

    The object and the options passed to render are also yielded to the block.

Returns:

  • (Field)

    A Field object



111
112
113
114
115
116
117
118
119
# File 'lib/blueprinter/base.rb', line 111

def self.field(method, options = {}, &block)
  current_view << Field.new(
    method,
    options.fetch(:name) { method },
    options.fetch(:extractor) { Blueprinter.configuration.extractor_default.new },
    self,
    options.merge(block: block)
  )
end

.fields(*field_names) ⇒ Array<Symbol>

Specify one or more field/method names to be included for serialization. Takes at least one field or method names.

Examples:

Specifying a user’s first_name and last_name to be serialized.

class UserBlueprint < Blueprinter::Base
  fields :first_name, :last_name
  # other code
end

Parameters:

  • method (Symbol)

    the field or method name you want to include for serialization.

Returns:

  • (Array<Symbol>)

    an array of field names



273
274
275
276
277
# File 'lib/blueprinter/base.rb', line 273

def self.fields(*field_names)
  field_names.each do |field_name|
    field(field_name)
  end
end

.identifier(method, name: method, extractor: Blueprinter.configuration.extractor_default.new) {|object, options| ... } ⇒ Field

Specify a field or method name used as an identifier. Usually, this is something like :id

Note: identifiers are always rendered and considered their own view, similar to the :default view.

Examples:

Specifying a uuid as an identifier.

class UserBlueprint < Blueprinter::Base
  identifier :uuid
  # other code
end

Passing a block to be evaluated as the value.

class UserBlueprint < Blueprinter::Base
  identifier :uuid do |user, options|
    options[:current_user].anonymize(user.uuid)
  end
end

Parameters:

Yields:

  • (object, options)

    The object and the options passed to render are also yielded to the block.

    Kind of extractor to use. Either define your own or use Blueprinter’s premade extractors. Defaults to AutoExtractor

Returns:

  • (Field)

    A Field object



46
47
48
49
50
51
52
53
54
# File 'lib/blueprinter/base.rb', line 46

def self.identifier(method, name: method, extractor: Blueprinter.configuration.extractor_default.new, &block)
  view_collection[:identifier] << Field.new(
    method,
    name,
    extractor,
    self,
    block: block
  )
end

.include_view(view_name) ⇒ Array<Symbol>

Specify another view that should be mixed into the current view.

Examples:

Including a normal view into an extended view.

class UserBlueprint < Blueprinter::Base
  # other code...
  view :normal do
    fields :first_name, :last_name
  end
  view :extended do
    include_view :normal # include fields specified from above.
    field :description
  end
  #=> [:first_name, :last_name, :description]
end

Parameters:

  • view_name (Symbol)

    the view to mix into the current view.

Returns:

  • (Array<Symbol>)

    an array of view names.



332
333
334
# File 'lib/blueprinter/base.rb', line 332

def self.include_view(view_name)
  current_view.include_view(view_name)
end

.include_views(*view_names) ⇒ Array<Symbol>

Specify additional views that should be mixed into the current view.

@param view_name [Array<Symbol>] the views to mix into the current view.

Examples:

Including the normal and special views into an extended view.

class UserBlueprint < Blueprinter::Base
  # other code...
  view :normal do
    fields :first_name, :last_name
  end
  view :special do
    fields :birthday, :company
  end
  view :extended do
    include_views :normal, :special # include fields specified from above.
    field :description
  end
  #=> [:first_name, :last_name, :birthday, :company, :description]
end

Returns:

  • (Array<Symbol>)

    an array of view names.



358
359
360
# File 'lib/blueprinter/base.rb', line 358

def self.include_views(*view_names)
  current_view.include_views(view_names)
end

.prepare(object, view_name:, local_options:, root: nil, meta: nil) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This is the magic method that converts complex objects into a simple hash ready for JSON conversion.

Note: we accept view (public interface) that is in reality a view_name, so we rename it for clarity

Raises:



252
253
254
255
256
257
258
# File 'lib/blueprinter/base.rb', line 252

def self.prepare(object, view_name:, local_options:, root: nil, meta: nil)
  raise BlueprinterError, "View '#{view_name}' is not defined" unless view_collection.view? view_name

  object = Blueprinter.configuration.extensions.pre_render(object, self, view_name, local_options)
  data = prepare_data(object, view_name, local_options)
  prepend_root_and_meta(data, root, meta)
end

.render(object, options = {}) ⇒ String

Generates a JSON formatted String. Takes a required object and an optional view.

Examples:

Generating JSON with an extended view

post = Post.all
Blueprinter::Base.render post, view: :extended
# => "[{\"id\":1,\"title\":\"Hello\"},{\"id\":2,\"title\":\"My Day\"}]"

Parameters:

  • object (Object)

    the Object to serialize upon.

  • options (Hash) (defaults to: {})

    the options hash which requires a :view. Any additional key value pairs will be exposed during serialization.

Options Hash (options):

  • :view (Symbol)

    Defaults to :default. The view name that corresponds to the group of fields to be serialized.

  • :root (Symbol|String)

    Defaults to nil. Render the json/hash with a root key if provided.

  • :meta (Any)

    Defaults to nil. Render the json/hash with a meta attribute with provided value if both root and meta keys are provided in the options hash.

Returns:

  • (String)

    JSON formatted String



191
192
193
# File 'lib/blueprinter/base.rb', line 191

def self.render(object, options = {})
  jsonify(prepare_for_render(object, options))
end

.render_as_hash(object, options = {}) ⇒ Hash

Generates a hash. Takes a required object and an optional view.

Examples:

Generating a hash with an extended view

post = Post.all
Blueprinter::Base.render_as_hash post, view: :extended
# => [{id:1, title: Hello},{id:2, title: My Day}]

Parameters:

  • object (Object)

    the Object to serialize upon.

  • options (Hash) (defaults to: {})

    the options hash which requires a :view. Any additional key value pairs will be exposed during serialization.

Options Hash (options):

  • :view (Symbol)

    Defaults to :default. The view name that corresponds to the group of fields to be serialized.

  • :root (Symbol|String)

    Defaults to nil. Render the json/hash with a root key if provided.

  • :meta (Any)

    Defaults to nil. Render the json/hash with a meta attribute with provided value if both root and meta keys are provided in the options hash.

Returns:

  • (Hash)


216
217
218
# File 'lib/blueprinter/base.rb', line 216

def self.render_as_hash(object, options = {})
  prepare_for_render(object, options)
end

.render_as_json(object, options = {}) ⇒ Hash

Generates a JSONified hash. Takes a required object and an optional view.

Examples:

Generating a hash with an extended view

post = Post.all
Blueprinter::Base.render_as_json post, view: :extended
# => [{"id" => "1", "title" => "Hello"},{"id" => "2", "title" => "My Day"}]

Parameters:

  • object (Object)

    the Object to serialize upon.

  • options (Hash) (defaults to: {})

    the options hash which requires a :view. Any additional key value pairs will be exposed during serialization.

Options Hash (options):

  • :view (Symbol)

    Defaults to :default. The view name that corresponds to the group of fields to be serialized.

  • :root (Symbol|String)

    Defaults to nil. Render the json/hash with a root key if provided.

  • :meta (Any)

    Defaults to nil. Render the json/hash with a meta attribute with provided value if both root and meta keys are provided in the options hash.

Returns:

  • (Hash)


241
242
243
# File 'lib/blueprinter/base.rb', line 241

def self.render_as_json(object, options = {})
  prepare_for_render(object, options).as_json
end

.transform(transformer) ⇒ Array<Class>

Specify one transformer to be included for serialization. Takes a class which extends Blueprinter::Transformer

Examples:

Specifying a DynamicFieldTransformer transformer for including dynamic fields to be serialized.

class User
  def custom_columns
    self.dynamic_fields # which is an array of some columns
  end

  def custom_fields
    custom_columns.each_with_object({}) { |col,result| result[col] = self.send(col) }
  end
end

class UserBlueprint < Blueprinter::Base
  fields :first_name, :last_name
  transform DynamicFieldTransformer
  # other code
end

class DynamicFieldTransformer < Blueprinter::Transformer
  def transform(hash, object, options)
    hash.merge!(object.dynamic_fields)
  end
end

Parameters:

  • class

    name [Class] which implements the method transform to include for serialization.

Returns:

  • (Array<Class>)

    an array of transformers



310
311
312
# File 'lib/blueprinter/base.rb', line 310

def self.transform(transformer)
  current_view.add_transformer(transformer)
end

.view(view_name) ⇒ View

Specify a view and the fields it should have. It accepts a view name and a block. The block should specify the fields.

Examples:

Using views

view :extended do
  fields :position, :company
  include_view :normal
  exclude :first_name
end

Parameters:

  • view_name (Symbol)

    the view name

Yield Returns:

Returns:

  • (View)

    a Blueprinter::View object



420
421
422
423
424
425
# File 'lib/blueprinter/base.rb', line 420

def self.view(view_name)
  @current_view = view_collection[view_name]
  view_collection[:default].track_definition_order(view_name)
  yield
  @current_view = view_collection[:default]
end

.view?(view_name) ⇒ Boolean

Check whether or not a Blueprint supports the supplied view. It accepts a view name.

class ExampleBlueprint < Blueprinter::Base

view :custom do
end

end

ExampleBlueprint.view?(:custom) => true
ExampleBlueprint.view?(:doesnt_exist) => false

supported by this Blueprint.

Examples:

With the following Blueprint

Parameters:

  • view_name (Symbol)

    the view name

Returns:

  • (Boolean)

    a boolean value indicating if the view is



444
445
446
# File 'lib/blueprinter/base.rb', line 444

def self.view?(view_name)
  view_collection.view? view_name
end