xively-rb 0.2.09

Sign up to get free protection for your applications and to get access to all the features.
Files changed (124) hide show
  1. data/.gitignore +13 -0
  2. data/.rbenv-version +1 -0
  3. data/.rspec +2 -0
  4. data/.rvmrc +1 -0
  5. data/.travis.yml +7 -0
  6. data/CHANGELOG.md +91 -0
  7. data/CONTRIBUTING.md +95 -0
  8. data/Gemfile +15 -0
  9. data/LICENSE.md +13 -0
  10. data/README.md +10 -0
  11. data/Rakefile +25 -0
  12. data/ci/build_hudson.sh +24 -0
  13. data/init.rb +2 -0
  14. data/lib/xively-rb.rb +44 -0
  15. data/lib/xively-rb/array_extensions.rb +6 -0
  16. data/lib/xively-rb/base.rb +52 -0
  17. data/lib/xively-rb/base/instance_methods.rb +28 -0
  18. data/lib/xively-rb/client.rb +43 -0
  19. data/lib/xively-rb/datapoint.rb +72 -0
  20. data/lib/xively-rb/datastream.rb +127 -0
  21. data/lib/xively-rb/exceptions.rb +5 -0
  22. data/lib/xively-rb/feed.rb +109 -0
  23. data/lib/xively-rb/hash_extensions.rb +16 -0
  24. data/lib/xively-rb/helpers.rb +41 -0
  25. data/lib/xively-rb/key.rb +99 -0
  26. data/lib/xively-rb/nil_content.rb +15 -0
  27. data/lib/xively-rb/object_extensions.rb +6 -0
  28. data/lib/xively-rb/parsers/csv/datastream_defaults.rb +50 -0
  29. data/lib/xively-rb/parsers/csv/feed_defaults.rb +97 -0
  30. data/lib/xively-rb/parsers/defaults.rb +15 -0
  31. data/lib/xively-rb/parsers/json/datapoint_defaults.rb +16 -0
  32. data/lib/xively-rb/parsers/json/datastream_defaults.rb +58 -0
  33. data/lib/xively-rb/parsers/json/feed_defaults.rb +114 -0
  34. data/lib/xively-rb/parsers/json/key_defaults.rb +20 -0
  35. data/lib/xively-rb/parsers/json/search_result_defaults.rb +24 -0
  36. data/lib/xively-rb/parsers/json/trigger_defaults.rb +16 -0
  37. data/lib/xively-rb/parsers/xml/datapoint_defaults.rb +27 -0
  38. data/lib/xively-rb/parsers/xml/datastream_defaults.rb +53 -0
  39. data/lib/xively-rb/parsers/xml/errors.rb +7 -0
  40. data/lib/xively-rb/parsers/xml/feed_defaults.rb +83 -0
  41. data/lib/xively-rb/parsers/xml/helpers.rb +116 -0
  42. data/lib/xively-rb/parsers/xml/key_defaults.rb +46 -0
  43. data/lib/xively-rb/parsers/xml/trigger_defaults.rb +28 -0
  44. data/lib/xively-rb/permission.rb +67 -0
  45. data/lib/xively-rb/resource.rb +43 -0
  46. data/lib/xively-rb/search_result.rb +68 -0
  47. data/lib/xively-rb/string_extensions.rb +6 -0
  48. data/lib/xively-rb/templates/csv/datapoint_defaults.rb +22 -0
  49. data/lib/xively-rb/templates/csv/datastream_defaults.rb +43 -0
  50. data/lib/xively-rb/templates/csv/feed_defaults.rb +47 -0
  51. data/lib/xively-rb/templates/defaults.rb +14 -0
  52. data/lib/xively-rb/templates/json/datapoint_defaults.rb +15 -0
  53. data/lib/xively-rb/templates/json/datastream_defaults.rb +61 -0
  54. data/lib/xively-rb/templates/json/feed_defaults.rb +90 -0
  55. data/lib/xively-rb/templates/json/key_defaults.rb +39 -0
  56. data/lib/xively-rb/templates/json/search_result_defaults.rb +42 -0
  57. data/lib/xively-rb/templates/json/trigger_defaults.rb +21 -0
  58. data/lib/xively-rb/templates/xml/datapoint_defaults.rb +25 -0
  59. data/lib/xively-rb/templates/xml/datastream_defaults.rb +66 -0
  60. data/lib/xively-rb/templates/xml/feed_defaults.rb +112 -0
  61. data/lib/xively-rb/templates/xml/search_result_defaults.rb +118 -0
  62. data/lib/xively-rb/templates/xml_headers.rb +17 -0
  63. data/lib/xively-rb/trigger.rb +66 -0
  64. data/lib/xively-rb/validations.rb +9 -0
  65. data/lib/xively-rb/version.rb +3 -0
  66. data/spec/fixtures/models.rb +81 -0
  67. data/spec/spec_helper.rb +29 -0
  68. data/spec/support/contain_datapoint_eeml_matcher.rb +16 -0
  69. data/spec/support/contain_datastream_eeml_matcher.rb +60 -0
  70. data/spec/support/contain_feed_eeml_matcher.rb +98 -0
  71. data/spec/support/datapoint_helper.rb +53 -0
  72. data/spec/support/datastream_helper.rb +324 -0
  73. data/spec/support/describe_eeml_matcher.rb +23 -0
  74. data/spec/support/feed_helper.rb +783 -0
  75. data/spec/support/fully_represent_datapoint_matcher.rb +30 -0
  76. data/spec/support/fully_represent_datastream_matcher.rb +96 -0
  77. data/spec/support/fully_represent_feed_matcher.rb +234 -0
  78. data/spec/support/fully_represent_key_matcher.rb +74 -0
  79. data/spec/support/fully_represent_search_result_matcher.rb +67 -0
  80. data/spec/support/fully_represent_trigger_matcher.rb +29 -0
  81. data/spec/support/key_helper.rb +74 -0
  82. data/spec/support/search_result_helper.rb +252 -0
  83. data/spec/support/trigger_helper.rb +51 -0
  84. data/spec/xively-rb/array_extensions_spec.rb +9 -0
  85. data/spec/xively-rb/base/instance_methods_spec.rb +109 -0
  86. data/spec/xively-rb/base_spec.rb +56 -0
  87. data/spec/xively-rb/client_spec.rb +51 -0
  88. data/spec/xively-rb/datapoint_spec.rb +187 -0
  89. data/spec/xively-rb/datastream_spec.rb +344 -0
  90. data/spec/xively-rb/feed_spec.rb +341 -0
  91. data/spec/xively-rb/hash_extensions_spec.rb +20 -0
  92. data/spec/xively-rb/helpers_spec.rb +56 -0
  93. data/spec/xively-rb/key_spec.rb +198 -0
  94. data/spec/xively-rb/parsers/csv/datastream_defaults_spec.rb +110 -0
  95. data/spec/xively-rb/parsers/csv/feed_defaults_spec.rb +234 -0
  96. data/spec/xively-rb/parsers/json/datapoint_defaults_spec.rb +21 -0
  97. data/spec/xively-rb/parsers/json/datastream_defaults_spec.rb +105 -0
  98. data/spec/xively-rb/parsers/json/feed_defaults_spec.rb +45 -0
  99. data/spec/xively-rb/parsers/json/key_defaults_spec.rb +14 -0
  100. data/spec/xively-rb/parsers/json/search_result_defaults_spec.rb +18 -0
  101. data/spec/xively-rb/parsers/json/trigger_defaults_spec.rb +22 -0
  102. data/spec/xively-rb/parsers/xml/datapoint_defaults_spec.rb +19 -0
  103. data/spec/xively-rb/parsers/xml/datastream_defaults_spec.rb +148 -0
  104. data/spec/xively-rb/parsers/xml/feed_defaults_spec.rb +254 -0
  105. data/spec/xively-rb/parsers/xml/key_defaults_spec.rb +22 -0
  106. data/spec/xively-rb/parsers/xml/trigger_defaults_spec.rb +22 -0
  107. data/spec/xively-rb/search_result_spec.rb +257 -0
  108. data/spec/xively-rb/string_extensions_spec.rb +12 -0
  109. data/spec/xively-rb/templates/csv/datapoint_defaults_spec.rb +41 -0
  110. data/spec/xively-rb/templates/csv/datastream_defaults_spec.rb +131 -0
  111. data/spec/xively-rb/templates/csv/feed_defaults_spec.rb +78 -0
  112. data/spec/xively-rb/templates/json/datapoint_defaults_spec.rb +14 -0
  113. data/spec/xively-rb/templates/json/datastream_defaults_spec.rb +170 -0
  114. data/spec/xively-rb/templates/json/feed_defaults_spec.rb +399 -0
  115. data/spec/xively-rb/templates/json/key_defaults_spec.rb +29 -0
  116. data/spec/xively-rb/templates/json/search_result_defaults_spec.rb +37 -0
  117. data/spec/xively-rb/templates/json/trigger_defaults_spec.rb +19 -0
  118. data/spec/xively-rb/templates/xml/datapoint_defaults_spec.rb +14 -0
  119. data/spec/xively-rb/templates/xml/datastream_defaults_spec.rb +113 -0
  120. data/spec/xively-rb/templates/xml/feed_defaults_spec.rb +131 -0
  121. data/spec/xively-rb/templates/xml/search_result_defaults_spec.rb +44 -0
  122. data/spec/xively-rb/trigger_spec.rb +157 -0
  123. data/xively-rb.gemspec +41 -0
  124. metadata +333 -0
@@ -0,0 +1,53 @@
1
+ module Xively
2
+ module Parsers
3
+ module XML
4
+ module DatastreamDefaults
5
+ include Xively::Parsers::XML::Helpers
6
+
7
+ def from_xml(xml)
8
+ begin
9
+ parsed = MultiXml.parse(xml)
10
+ raise InvalidXMLError, "Missing 'environment' node from base node" if parsed['eeml'].nil? || !parsed['eeml'].key?('environment')
11
+ return {} if parsed['eeml']['environment'].nil?
12
+ if parsed['eeml']['version'] == '5' || parsed['eeml']['xmlns'] == 'http://www.eeml.org/xsd/005'
13
+ transform_v1(parsed['eeml']['environment'])
14
+ else
15
+ transform_v2(parsed['eeml']['environment'])
16
+ end
17
+ rescue MultiXml::ParseError => e
18
+ raise InvalidXMLError, e.message
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ # As produced by http://xively.com/api/v2/FEED_ID/datastreams/DATASTREAM_ID.xml
25
+ def transform_v2(xml)
26
+ validate_xml(xml)
27
+ datastream = convert_to_hash(xml['data'])
28
+ _extract_datastream(datastream).merge({
29
+ :feed_id => strip(xml,'id'),
30
+ :feed_creator => strip(xml,'creator')
31
+ })
32
+ end
33
+
34
+ # As produced by http://xively.com/api/v1/FEED_ID/datastreams/DATASTREAM_ID.xml
35
+ def transform_v1(xml)
36
+ validate_xml(xml)
37
+ datastream = convert_to_hash(xml['data'])
38
+ _extract_datastream_v1(datastream).merge({
39
+ :feed_id => strip(xml,'id'),
40
+ :updated => strip(xml,'updated'),
41
+ :feed_creator => 'http://www.haque.co.uk'
42
+ })
43
+ end
44
+
45
+ def validate_xml(xml)
46
+ raise InvalidXMLError, "Multiple 'data' nodes are not permitted for Datastream level XML" if xml['data'].is_a?(Array)
47
+ raise InvalidXMLError, "Missing 'data' node from source document" if xml['data'].nil?
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+
@@ -0,0 +1,7 @@
1
+ module Xively
2
+ module Parsers
3
+ module XML
4
+ class InvalidXMLError < Xively::ParserError; end
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,83 @@
1
+ module Xively
2
+ module Parsers
3
+ module XML
4
+ module FeedDefaults
5
+ include Xively::Parsers::XML::Helpers
6
+
7
+ def from_xml(xml)
8
+ begin
9
+ parsed = MultiXml.parse(xml)
10
+ raise InvalidXMLError, "Missing 'environment' node from base node" if parsed['eeml'].nil? || !parsed['eeml'].key?('environment')
11
+ return {} if parsed['eeml']['environment'].nil?
12
+ if parsed['eeml']['version'] == '5' || parsed['eeml']['xmlns'] == 'http://www.eeml.org/xsd/005'
13
+ transform_v1(parsed['eeml']['environment'])
14
+ else
15
+ transform_v2(parsed['eeml']['environment'])
16
+ end
17
+ rescue MultiXml::ParseError => e
18
+ raise InvalidXMLError, e.message
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ # As produced by http://xively.com/api/v2/FEED_ID.xml
25
+ def transform_v2(xml)
26
+ location = xml['location'] || {}
27
+ user = xml['user'] || {}
28
+ {
29
+ :title => strip(xml,'title'),
30
+ :updated => strip(xml,'updated'),
31
+ :creator => strip(xml,'creator'),
32
+ :created => strip(xml,'created'),
33
+ :feed => strip(xml,'feed'),
34
+ :auto_feed_url => strip(xml,'auto_feed_url'),
35
+ :status => strip(xml,'status'),
36
+ :description => strip(xml,'description'),
37
+ :icon => strip(xml,'icon'),
38
+ :website => strip(xml,'website'),
39
+ :email => strip(xml,'email'),
40
+ :private => strip(xml,'private'),
41
+ :location_lon => strip(location,'lon'),
42
+ :location_lat => strip(location,'lat'),
43
+ :location_ele => strip(location,'ele'),
44
+ :location_name => strip(location,'name'),
45
+ :location_domain => strip(location,'domain'),
46
+ :location_exposure => strip(location,'exposure'),
47
+ :location_disposition => strip(location,'disposition'),
48
+ :owner_login => strip(user,'login'),
49
+ :datastreams => _extract_datastreams(xml['data'])
50
+ }.merge(sanitised_tags(xml))
51
+ end
52
+
53
+ # As produced by http://xively.com/api/v1/FEED_ID.xml
54
+ def transform_v1(xml)
55
+ location = xml['location'] || {}
56
+ user = xml['user'] || {}
57
+ {
58
+ :title => strip(xml,'title'),
59
+ :updated => strip(xml,'updated'),
60
+ :creator => 'http://www.haque.co.uk',
61
+ :created => strip(xml,'created'),
62
+ :feed => strip(xml,'feed'),
63
+ :status => strip(xml,'status'),
64
+ :description => strip(xml,'description'),
65
+ :icon => strip(xml,'icon'),
66
+ :website => strip(xml,'website'),
67
+ :email => strip(xml,'email'),
68
+ :location_lon => strip(location,'lon'),
69
+ :location_lat => strip(location,'lat'),
70
+ :location_ele => strip(location,'ele'),
71
+ :location_name => strip(location,'name'),
72
+ :location_domain => strip(location,'domain'),
73
+ :location_exposure => strip(location,'exposure'),
74
+ :location_disposition => strip(location,'disposition'),
75
+ :datastreams => _extract_datastreams_v1(xml['data'])
76
+ }
77
+ end
78
+
79
+ end
80
+ end
81
+ end
82
+ end
83
+
@@ -0,0 +1,116 @@
1
+ module Xively
2
+ module Parsers
3
+ module XML
4
+ module Helpers
5
+
6
+ private
7
+
8
+ def strip(xml, value)
9
+ if xml.key?(value)
10
+ xml[value].nil? ? '' : xml[value].strip
11
+ else
12
+ nil
13
+ end
14
+ end
15
+
16
+ def convert_to_hash(val)
17
+ if val.class == String
18
+ {'__content__' => val}
19
+ else
20
+ val ? val.merge({'__content__' => val['__content__']}) : {}
21
+ end
22
+ end
23
+
24
+ def convert_to_array(val)
25
+ if val.is_a?(Hash)
26
+ val = [val]
27
+ else
28
+ [*val]
29
+ end
30
+ end
31
+
32
+ def _extract_datastreams(xml)
33
+ return unless xml
34
+ xml = convert_to_array(xml)
35
+ xml.collect do |ds|
36
+ _extract_datastream(ds)
37
+ end
38
+ end
39
+
40
+
41
+ def _extract_datastream(xml)
42
+ current_value = convert_to_hash(xml['current_value'])
43
+ unit = convert_to_hash(xml['unit'])
44
+ {
45
+ :current_value => strip(current_value,'__content__'),
46
+ :updated => strip(current_value,'at'),
47
+ :id => strip(xml,'id'),
48
+ :unit_symbol => strip(unit,'symbol'),
49
+ :unit_type => strip(unit,'type'),
50
+ :unit_label => strip(unit,'__content__'),
51
+ :min_value => strip(xml,'min_value'),
52
+ :max_value => strip(xml,'max_value'),
53
+ :datapoints => _extract_datapoints(xml['datapoints'])
54
+ }.merge(sanitised_tags(xml))
55
+ end
56
+
57
+ def _extract_datastreams_v1(xml)
58
+ return unless xml
59
+ xml = convert_to_array(xml)
60
+ xml.collect do |ds|
61
+ _extract_datastream_v1(ds)
62
+ end
63
+ end
64
+
65
+ def _extract_datastream_v1(xml)
66
+ unit = convert_to_hash(xml['unit'])
67
+ value = convert_to_hash(xml['value'])
68
+ {
69
+ :current_value => strip(value,'__content__'),
70
+ :id => strip(xml,'id'),
71
+ :unit_symbol => strip(unit,'symbol'),
72
+ :unit_type => strip(unit,'type'),
73
+ :unit_label => strip(unit,'__content__'),
74
+ :min_value => strip(value,'minValue'),
75
+ :max_value => strip(value,'maxValue')
76
+ }.merge(sanitised_tags(xml))
77
+ end
78
+
79
+ def _extract_datapoints(xml)
80
+ return unless xml
81
+ value = xml['value']
82
+ value = convert_to_array(value)
83
+ value.collect do |dp|
84
+ _extract_datapoint(dp)
85
+ end
86
+ end
87
+
88
+ def _extract_datapoint(xml)
89
+ value = convert_to_hash(xml)
90
+ {
91
+ :at => strip(value,'at'),
92
+ :value => strip(value,'__content__')
93
+ }
94
+ end
95
+
96
+ def _extract_tags(xml)
97
+ if xml.class != Array
98
+ xml = [xml]
99
+ end
100
+ if (tags = xml.collect { |t| "#{t}".strip }).any?
101
+ Xively::CSV.generate_line(tags.delete_if { |v| v.to_s.strip == "" }.sort{ |a,b| a.downcase <=> b.downcase}).strip
102
+ end
103
+ end
104
+
105
+ # Keep blank tags but delete if value is nil
106
+ def sanitised_tags(xml)
107
+ if xml.key?('tag')
108
+ {:tags => _extract_tags(xml['tag'])}
109
+ else
110
+ {}
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,46 @@
1
+ module Xively
2
+ module Parsers
3
+ module XML
4
+ module KeyDefaults
5
+ def from_xml(xml)
6
+ begin
7
+ xml = Nokogiri::XML(xml) do |config|
8
+ config.strict.nonet
9
+ end
10
+ hash = {}
11
+ hash["id"] = xml.at_xpath("//id").content if xml.at_xpath("//id")
12
+ hash["expires_at"] = xml.at_xpath("//expires-at").content if xml.at_xpath("//expires-at")
13
+ hash["key"] = xml.at_xpath("//api-key").content if xml.at_xpath("//api-key")
14
+ hash["label"] = xml.at_xpath("//label").content if xml.at_xpath("//label")
15
+ hash["user"] = xml.at_xpath("//user").content if xml.at_xpath("//user")
16
+ hash["private_access"] = xml.at_xpath("//private-access").content if xml.at_xpath("//private-access")
17
+
18
+ hash["permissions"] = xml.xpath("//key/permissions/permission").collect { |permission|
19
+ access_methods = permission.xpath("access-methods/access-method").collect { |method|
20
+ method.content.to_s.downcase
21
+ }
22
+ resources = permission.xpath("resources/resource").collect { |resource|
23
+ { "feed_id" => resource.at_xpath("feed-id").content,
24
+ "datastream_id" => resource.at_xpath("datastream-id").content,
25
+ "datastream_trigger_id" => resource.at_xpath("datastream-trigger-id").content
26
+ }.delete_if_nil_value
27
+ }
28
+ {
29
+ "referer" => permission.at_xpath("referer").content,
30
+ "source_ip" => permission.at_xpath("source-ip").content,
31
+ "private_access" => permission.at_xpath("private-access").content,
32
+ "access_methods" => access_methods,
33
+ "resources" => resources
34
+ }.delete_if_nil_value
35
+ }
36
+
37
+ hash
38
+ rescue Nokogiri::SyntaxError => e
39
+ raise InvalidXMLError, e.message
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+
@@ -0,0 +1,28 @@
1
+ module Xively
2
+ module Parsers
3
+ module XML
4
+ module TriggerDefaults
5
+ def from_xml(xml)
6
+ begin
7
+ xml = Nokogiri::XML(xml) do |config|
8
+ config.strict.nonet
9
+ end
10
+ hash = {}
11
+ hash["id"] = xml.at_xpath("//id").content if xml.at_xpath("//id")
12
+ hash["url"] = xml.at_xpath("//url").content if xml.at_xpath("//url")
13
+ hash["trigger_type"] = xml.at_xpath("//trigger-type").content if xml.at_xpath("//trigger-type")
14
+ hash["threshold_value"] = xml.at_xpath("//threshold-value").content if xml.at_xpath("//threshold-value")
15
+ hash["notified_at"] = xml.at_xpath("//notified-at").content if xml.at_xpath("//notified-at")
16
+ hash["user"] = xml.at_xpath("//user").content if xml.at_xpath("//user")
17
+ hash["environment_id"] = xml.at_xpath("//environment-id").content if xml.at_xpath("//environment-id")
18
+ hash["stream_id"] = xml.at_xpath("//stream-id").content if xml.at_xpath("//stream-id")
19
+ hash
20
+ rescue Nokogiri::SyntaxError => e
21
+ raise InvalidXMLError, e.message
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+
@@ -0,0 +1,67 @@
1
+ module Xively
2
+ class Permission
3
+ ALLOWED_KEYS = %w(label access_methods referer source_ip minimum_interval resources)
4
+ ALLOWED_KEYS.each { |key| attr_accessor(key.to_sym) }
5
+ NESTED_KEYS = %w(resources)
6
+
7
+ include Validations
8
+
9
+ def valid?
10
+ pass = true
11
+ if access_methods.nil? || access_methods.empty?
12
+ errors[:access_methods] = ["can't be blank"]
13
+ pass = false
14
+ end
15
+
16
+ resources.each do |resource|
17
+ unless resource.valid?
18
+ resource.errors.each do |attr, resource_errors|
19
+ errors["resources_#{attr}".to_sym] = ([*errors["resources_#{attr}".to_sym]] | [*resource_errors]).compact
20
+ end
21
+ pass = false
22
+ end
23
+ end
24
+
25
+ return pass
26
+ end
27
+
28
+ # Build an instance from a Hash only
29
+ def initialize(input = {})
30
+ self.attributes = input
31
+ end
32
+
33
+ def resources
34
+ return [] if @resources.nil?
35
+ @resources
36
+ end
37
+
38
+ def resources=(array)
39
+ return unless array.is_a?(Array)
40
+ @resources = []
41
+ array.each do |resource|
42
+ if resource.is_a?(Resource)
43
+ @resources << resource
44
+ elsif resource.is_a?(Hash)
45
+ @resources << Resource.new(resource)
46
+ end
47
+ end
48
+ end
49
+
50
+ def attributes
51
+ h = {}
52
+ ALLOWED_KEYS.each do |key|
53
+ value = self.send(key)
54
+ h[key] = value unless value.nil?
55
+ end
56
+ return h
57
+ end
58
+
59
+ def attributes=(input)
60
+ return if input.nil?
61
+ input.deep_stringify_keys!
62
+ ALLOWED_KEYS.each { |key| self.send("#{key}=", input[key]) }
63
+ NESTED_KEYS.each { |key| self.send("#{key}=", input["#{key}_attributes"]) unless input["#{key}_attributes"].nil? }
64
+ return attributes
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,43 @@
1
+ module Xively
2
+ class Resource
3
+ ALLOWED_KEYS = %w(feed_id datastream_id datastream_trigger_id)
4
+ ALLOWED_KEYS.each { |key| attr_accessor(key.to_sym) }
5
+
6
+ include Validations
7
+
8
+ def valid?
9
+ pass = true
10
+ if feed_id.blank? && datastream_id.blank? && datastream_trigger_id.blank?
11
+ errors[:feed_id] = "Must supply at least one of feed_id (optionally with a datastream_id) or datastream_trigger_id"
12
+ pass = false
13
+ end
14
+
15
+ if feed_id.blank? && !datastream_id.blank?
16
+ errors[:feed_id] = ["can't be blank if we have supplied a datastream_id"]
17
+ pass = false
18
+ end
19
+
20
+ return pass
21
+ end
22
+
23
+ def initialize(input = {})
24
+ self.attributes = input
25
+ end
26
+
27
+ def attributes
28
+ h = {}
29
+ ALLOWED_KEYS.each do |key|
30
+ value = self.send(key)
31
+ h[key] = value unless value.nil?
32
+ end
33
+ return h
34
+ end
35
+
36
+ def attributes=(input)
37
+ return if input.nil?
38
+ input.deep_stringify_keys!
39
+ ALLOWED_KEYS.each { |key| self.send("#{key}=", input[key]) }
40
+ return attributes
41
+ end
42
+ end
43
+ end