Class: RightApi::ResourceDetail

Inherits:
Object
  • Object
show all
Includes:
Helper
Defined in:
lib/right_api_client/resource_detail.rb

Overview

Takes the information returned from the API and converts it into instance methods

Constant Summary

Constants included from Helper

Helper::INCONSISTENT_RESOURCE_TYPES, Helper::INSTANCE_FACING_RESOURCES, Helper::RESOURCE_SPECIAL_ACTIONS

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Helper

#add_id_and_params_to_path, #api_methods, #define_instance_method, #fix_array_of_hashes, #get_and_delete_href_from_links, #get_associated_resources, #get_href_from_links, #get_singular, #has_id, #insert_in_path, #is_singular?, #simple_singularize

Constructor Details

#initialize(client, resource_type, href, hash) ⇒ ResourceDetail

ResourceDetail will MODIFY hash



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/right_api_client/resource_detail.rb', line 15

def initialize(client, resource_type, href, hash)
  @client = client
  @resource_type = resource_type
  @raw = hash.dup
  @attributes, @associations, @actions = Set.new, Set.new, Set.new
  @attributes_with_values = {}

  links = hash.delete('links') || []
  raw_actions = hash.delete('actions') || []

  # We have to delete the self href from the links because later we will
  # go through these links and add them in as methods
  self_hash = get_and_delete_href_from_links(links)
  if self_hash != nil
    hash['href'] = self_hash
  end

  # Add links to attributes set and create a method that returns the links
  attributes << :links
  define_instance_method(:links) { return links }

  # Follow the actions:
    # API doesn't tell us whether a resource action is a GET or a POST, but
    # they are all post so add them all as posts for now.
  raw_actions.each do |action|
    action_name = action['rel']
    # Add it to the actions set
    actions << action_name.to_sym

    define_instance_method(action_name.to_sym) do |*args|
      client.send(:do_post, "#{hash['href']}/#{action['rel']}", *args)
    end
  end

  # Follow the links to create methods
  get_associated_resources(client, links, associations)

  # Some resources are not linked together, so they have to be manually
  # added here.
  case resource_type
  when 'instance'
    define_instance_method('live_tasks') do |*args|
      if has_id(*args)
        path = href + '/live/tasks'
        path = add_id_and_params_to_path(path, *args)
        RightApi::Resource.process(client, 'live_task', path)
      end
    end
  end

  # Add the rest as instance methods
  hash.each do |k, v|
    k = k.to_sym
    # If a parent resource is requested with a view then it might return
    # extra data that can be used to build child resources here, without
    # doing another get request.
    if associations.include?(k)
      # v might be an array or hash so use include rather than has_key
      if v.include?('links')
        child_self_link = v['links'].find { |target| target['rel'] == 'self' }
        if child_self_link
          child_href = child_self_link['href']
          if child_href
            # Currently, only instances need this optimization, but in the
            # future we might like to extract resource_type from child_href
            # and not hard-code it.
            if child_href.index('instance')
              define_instance_method(k) do |*args|
                path = add_id_and_params_to_path(child_href, *args)
                RightApi::Resource.process(client, 'instance', path, v)
              end
            end
          end
        end
      else
        # This is an attribute whose name coincides with the name of a link,
        # but which isn't actually an embedded subrecource (it has no links
        # or other media-type decorators). Add it to attributes.
        attributes << k
        @attributes_with_values[k] = v
      end
    else
      # Add it to the attributes set and create a method for it
      attributes << k
      @attributes_with_values[k] = v
      define_instance_method(k) { return @attributes_with_values[k] }
    end
  end

  # Add destroy method to relevant resources
  define_instance_method('destroy') do |*args|
    client.send(:do_delete, href, *args)
  end

  # Add update method to relevant resources
  define_instance_method('update') do |*args|

    if resource_type == 'account' # HACK: handle child_account update specially
      update_href = href.sub(/account/, 'child_account')
      client.send(:do_put, update_href, *args)
    else
      client.send(:do_put, href, *args)
    end
  end

  # Add show method to relevant resources
  define_instance_method('show') do |*args|
    self
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(m, *args) ⇒ Object

Any other method other than standard actions(show,update,destroy) is simply appended to the href and called with a POST.



140
141
142
143
# File 'lib/right_api_client/resource_detail.rb', line 140

def method_missing(m, *args)
  # the method href would have been defined while initializing the object
  client.send(:do_post, [ href, m.to_s ].join('/'), *args)
end

Instance Attribute Details

#actionsObject (readonly)

Returns the value of attribute actions.



5
6
7
# File 'lib/right_api_client/resource_detail.rb', line 5

def actions
  @actions
end

#associationsObject (readonly)

Returns the value of attribute associations.



5
6
7
# File 'lib/right_api_client/resource_detail.rb', line 5

def associations
  @associations
end

#attributesObject (readonly)

Returns the value of attribute attributes.



5
6
7
# File 'lib/right_api_client/resource_detail.rb', line 5

def attributes
  @attributes
end

#clientObject (readonly)

Returns the value of attribute client.



5
6
7
# File 'lib/right_api_client/resource_detail.rb', line 5

def client
  @client
end

#rawObject (readonly)

Returns the value of attribute raw.



5
6
7
# File 'lib/right_api_client/resource_detail.rb', line 5

def raw
  @raw
end

#resource_typeObject (readonly)

Returns the value of attribute resource_type.



5
6
7
# File 'lib/right_api_client/resource_detail.rb', line 5

def resource_type
  @resource_type
end

Instance Method Details

#[](k) ⇒ Object

Access attributes of this resource in a Hash-like manner. This is useful in cases where an attribute name coincides with a link name, e.g. a resource that contains embedded subresources.

This method can accept String or Symbol attribute names. The data type of the returned object is unspecified; it could be a String, Integer, Hash, Array or any other JSON data type. If a Hash is returned, then its keys will always be String.



134
135
136
# File 'lib/right_api_client/resource_detail.rb', line 134

def [](k)
  @attributes_with_values[k.to_sym]
end

#inspectObject



7
8
9
10
11
12
# File 'lib/right_api_client/resource_detail.rb', line 7

def inspect
  "#<#{self.class.name} " +
  "resource_type=\"#{@resource_type}\"" +
  "#{', name=' + name.inspect if self.respond_to?(:name)}" +
  "#{', resource_uid='+ resource_uid.inspect if self.respond_to?(:resource_uid)}>"
end