Class: Halchemy::HalResource

Inherits:
Resource
  • Object
show all
Defined in:
lib/halchemy/resource.rb

Overview

The HalResource, like Resource, is also a Hash that adds functionality to work with the link relations in a HAL Resource.

Instance Attribute Summary

Attributes inherited from Resource

#_halchemy

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ HalResource

Returns a new instance of HalResource.

Raises:

  • (ArgumentError)


44
45
46
47
# File 'lib/halchemy/resource.rb', line 44

def initialize(*args)
  super
  raise ArgumentError, "Not a WELL-formed HAL resource" unless HalResource.hal?(self)
end

Class Method Details

.from_hash(json) ⇒ Object

Raises:

  • (ArgumentError)


49
50
51
52
53
54
55
# File 'lib/halchemy/resource.rb', line 49

def self.from_hash(json)
  obj = allocate
  obj.merge!(json) if json.is_a?(Hash)
  raise ArgumentError, "Not a well-FORMED HAL resource" unless HalResource.hal?(obj)

  obj
end

.hal?(hash) ⇒ boolean

Parameters:

  • hash (Hash)

Returns:

  • (boolean)


30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/halchemy/resource.rb', line 30

def self.hal?(hash)
  return false unless hash.is_a?(Hash)

  links = hash["_links"]
  embedded = hash["_embedded"]

  return false unless links.is_a?(Hash)
  return false unless links["self"].is_a?(Hash)
  return false unless links["self"]["href"].is_a?(String)
  return false if embedded && !embedded.is_a?(Hash)

  true
end

Instance Method Details

#collection(field) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/halchemy/resource.rb', line 84

def collection(field)
  raise_for_syntax_error(field)

  Enumerator.new do |y|
    self[field].each do |item|
      unless Halchemy::HalResource.hal?(item)
        raise TypeError, "The '#{field}' collection contains non-HAL formatted objects"
      end

      y.yield Halchemy::HalResource.from_hash(item)
    end
  end
end

#embedded(rel_name, expect: nil) ⇒ Halchemy::HalResource+

Parameters:

  • rel_name (string)
  • expect (Symbol, nil) (defaults to: nil)

Returns:

Raises:

  • (KeyError)


101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/halchemy/resource.rb', line 101

def embedded(rel_name, expect: nil)
  val = dig("_embedded", rel_name)
  raise KeyError, "No embedded resource found for rel '#{rel_name}'" if val.nil?

  if expect == Multiplicity::MANY
    raise TypeError, "Expected array for rel '#{rel_name}', got #{val.class}" unless val.is_a?(Array)

    return val.map { |item| HalResource.from_hash(item) }
  elsif expect == Multiplicity::ONE
    raise TypeError, "Expected object for rel '#{rel_name}', got #{val.class}" unless val.is_a?(Hash)

    return HalResource.from_hash(val)
  end

  if val.is_a?(Array)
    val.map { |item| HalResource.from_hash(item) }
  elsif val.is_a?(Hash)
    HalResource.from_hash(val)
  else
    raise TypeError, "Invalid embedded value for rel '#{rel_name}': expected object or array, got #{val.class}"
  end
end

#embedded_many(rel_name) ⇒ Object

Raises:

  • (TypeError)


124
125
126
127
128
129
# File 'lib/halchemy/resource.rb', line 124

def embedded_many(rel_name)
  result = embedded(rel_name, expect: Multiplicity::MANY)
  raise TypeError, "Expected array for embedded '#{rel_name}', got #{result.class}" unless result.is_a?(Array)

  result
end

#embedded_one(rel_name) ⇒ Object

Raises:

  • (TypeError)


131
132
133
134
135
136
# File 'lib/halchemy/resource.rb', line 131

def embedded_one(rel_name)
  result = embedded(rel_name, expect: Multiplicity::ONE)
  raise TypeError, "Expected object for rel '#{rel_name}', got #{result.class}" unless result.is_a?(Hash)

  result
end

#embedded_rel?(rel_name) ⇒ Boolean

Returns:

  • (Boolean)


69
70
71
# File 'lib/halchemy/resource.rb', line 69

def embedded_rel?(rel_name)
  self["_embedded"].key?(rel_name)
end

#embedded_relsObject



73
74
75
# File 'lib/halchemy/resource.rb', line 73

def embedded_rels
  self["_embedded"]&.keys || []
end


65
66
67
# File 'lib/halchemy/resource.rb', line 65

def links
  self["_links"].keys ||= []
end

#raise_for_syntax_error(field) ⇒ Object

Raises:

  • (TypeError)


77
78
79
80
81
82
# File 'lib/halchemy/resource.rb', line 77

def raise_for_syntax_error(field)
  unless keys.include?(field)
    raise KeyError, "Field '#{field}' does not exist, so cannot be iterated as a collection"
  end
  raise TypeError, "Field '#{field}' is not a collection" unless self[field].is_a?(Array)
end

#rel?(rel_name) ⇒ Boolean

Returns:

  • (Boolean)


61
62
63
# File 'lib/halchemy/resource.rb', line 61

def rel?(rel_name)
  self["_links"].key?(rel_name)
end

#to_sObject



57
58
59
# File 'lib/halchemy/resource.rb', line 57

def to_s
  "<HalResource href='#{dig("_links", "self", "href")}' >"
end