lib/hyperclient/resource.rb in hyperclient-0.8.5 vs lib/hyperclient/resource.rb in hyperclient-0.8.6

- old
+ new

@@ -1,8 +1,19 @@ require 'forwardable' module Hyperclient + # Public: Exception that is raised when passing in invalid representation data + # for the resource. + class InvalidRepresentationError < ArgumentError + attr_reader :representation + + def initialize(error_description, representation) + super(error_description) + @representation = representation + end + end + # Public: Represents a resource from your API. Its responsability is to # ease the way you access its attributes, links and embedded resources. class Resource extend Forwardable @@ -27,12 +38,13 @@ # Public: Initializes a Resource. # # representation - The hash with the HAL representation of the Resource. # entry_point - The EntryPoint object to inject the configutation. def initialize(representation, entry_point, response = nil) - representation = representation ? representation.dup : {} + representation = validate(representation) links = representation['_links'] || {} + @_links = LinkCollection.new(links, links['curies'], entry_point) @_embedded = ResourceCollection.new(representation['_embedded'], entry_point) @_attributes = Attributes.new(representation) @_entry_point = entry_point @_response = response @@ -65,9 +77,24 @@ raise KeyError end end private + + # Internal: Ensures the received representation is a valid Hash-lookalike. + def validate(representation) + return {} unless representation + + if representation.respond_to?(:to_hash) + representation.to_hash.dup + else + raise InvalidRepresentationError.new( + "Invalid representation for resource (got #{representation.class}, expected Hash). " \ + "Is your web server returning JSON HAL data with a 'Content-Type: application/hal+json' header?", + representation + ) + end + end # Internal: Returns the self Link of the Resource. Used to handle the HTTP # methods. def _self_link @_links['self']