helium-ruby 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -0
  3. data/README.md +3 -3
  4. data/docs/Helium.html +4 -4
  5. data/docs/Helium/Client.html +9 -9
  6. data/docs/Helium/Client/Elements.html +8 -110
  7. data/docs/Helium/Client/Http.html +31 -33
  8. data/docs/Helium/Client/Labels.html +38 -218
  9. data/docs/Helium/Client/Organizations.html +1 -1
  10. data/docs/Helium/Client/Sensors.html +30 -214
  11. data/docs/Helium/Client/Users.html +1 -1
  12. data/docs/Helium/ClientError.html +153 -0
  13. data/docs/Helium/Cursor.html +8 -8
  14. data/docs/Helium/DataPoint.html +9 -9
  15. data/docs/Helium/Element.html +16 -79
  16. data/docs/Helium/Error.html +267 -0
  17. data/docs/Helium/InvalidApiKey.html +157 -0
  18. data/docs/Helium/Label.html +29 -133
  19. data/docs/Helium/Organization.html +8 -8
  20. data/docs/Helium/Resource.html +717 -43
  21. data/docs/Helium/Sensor.html +31 -132
  22. data/docs/Helium/User.html +8 -8
  23. data/docs/Helium/Utils.html +1 -1
  24. data/docs/_index.html +33 -4
  25. data/docs/class_list.html +1 -1
  26. data/docs/file.README.html +4 -4
  27. data/docs/index.html +4 -4
  28. data/docs/method_list.html +112 -144
  29. data/docs/top-level-namespace.html +1 -1
  30. data/lib/helium.rb +1 -0
  31. data/lib/helium/client.rb +3 -3
  32. data/lib/helium/client/elements.rb +10 -27
  33. data/lib/helium/client/http.rb +38 -19
  34. data/lib/helium/client/labels.rb +7 -53
  35. data/lib/helium/client/sensors.rb +5 -54
  36. data/lib/helium/cursor.rb +6 -6
  37. data/lib/helium/data_point.rb +5 -5
  38. data/lib/helium/element.rb +7 -8
  39. data/lib/helium/error.rb +28 -0
  40. data/lib/helium/label.rb +3 -11
  41. data/lib/helium/organization.rb +4 -4
  42. data/lib/helium/resource.rb +103 -5
  43. data/lib/helium/sensor.rb +13 -15
  44. data/lib/helium/user.rb +4 -4
  45. data/lib/helium/version.rb +1 -1
  46. metadata +6 -2
@@ -102,7 +102,7 @@
102
102
  </div>
103
103
 
104
104
  <div id="footer">
105
- Generated on Mon Aug 22 15:52:19 2016 by
105
+ Generated on Wed Aug 24 13:22:50 2016 by
106
106
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
107
107
  0.9.3 (ruby-2.3.1).
108
108
  </div>
@@ -3,6 +3,7 @@ require 'json'
3
3
  require 'date'
4
4
 
5
5
  require "helium/version"
6
+ require "helium/error"
6
7
  require "helium/utils"
7
8
  require "helium/client"
8
9
  require "helium/cursor"
@@ -17,9 +17,9 @@ module Helium
17
17
 
18
18
  attr_accessor :api_key
19
19
 
20
- def initialize(api_key:, debug: false)
21
- @api_key = api_key
22
- @debug = debug
20
+ def initialize(opts = {})
21
+ @api_key = opts.fetch(:api_key)
22
+ @debug = opts.fetch(:debug, false)
23
23
  end
24
24
 
25
25
  def inspect
@@ -2,40 +2,23 @@ module Helium
2
2
  class Client
3
3
  module Elements
4
4
  def elements
5
- response = get('/element')
6
- elements_data = JSON.parse(response.body)["data"]
7
-
8
- elements = elements_data.map do |element_data|
9
- Element.new(client: self, params: element_data)
10
- end
11
-
12
- return elements
5
+ Element.all(client: self)
13
6
  end
14
7
 
15
8
  def element(id)
16
- response = get("/element/#{id}")
17
- element_data = JSON.parse(response.body)["data"]
18
-
19
- return Element.new(client: self, params: element_data)
9
+ Element.find(id, client: self)
20
10
  end
21
11
 
22
- def update_element(element, name:)
23
- path = "/element/#{element.id}"
24
-
25
- body = {
26
- data: {
27
- attributes: {
28
- name: name
29
- },
30
- id: element.id,
31
- type: "element"
32
- }
33
- }
12
+ def element_sensors(element)
13
+ path = "/element/#{element.id}?include=sensor"
14
+ response = get(path)
15
+ sensors_data = JSON.parse(response.body)["included"]
34
16
 
35
- response = patch(path, body: body)
36
- element_data = JSON.parse(response.body)["data"]
17
+ sensors = sensors_data.map do |sensor|
18
+ Sensor.new(client: self, params: sensor)
19
+ end
37
20
 
38
- return Element.new(client: self, params: element_data)
21
+ return sensors
39
22
  end
40
23
  end
41
24
  end
@@ -11,28 +11,27 @@ module Helium
11
11
  'User-Agent' => 'helium-ruby'
12
12
  }
13
13
 
14
- def get(path = nil, url: nil, params: {})
15
- request = generate_request(path, url: url, method: :get, params: params)
16
- run(request)
14
+ def get(path, opts = {})
15
+ run(path, :get, opts)
17
16
  end
18
17
 
19
- def paginated_get(path, klass:, params: {})
18
+ def paginated_get(path, opts = {})
19
+ klass = opts.fetch(:klass)
20
+ params = opts.fetch(:params, {})
21
+
20
22
  Cursor.new(client: self, path: path, klass: klass, params: params)
21
23
  end
22
24
 
23
- def post(path, body: {})
24
- request = generate_request(path, method: :post, body: body)
25
- run(request)
25
+ def post(path, opts = {})
26
+ run(path, :post, opts)
26
27
  end
27
28
 
28
- def patch(path, body: {})
29
- request = generate_request(path, method: :patch, body: body)
30
- run(request)
29
+ def patch(path, opts = {})
30
+ run(path, :patch, opts)
31
31
  end
32
32
 
33
33
  def delete(path)
34
- request = generate_request(path, method: :delete)
35
- response = run(request)
34
+ response = run(path, :delete)
36
35
  response.code == 204
37
36
  end
38
37
 
@@ -44,9 +43,24 @@ module Helium
44
43
  })
45
44
  end
46
45
 
47
- def generate_request(path = nil, url: nil, method:, params: {}, body: {})
48
- path = path.gsub(/^\//, '') if path
49
- url ||= "#{PROTOCOL}://#{HOST}/v#{API_VERSION}/#{path}"
46
+ def run(path, method, opts = {})
47
+ request = generate_request(path, opts.merge(method: method))
48
+ response = run_request(request)
49
+ return response
50
+ end
51
+
52
+ def generate_request(path, opts = {})
53
+ method = opts.fetch(:method)
54
+ params = opts.fetch(:params, {})
55
+ body = opts.fetch(:body, {})
56
+
57
+
58
+ url = if path =~ /^http/
59
+ path
60
+ else
61
+ path = path.gsub(/^\//, '')
62
+ "#{PROTOCOL}://#{HOST}/v#{API_VERSION}/#{path}"
63
+ end
50
64
 
51
65
  Typhoeus::Request.new(url, {
52
66
  method: method,
@@ -56,19 +70,24 @@ module Helium
56
70
  })
57
71
  end
58
72
 
59
- def run(request)
73
+ def run_request(request)
60
74
  request.run()
61
75
 
76
+ response = request.response
77
+
62
78
  if debug?
63
79
  method = request.options[:method]
64
80
  puts "#{method.upcase} #{request.url} #{request.response.code} #{request.response.total_time}"
65
81
  # puts request.response.body
66
82
  end
67
83
 
68
- # TODO error handling
69
- # halt(request.response.code, "Helium Get Failed: #{request.response.code.to_s}") unless request.response.code.between?(200,399)\
84
+ halt(response) unless response.code.between?(200,399)
85
+
86
+ return response
87
+ end
70
88
 
71
- return request.response
89
+ def halt(response)
90
+ raise Helium::Error.from_response(response)
72
91
  end
73
92
  end
74
93
  end
@@ -2,63 +2,15 @@ module Helium
2
2
  class Client
3
3
  module Labels
4
4
  def labels
5
- response = get('/label')
6
- labels_data = JSON.parse(response.body)["data"]
7
-
8
- labels = labels_data.map do |label_data|
9
- Label.new(client: self, params: label_data)
10
- end
11
-
12
- return labels
5
+ Label.all(client: self)
13
6
  end
14
7
 
15
8
  def label(id)
16
- response = get("/label/#{id}")
17
- label_data = JSON.parse(response.body)["data"]
18
-
19
- return Label.new(client: self, params: label_data)
20
- end
21
-
22
- def new_label(name:)
23
- path = "/label"
24
-
25
- body = {
26
- data: {
27
- attributes: {
28
- name: name
29
- },
30
- type: "label"
31
- }
32
- }
33
-
34
- response = post(path, body: body)
35
- label_data = JSON.parse(response.body)["data"]
36
-
37
- return Label.new(client: self, params: label_data)
9
+ Label.find(id, client: self)
38
10
  end
39
11
 
40
- def update_label(label, name:)
41
- path = "/label/#{label.id}"
42
-
43
- body = {
44
- data: {
45
- attributes: {
46
- name: name
47
- },
48
- id: label.id,
49
- type: "label"
50
- }
51
- }
52
-
53
- response = patch(path, body: body)
54
- label_data = JSON.parse(response.body)["data"]
55
-
56
- return Label.new(client: self, params: label_data)
57
- end
58
-
59
- def delete_label(label)
60
- path = "/label/#{label.id}"
61
- delete(path)
12
+ def create_label(attributes)
13
+ Label.create(attributes, client: self)
62
14
  end
63
15
 
64
16
  def label_sensors(label)
@@ -73,7 +25,9 @@ module Helium
73
25
  return sensors
74
26
  end
75
27
 
76
- def update_label_sensors(label, sensors: [])
28
+ def update_label_sensors(label, opts = {})
29
+ sensors = opts.fetch(:sensors, [])
30
+
77
31
  path = "/label/#{label.id}/relationships/sensor"
78
32
 
79
33
  sensors = Array(sensors)
@@ -2,21 +2,11 @@ module Helium
2
2
  class Client
3
3
  module Sensors
4
4
  def sensors
5
- response = get('/sensor')
6
- sensors_data = JSON.parse(response.body)["data"]
7
-
8
- sensors = sensors_data.map do |sensor_data|
9
- Sensor.new(client: self, params: sensor_data)
10
- end
11
-
12
- return sensors
5
+ Sensor.all(client: self)
13
6
  end
14
7
 
15
8
  def sensor(id)
16
- response = get("/sensor/#{id}")
17
- sensor_data = JSON.parse(response.body)["data"]
18
-
19
- return Sensor.new(client: self, params: sensor_data)
9
+ Sensor.find(id, client: self)
20
10
  end
21
11
 
22
12
  def sensor_timeseries(sensor, opts = {})
@@ -29,53 +19,14 @@ module Helium
29
19
  "filter[end]" => datetime_to_iso(opts.fetch(:end_time, nil)),
30
20
  "agg[type]" => opts.fetch(:aggtype),
31
21
  "agg[size]" => opts.fetch(:aggsize)
32
- }.delete_if { |key, value| value.to_s.empty? }
22
+ }.delete_if { |_key, value| value.to_s.empty? }
33
23
 
34
24
  paginated_get(path, klass: Helium::DataPoint, params: params)
35
25
  end
36
26
 
37
- def new_sensor(name:)
38
- path = "/sensor"
39
-
40
- body = {
41
- data: {
42
- attributes: {
43
- name: name
44
- },
45
- type: "sensor"
46
- }
47
- }
48
-
49
- response = post(path, body: body)
50
- sensor_data = JSON.parse(response.body)["data"]
51
-
52
- return Sensor.new(client: self, params: sensor_data)
53
- end
54
-
55
- def update_sensor(sensor, name:)
56
- path = "/sensor/#{sensor.id}"
57
-
58
- body = {
59
- data: {
60
- attributes: {
61
- name: name
62
- },
63
- id: sensor.id,
64
- type: "sensor"
65
- }
66
- }
67
-
68
- response = patch(path, body: body)
69
- sensor_data = JSON.parse(response.body)["data"]
70
-
71
- return Sensor.new(client: self, params: sensor_data)
27
+ def create_sensor(attributes)
28
+ Sensor.create(attributes, client: self)
72
29
  end
73
-
74
- def delete_sensor(sensor)
75
- path = "/sensor/#{sensor.id}"
76
- delete(path)
77
- end
78
-
79
30
  end
80
31
  end
81
32
  end
@@ -2,11 +2,11 @@ module Helium
2
2
  class Cursor
3
3
  include Enumerable
4
4
 
5
- def initialize(client:, path:, klass:, params: {})
6
- @client = client
7
- @path = path
8
- @klass = klass
9
- @params = params
5
+ def initialize(opts = {})
6
+ @client = opts.fetch(:client)
7
+ @path = opts.fetch(:path)
8
+ @klass = opts.fetch(:klass)
9
+ @params = opts.fetch(:params, {})
10
10
 
11
11
  @collection = []
12
12
  @next_link = nil
@@ -37,7 +37,7 @@ module Helium
37
37
 
38
38
  def fetch_next_page
39
39
  if @next_link
40
- response = @client.get(url: @next_link)
40
+ response = @client.get(@next_link)
41
41
  else
42
42
  response = @client.get(@path, params: @params)
43
43
  end
@@ -2,12 +2,12 @@ module Helium
2
2
  class DataPoint < Resource
3
3
  attr_reader :timestamp, :value, :port
4
4
 
5
- def initialize(client:, params:)
6
- super(client: client, params: params)
5
+ def initialize(opts = {})
6
+ super(opts)
7
7
 
8
- @timestamp = params.dig("attributes", "timestamp")
9
- @value = params.dig("attributes", "value")
10
- @port = params.dig("attributes", "port")
8
+ @timestamp = @params.dig("attributes", "timestamp")
9
+ @value = @params.dig("attributes", "value")
10
+ @port = @params.dig("attributes", "port")
11
11
  end
12
12
 
13
13
  def timestamp
@@ -2,17 +2,16 @@ module Helium
2
2
  class Element < Resource
3
3
  attr_reader :name, :mac, :versions
4
4
 
5
- def initialize(client:, params:)
6
- super(client: client, params: params)
5
+ def initialize(opts = {})
6
+ super(opts)
7
7
 
8
- @name = params.dig("attributes", "name")
9
- @mac = params.dig("meta", "mac")
10
- @versions = params.dig("meta", "versions")
8
+ @name = @params.dig("attributes", "name")
9
+ @mac = @params.dig("meta", "mac")
10
+ @versions = @params.dig("meta", "versions")
11
11
  end
12
12
 
13
- # TODO these kinds of methods should be generalized into a Resource object
14
- def update(name:)
15
- @client.update_element(self, name: name)
13
+ def sensors
14
+ @client.element_sensors(self)
16
15
  end
17
16
 
18
17
  # TODO can probably generalize this a bit more
@@ -0,0 +1,28 @@
1
+ module Helium
2
+ # Custom error class for rescuing from Helium API errors
3
+ class Error < StandardError
4
+
5
+ # Returns the appropriate Helium::Error subclass based on status and
6
+ # response message
7
+ #
8
+ # @param [Typhoeus::Response] response
9
+ # @return [Helium::Error]
10
+ def self.from_response(response)
11
+ status = response.code
12
+ message = JSON.parse(response.body)["errors"].first["detail"]
13
+
14
+ klass = case status
15
+ when 401 then Helium::InvalidApiKey
16
+ else self
17
+ end
18
+
19
+ klass.new(message)
20
+ end
21
+ end
22
+
23
+ # Raised on errors in the 400-499 range
24
+ class ClientError < Error; end
25
+
26
+ # Raised when Helium returns a 401 error
27
+ class InvalidApiKey < ClientError; end
28
+ end
@@ -2,18 +2,10 @@ module Helium
2
2
  class Label < Resource
3
3
  attr_reader :name
4
4
 
5
- def initialize(client:, params:)
6
- super(client: client, params: params)
5
+ def initialize(opts = {})
6
+ super(opts)
7
7
 
8
- @name = params.dig("attributes", "name")
9
- end
10
-
11
- def update(name:)
12
- @client.update_label(self, name: name)
13
- end
14
-
15
- def destroy
16
- @client.delete_label(self)
8
+ @name = @params.dig("attributes", "name")
17
9
  end
18
10
 
19
11
  # TODO: would be nice to wrap this in a proxy collection, that way