Class: TocDoc::Resource

Inherits:
Object
  • Object
show all
Defined in:
lib/toc_doc/models/resource.rb

Overview

A lightweight wrapper providing dot-notation access to response fields. Backed by a Hash, with +method_missing+ for attribute access and +#to_h+ for round-tripping back to a plain Hash.

Unlike Sawyer, TocDoc does not use hypermedia relations, so this wrapper intentionally stays minimal.

Examples:

resource = TocDoc::Resource.new('date' => '2026-02-28', 'slots' => [])
resource.date   #=> "2026-02-28"
resource[:date] #=> "2026-02-28"
resource.to_h   #=> { "date" => "2026-02-28", "slots" => [] }

Direct Known Subclasses

Agenda, Availability, Place, Profile, Speciality, VisitMotive

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attrs = {}) ⇒ Resource

Returns a new instance of Resource.

Parameters:

  • attrs (Hash) (defaults to: {})

    the raw attribute hash (string or symbol keys)



56
57
58
# File 'lib/toc_doc/models/resource.rb', line 56

def initialize(attrs = {})
  @attrs = self.class.normalize_attrs(attrs)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *_args) ⇒ Object

Provides dot-notation access to response fields.

On first access, defines a singleton method so that subsequent calls bypass +method_missing+ entirely. The defined method reads live from +@attrs+, so mutations via +[]=+ are always reflected.

Parameters:

  • method_name (Symbol)

    the method name

Returns:

  • (Object)

    the attribute value

Raises:

  • (NoMethodError)

    when the key does not exist



136
137
138
139
140
141
142
143
144
# File 'lib/toc_doc/models/resource.rb', line 136

def method_missing(method_name, *_args)
  key = method_name.to_s
  if @attrs.key?(key)
    define_singleton_method(key) { @attrs[key] }
    @attrs[key]
  else
    super
  end
end

Instance Attribute Details

#attrsObject (readonly)

Returns the value of attribute attrs.



19
20
21
# File 'lib/toc_doc/models/resource.rb', line 19

def attrs
  @attrs
end

Class Method Details

.main_attrs(*keys) ⇒ Array<String>?

Declares which attribute keys are shown in +#inspect+. When called with arguments, sets the list for this class. When called with no arguments, returns the list (or +nil+ if unset), walking the ancestor chain so subclasses inherit the declaration.

Subclasses that never call +main_attrs+ fall back to showing all attrs.

Examples:

main_attrs :id, :name, :slug

Parameters:

  • keys (Array<Symbol, String>)

Returns:

  • (Array<String>, nil)


44
45
46
47
48
49
50
51
52
# File 'lib/toc_doc/models/resource.rb', line 44

def main_attrs(*keys)
  if keys.empty?
    ancestor = ancestors.find { |a| a.instance_variable_defined?(:@main_attrs) }
    ancestor&.instance_variable_get(:@main_attrs)
  else
    inherited = superclass.respond_to?(:main_attrs) ? (superclass.main_attrs || []) : []
    @main_attrs = (inherited + keys.map(&:to_s)).uniq
  end
end

.normalize_attrs(attrs) ⇒ Hash{String => Object}

Normalises a raw attribute hash to string keys, mirroring what #initialize does internally. Useful in class-level factory methods that need to inspect attrs before wrapping them in a Resource instance.

Parameters:

  • attrs (Hash)

    raw hash with string or symbol keys

Returns:

  • (Hash{String => Object})


28
29
30
# File 'lib/toc_doc/models/resource.rb', line 28

def normalize_attrs(attrs)
  attrs.transform_keys(&:to_s)
end

Instance Method Details

#==(other) ⇒ Boolean

Equality comparison.

Two TocDoc::Resource instances are equal when their attribute hashes match. A TocDoc::Resource is also equal to a plain +Hash+ with equivalent keys.

Parameters:

Returns:

  • (Boolean)


103
104
105
106
107
108
109
# File 'lib/toc_doc/models/resource.rb', line 103

def ==(other)
  case other
  when Resource then @attrs == other.to_h
  when Hash     then @attrs == self.class.normalize_attrs(other)
  else false
  end
end

#[](key) ⇒ Object?

Read an attribute by name.

Examples:

resource[:date] #=> "2026-02-28"

Parameters:

  • key (String, Symbol)

    attribute name

Returns:

  • (Object, nil)

    the attribute value, or +nil+ if not present



67
68
69
# File 'lib/toc_doc/models/resource.rb', line 67

def [](key)
  @attrs[key.to_s]
end

#[]=(key, value) ⇒ Object

Write an attribute by name.

Parameters:

  • key (String, Symbol)

    attribute name

  • value (Object)

    the value to set

Returns:

  • (Object)

    the value



76
77
78
# File 'lib/toc_doc/models/resource.rb', line 76

def []=(key, value)
  @attrs[key.to_s] = value
end

#attribute_namesArray<String>

Returns the list of attribute names present on this resource.

Examples:

resource = TocDoc::Resource.new('date' => '2026-02-28', 'slots' => [])
resource.attribute_names #=> ["date", "slots"]

Returns:

  • (Array<String>)

    attribute names as strings



123
124
125
# File 'lib/toc_doc/models/resource.rb', line 123

def attribute_names
  @attrs.keys
end

#inspectString

Returns a human-readable representation of the resource showing only the declared main_attrs (or all attrs when none are declared).

Returns:

  • (String)


150
151
152
153
154
155
156
# File 'lib/toc_doc/models/resource.rb', line 150

def inspect
  pairs = inspect_hash.map do |key, value|
    "@#{key}=#{value.inspect}"
  end.join(', ')

  "#<#{self.class} #{pairs}>"
end

#to_hHash{String => Object}

Return a plain Hash representation with all nested TocDoc::Resource values recursively converted to plain Hashes.

Returns:

  • (Hash{String => Object})


84
85
86
# File 'lib/toc_doc/models/resource.rb', line 84

def to_h
  @attrs.transform_values { |v| deep_convert(v) }
end

#to_jsonString

Serialize the resource to a JSON string.

Parameters:

  • args (Array)

    forwarded to +Hash#to_json+

Returns:

  • (String)


92
93
94
# File 'lib/toc_doc/models/resource.rb', line 92

def to_json(*)
  to_h.to_json(*)
end