class Jsonite

Jsonite

A tiny, HAL-compliant JSON presenter.

tools.ietf.org/html/draft-kelly-json-hal-05

Constants

VERSION

Attributes

defaults[R]
resource[R]

Public Class Methods

embed(rel, options = {}) click to toggle source

Defines an embedded resource.

class TodoPresenter < Jsonite
  property :description
end
class UserPresenter < Jsonite
  embed :todos, with: TodoPresenter
end
# {
#   "_embedded": {
#     "todos": [
#       {
#         "description": "Buy milk"
#       }
#     ]
#   }
# }

Configuration options:

  • :with - A specified presenter. Required if a handler isn't present.

  • :ignore_nil - Ignore `nil`.

# File lib/jsonite.rb, line 139
def embed rel, options = {}, &handler
  options.fetch :with unless handler
  embedded[rel.to_s] = { handler: handler }.merge options
end
embedded() click to toggle source
# File lib/jsonite.rb, line 144
def embedded
  @embedded ||= {}
end
let(name, &handler) click to toggle source

Defines a memoized “virtual” method on the resource.

class UserPresenter < Jsonite
  let(:full_name) { "#{first_name} #{last_name}" }
  property :full_name
end
# {
#   "full_name": "Stephen Celis"
# }
# File lib/jsonite.rb, line 157
def let name, &handler
  lets[name.to_s] = handler
end
lets() click to toggle source
# File lib/jsonite.rb, line 161
def lets
  @lets ||= {}
end
new(resource, defaults = {}) click to toggle source

Initializes a new presenter instance with the given resource.

Default options are passed to as_json during presentation.

# File lib/jsonite.rb, line 181
def initialize resource, defaults = {}
  @resource, @defaults = resource, defaults
end
present(resource, options = {}) click to toggle source

Presents a resource (or array of resources).

class UserPresenter < Jsonite
  property :email
end
users = User.all
UserPresenter.present(users.first)
# => {"email"=>"stephen@example.com"}
UserPresenter.present(users)
# => [{"email"=>"stephen@example.com"}, ...]

Configuration options:

  • :root - A root key to wrap the resource with.

  • :with - A specified presenter (defaults to `self`).

All other options are passed along to #present.

# File lib/jsonite.rb, line 31
def present resource, options = {}
  presenter = options.delete(:with) { self }

  presented = if resource.is_a? Jsonite
    resource.present options
  elsif resource.respond_to?(:to_ary)
    resource.to_ary.map do |member|
      presenter.new(member).present options.merge root: nil
    end
  else
    presenter.new(resource).present options.merge root: nil
  end

  root = options.fetch(:root) { Helper.resource_name(resource) }
  root ? { root => presented } : presented
end
properties(*properties) click to toggle source
# File lib/jsonite.rb, line 66
def properties *properties
  @properties ||= {}
  properties.map(&method(:property)) if properties.present?
  @properties
end
property(name, options = {}) click to toggle source

Defines a property to be exposed during presentation.

class UserPresenter < Jsonite
  property :email
end
# {
#   "email": "stephen@example.com"
# }

Configuration options:

  • :with - A specified presenter. Ignored when a handler is present. Useful when you want to embed a resource as a property (rather than in the _embedded node).

  • :ignore_nil - Ignore `nil`.

# File lib/jsonite.rb, line 62
def property name, options = {}, &handler
  properties[name.to_s] = { handler: handler }.merge options
end

Private Class Methods

inherited(presenter) click to toggle source
# File lib/jsonite.rb, line 167
def inherited presenter
  presenter.properties.update properties
  presenter.links.update links
  presenter.embedded.update embedded
  presenter.lets.update lets
end

Public Instance Methods

as_json(options = {}) click to toggle source

Returns a JSON-ready representation (Hash) of the resource.

Options:

  • :root

# File lib/jsonite.rb, line 210
def as_json options = {}
  present(options).as_json options
end
present(options = {}) click to toggle source

Returns a raw representation (Hash) of the resource.

Options:

  • :context - A context to pass a presenter instance while rendering properties, links, and embedded resources.

# File lib/jsonite.rb, line 190
def present options = {}
  options = defaults.merge options

  context = options.delete :context
  proxied = LetsProxy.new resource, context, self.class.lets

  presented = properties proxied, context
  _links = links proxied, context
  presented['_links'] = _links if _links.present?
  _embedded = embedded proxied, context
  presented['_embedded'] = _embedded if _embedded.present?

  root = options.fetch(:root) { Helper.resource_name(resource) }
  root ? { root => presented } : presented
end

Private Instance Methods

embedded(rsrc, context = nil) click to toggle source
# File lib/jsonite.rb, line 231
def embedded rsrc, context = nil
  self.class.embedded.each_with_object({}) do |(name, options), embeds|
    catch(:ignore) { embeds[name] = fetch name, rsrc, context, options }
  end
end
fetch(name, rsrc, context, options) click to toggle source
# File lib/jsonite.rb, line 237
def fetch name, rsrc, context, options
  value = if options[:handler]
    rsrc.instance_exec context, &options[:handler]
  else
    rsrc.__send__ name
  end

  throw :ignore if options[:ignore_nil] && value.nil?

  if options[:with] && !value.nil?
    return options[:with].present value, context: context, root: nil
  end

  value
end
properties(rsrc, context = nil) click to toggle source
# File lib/jsonite.rb, line 216
def properties rsrc, context = nil
  self.class.properties.each_with_object({}) do |(name, options), props|
    catch(:ignore) { props[name] = fetch name, rsrc, context, options }
  end
end