Class: Sawyer::Resource

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/sawyer/resource.rb

Constant Summary collapse

SPECIAL_METHODS =
Set.new(%w(agent rels fields))
ATTR_SETTER =
'='.freeze
ATTR_PREDICATE =
'?'.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(agent, data = {}) ⇒ Resource

Initializes a Resource with the given data.

agent - The Sawyer::Agent that made the API request. data - Hash of key/value properties.


12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/sawyer/resource.rb', line 12

def initialize(agent, data = {})
  @_agent  = agent
  data, links = agent.parse_links(data)
  @_rels = Relation.from_links(agent, links)
  @_fields = Set.new
  @_metaclass = (class << self; self; end)
  @attrs = {}
  data.each do |key, value|
    @_fields << key
    @attrs[key.to_sym] = process_value(value)
  end
  @_metaclass.send(:attr_accessor, *data.keys)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args) ⇒ Object

Provides access to a resource's attributes.


76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/sawyer/resource.rb', line 76

def method_missing(method, *args)
  attr_name, suffix = method.to_s.scan(/([a-z0-9\_]+)(\?|\=)?$/i).first
  if suffix == ATTR_SETTER
    @_metaclass.send(:attr_accessor, attr_name)
    @_fields << attr_name.to_sym
    send(method, args.first)
  elsif attr_name && @_fields.include?(attr_name.to_sym)
    value = @attrs[attr_name.to_sym]
    case suffix
    when nil
      @_metaclass.send(:attr_accessor, attr_name)
      value
    when ATTR_PREDICATE then !!value
    end
  elsif suffix.nil? && SPECIAL_METHODS.include?(attr_name)
    instance_variable_get "@_#{attr_name}"
  elsif attr_name && !@_fields.include?(attr_name.to_sym)
    nil
  else
    super
  end
end

Instance Attribute Details

#_agentObject (readonly)

Returns the value of attribute _agent.


4
5
6
# File 'lib/sawyer/resource.rb', line 4

def _agent
  @_agent
end

#_fieldsObject (readonly)

Returns the value of attribute _fields.


4
5
6
# File 'lib/sawyer/resource.rb', line 4

def _fields
  @_fields
end

#_relsObject (readonly)

Returns the value of attribute _rels.


4
5
6
# File 'lib/sawyer/resource.rb', line 4

def _rels
  @_rels
end

#attrsObject (readonly)

Returns the value of attribute attrs.


5
6
7
# File 'lib/sawyer/resource.rb', line 5

def attrs
  @attrs
end

Class Method Details

.attr_accessor(*attrs) ⇒ Object

Wire up accessor methods to pull from attrs


100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/sawyer/resource.rb', line 100

def self.attr_accessor(*attrs)
  attrs.each do |attribute|
    class_eval do
      define_method attribute do
        @attrs[attribute.to_sym]
      end

      define_method "#{attribute}=" do |value|
        @attrs[attribute.to_sym] = value
      end

      define_method "#{attribute}?" do
        !!@attrs[attribute.to_sym]
      end
    end
  end
end

Instance Method Details

#[](method) ⇒ Object

Allow fields to be retrieved via Hash notation

method - key name

Returns the value from attrs if exists


54
55
56
57
58
# File 'lib/sawyer/resource.rb', line 54

def [](method)
  send(method.to_sym)
rescue NoMethodError
  nil
end

#[]=(method, value) ⇒ Object

Allow fields to be set via Hash notation

method - key name value - value to set for the attr key

Returns - value


66
67
68
69
70
# File 'lib/sawyer/resource.rb', line 66

def []=(method, value)
  send("#{method}=", value)
rescue NoMethodError
  nil
end

#each(&block) ⇒ Object


122
123
124
# File 'lib/sawyer/resource.rb', line 122

def each(&block)
  @attrs.each(&block)
end

#inspectObject


118
119
120
# File 'lib/sawyer/resource.rb', line 118

def inspect
  to_attrs.respond_to?(:pretty_inspect) ? to_attrs.pretty_inspect : to_attrs.inspect
end

#key?(key) ⇒ Boolean

Checks to see if the given key is in this resource.

key - A Symbol key.

Returns true if the key exists, or false.

Returns:

  • (Boolean)

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

def key?(key)
  @_fields.include? key
end

#marshal_dumpObject


146
147
148
# File 'lib/sawyer/resource.rb', line 146

def marshal_dump
  [@attrs, @_fields, @_rels]
end

#marshal_load(dumped) ⇒ Object


150
151
152
153
# File 'lib/sawyer/resource.rb', line 150

def marshal_load(dumped)
  @attrs, @_fields, @_rels = *dumped.shift(3)
  @_metaclass = (class << self; self; end)
end

#process_value(value) ⇒ Object

Processes an individual value of this resource. Hashes get exploded into another Resource, and Arrays get their values processed too.

value - An Object value of a Resource's data.

Returns an Object to set as the value of a Resource key.


32
33
34
35
36
37
38
# File 'lib/sawyer/resource.rb', line 32

def process_value(value)
  case value
  when Hash  then self.class.new(@_agent, value)
  when Array then value.map { |v| process_value(v) }
  else value
  end
end

#to_attrsObject Also known as: to_hash, to_h


131
132
133
134
135
136
137
138
139
140
141
# File 'lib/sawyer/resource.rb', line 131

def to_attrs
  hash = self.attrs.clone
  hash.keys.each do |k|
    if hash[k].is_a?(Sawyer::Resource)
      hash[k] = hash[k].to_attrs
    elsif hash[k].is_a?(Array) && hash[k].all?{|el| el.is_a?(Sawyer::Resource)}
      hash[k] = hash[k].collect{|el| el.to_attrs}
    end
  end
  hash
end

#to_yaml_propertiesObject

private


127
128
129
# File 'lib/sawyer/resource.rb', line 127

def to_yaml_properties
  [:@attrs, :@_fields, :@_rels]
end