lib/onsi/resource.rb in onsi-0.8.0 vs lib/onsi/resource.rb in onsi-1.0.0

- old
+ new

@@ -1,20 +1,74 @@ +require_relative 'errors' + module Onsi + ## + # The wrapper for generating a object + # + # @author Maddie Schipper + # @since 1.0.0 class Resource - attr_reader :object, :version, :includes + ## + # Root object type key + # + # @private + TYPE_KEY = 'type'.freeze - TYPE_KEY = 'type'.freeze - ID_KEY = 'id'.freeze - ATTRIBUTES_KEY = 'attributes'.freeze + ## + # Root object id key + # + # @private + ID_KEY = 'id'.freeze + + ## + # Root object attributes key + # + # @private + ATTRIBUTES_KEY = 'attributes'.freeze + + ## + # Root object relationships key + # + # @private RELATIONSHIPS_KEY = 'relationships'.freeze - META_KEY = 'meta'.freeze - DATA_KEY = 'data'.freeze - INCLUDED_KEY = 'included'.freeze - class InvalidResourceError < StandardError; end + ## + # Root object meta key + # + # @private + META_KEY = 'meta'.freeze + ## + # Root object data key + # + # @private + DATA_KEY = 'data'.freeze + + ## + # Root object included key + # + # @private + INCLUDED_KEY = 'included'.freeze + + ## + # Raised if the resource or includes are invalid. + class InvalidResourceError < Onsi::Errors::BaseError; end + class << self + ## + # 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>] def as_resource(resource, version) case resource when Onsi::Resource resource when Enumerable @@ -22,10 +76,19 @@ else Onsi::Resource.new(resource, version) end 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. def render(resource, version) resources = as_resource(resource, version) {}.tap do |root| root[DATA_KEY] = resources.as_json included = all_included(resources) @@ -33,24 +96,63 @@ root[INCLUDED_KEY] = included end end end + private + def all_included(resources) Array(resources).map(&:flat_includes).flatten.uniq do |res| "#{res[TYPE_KEY]}-#{res[ID_KEY]}" end end end + ## + # The backing object. + # + # @note MUST include Onsi::Model + # + # @return [Any] The object to be rendered by the resource. + attr_reader :object + + ## + # The version to render. + # + # @return [Symbol] + attr_reader :version + + ## + # The includes for the object. + # + # @return [Array<Onsi::Includes>] + attr_reader :includes + + ## + # 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 def initialize(object, version = nil, includes: nil) @object = object @version = version || Model::DEFAULT_API_VERSION @includes = includes validate! end + ## + # Creates a raw JSON object. + # + # @return [Hash] def as_json(_opts = {}) {}.tap do |root| root[TYPE_KEY] = type root[ID_KEY] = object.id.to_s root[ATTRIBUTES_KEY] = generate_attributes @@ -58,13 +160,21 @@ append_meta(root) append_includes(root) end end + ## + # All rendered includes + # + # @private def rendered_includes @rendered_includes ||= perform_render_includes end + ## + # Flat includes + # + # @private def flat_includes rendered_includes.values.map { |root| root[DATA_KEY] }.flatten end private