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