class Onsi::Resource
The wrapper for generating a object
@author Maddie Schipper @since 1.0.0
Constants
- ATTRIBUTES_KEY
Root object attributes key
@private
- DATA_KEY
Root object data key
@private
- ID_KEY
Root object id key
@private
- INCLUDED_KEY
Root object included key
@private
- META_KEY
Metadata key
@private
- RELATIONSHIPS_KEY
Root object relationships key
@private
- TYPE_KEY
Root object type key
@private
Attributes
The includes for the object.
@return [Array<Onsi::Includes>]
The backing object.
@note MUST include Onsi::Model
@return [Any] The object to be rendered by the resource.
The version to render.
@return [Symbol]
Public Class Methods
Convert an object into a Onsi::Resource
@param resource [Onsi::Resource, Enumerable, ActiveRecord::Base] The
object to be converted. - If a Onsi::Resource is passed it will be directly returned. - If an Enumerable is passed #map will be called and .as_resource will be recursivly called for each object. - If any other object is passed it will be wrapped in a Onsi::Resource
@param version [Symbol] The version of the resource. `:v1`
@return [Onsi::Resource, Array<Onsi::Resource>]
# File lib/onsi/resource.rb, line 71 def as_resource(resource, version) case resource when Onsi::Resource resource when Onsi::Paginate::Result as_resource(resource.query, version) when Enumerable resource.map { |res| as_resource(res, version) } else Onsi::Resource.new(resource, version) end end
Create a new resouce.
@param object [Any] The resource backing object.
@param version [Symbol] The version to render. Can be nil. If nil is
passed the DEFAULT_API_VERSION will be used.
@note The object MUST be a single object that includes Onsi::Model
@note The includes MUST be an array of Onsi::Include objects.
@return [Onsi::Resource] The new resource
# File lib/onsi/resource.rb, line 152 def initialize(object, version = nil, includes: nil) @object = object @version = version || Model::DEFAULT_API_VERSION @includes = includes validate! end
Render a resource to JSON
@param resource (see .as_resource)
@param version [Symbol] The version to render as. `:v1`
@return [Hash] The rendered resource as a hash ready to be converted
to JSON.
# File lib/onsi/resource.rb, line 93 def render(resource, version) resources = as_resource(resource, version) {}.tap do |root| root[DATA_KEY] = resources.as_json included = all_included(resources) if included.any? root[INCLUDED_KEY] = included end root[META_KEY] = {}.tap do |meta| meta[:count] = resources.count if resources.respond_to?(:count) if resource.is_a?(Onsi::Paginate::Result) meta[:pagination] = resource.params end end end end
Private Class Methods
# File lib/onsi/resource.rb, line 112 def all_included(resources) Array(resources).map(&:flat_includes).flatten.uniq do |res| "#{res[TYPE_KEY]}-#{res[ID_KEY]}" end end
Public Instance Methods
Creates a raw JSON object.
@return [Hash]
# File lib/onsi/resource.rb, line 163 def as_json(_opts = {}) {}.tap do |root| root[TYPE_KEY] = type root[ID_KEY] = object_identifier root[ATTRIBUTES_KEY] = generate_attributes append_relationships(root) append_meta(root) append_includes(root) end end
Flat includes
@private
# File lib/onsi/resource.rb, line 186 def flat_includes rendered_includes.values.map { |root| root[DATA_KEY] }.flatten end
All rendered includes
@private
# File lib/onsi/resource.rb, line 178 def rendered_includes @rendered_includes ||= perform_render_includes end
Private Instance Methods
# File lib/onsi/resource.rb, line 224 def append_includes(root) includes = generate_includes return unless includes.any? root[RELATIONSHIPS_KEY] ||= {} root[RELATIONSHIPS_KEY].merge!(includes) end
# File lib/onsi/resource.rb, line 217 def append_meta(root) meta = generate_metadata return unless meta.any? root[META_KEY] = meta end
# File lib/onsi/resource.rb, line 210 def append_relationships(root) relationships = generate_relationships return unless relationships.any? root[RELATIONSHIPS_KEY] = relationships end
# File lib/onsi/resource.rb, line 232 def generate_attributes object.class.api_renderer(version, nil, for_render: true).render_attributes(object) end
# File lib/onsi/resource.rb, line 244 def generate_includes {}.tap do |root| rendered_includes.each do |key, values| included = values[DATA_KEY] case included when Array root[key] = {}.tap do |subobj| subobj[DATA_KEY] = included.map do |inc| { TYPE_KEY => inc[TYPE_KEY], ID_KEY => inc[ID_KEY] } end end when Hash root[key] = { DATA_KEY => { TYPE_KEY => included[TYPE_KEY], ID_KEY => included[ID_KEY] } } end end end end
# File lib/onsi/resource.rb, line 240 def generate_metadata object.class.api_renderer(version, nil, for_render: true).render_metadata(object) end
# File lib/onsi/resource.rb, line 236 def generate_relationships object.class.api_renderer(version, nil, for_render: true).render_relationships(object) end
# File lib/onsi/resource.rb, line 201 def object_identifier attr = object.class.api_renderer(version, nil, for_render: true).id_attr object.send(attr).to_s end
# File lib/onsi/resource.rb, line 265 def perform_render_includes included = includes&.load_included {}.tap do |root| Hash(included).each do |key, results| root[key.to_s] = {} root[key.to_s][DATA_KEY] = render_included(results) end end end
# File lib/onsi/resource.rb, line 275 def render_included(resources) Resource.as_resource(resources, version).as_json end
# File lib/onsi/resource.rb, line 206 def type object.class.api_renderer(version, nil, for_render: true).type || object.class.name.underscore end
# File lib/onsi/resource.rb, line 192 def validate! unless object.class.included_modules.include?(Onsi::Model) raise InvalidResourceError, "Trying to render a #{object.class.name}. But it doesn't include Onsi::Model" end if includes.present? && !includes.is_a?(Onsi::Includes) raise InvalidResourceError, "Included resources in #{self} is not a Onsi::Includes" end end