xively-rb 0.2.09
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.
- data/.gitignore +13 -0
- data/.rbenv-version +1 -0
- data/.rspec +2 -0
- data/.rvmrc +1 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +91 -0
- data/CONTRIBUTING.md +95 -0
- data/Gemfile +15 -0
- data/LICENSE.md +13 -0
- data/README.md +10 -0
- data/Rakefile +25 -0
- data/ci/build_hudson.sh +24 -0
- data/init.rb +2 -0
- data/lib/xively-rb.rb +44 -0
- data/lib/xively-rb/array_extensions.rb +6 -0
- data/lib/xively-rb/base.rb +52 -0
- data/lib/xively-rb/base/instance_methods.rb +28 -0
- data/lib/xively-rb/client.rb +43 -0
- data/lib/xively-rb/datapoint.rb +72 -0
- data/lib/xively-rb/datastream.rb +127 -0
- data/lib/xively-rb/exceptions.rb +5 -0
- data/lib/xively-rb/feed.rb +109 -0
- data/lib/xively-rb/hash_extensions.rb +16 -0
- data/lib/xively-rb/helpers.rb +41 -0
- data/lib/xively-rb/key.rb +99 -0
- data/lib/xively-rb/nil_content.rb +15 -0
- data/lib/xively-rb/object_extensions.rb +6 -0
- data/lib/xively-rb/parsers/csv/datastream_defaults.rb +50 -0
- data/lib/xively-rb/parsers/csv/feed_defaults.rb +97 -0
- data/lib/xively-rb/parsers/defaults.rb +15 -0
- data/lib/xively-rb/parsers/json/datapoint_defaults.rb +16 -0
- data/lib/xively-rb/parsers/json/datastream_defaults.rb +58 -0
- data/lib/xively-rb/parsers/json/feed_defaults.rb +114 -0
- data/lib/xively-rb/parsers/json/key_defaults.rb +20 -0
- data/lib/xively-rb/parsers/json/search_result_defaults.rb +24 -0
- data/lib/xively-rb/parsers/json/trigger_defaults.rb +16 -0
- data/lib/xively-rb/parsers/xml/datapoint_defaults.rb +27 -0
- data/lib/xively-rb/parsers/xml/datastream_defaults.rb +53 -0
- data/lib/xively-rb/parsers/xml/errors.rb +7 -0
- data/lib/xively-rb/parsers/xml/feed_defaults.rb +83 -0
- data/lib/xively-rb/parsers/xml/helpers.rb +116 -0
- data/lib/xively-rb/parsers/xml/key_defaults.rb +46 -0
- data/lib/xively-rb/parsers/xml/trigger_defaults.rb +28 -0
- data/lib/xively-rb/permission.rb +67 -0
- data/lib/xively-rb/resource.rb +43 -0
- data/lib/xively-rb/search_result.rb +68 -0
- data/lib/xively-rb/string_extensions.rb +6 -0
- data/lib/xively-rb/templates/csv/datapoint_defaults.rb +22 -0
- data/lib/xively-rb/templates/csv/datastream_defaults.rb +43 -0
- data/lib/xively-rb/templates/csv/feed_defaults.rb +47 -0
- data/lib/xively-rb/templates/defaults.rb +14 -0
- data/lib/xively-rb/templates/json/datapoint_defaults.rb +15 -0
- data/lib/xively-rb/templates/json/datastream_defaults.rb +61 -0
- data/lib/xively-rb/templates/json/feed_defaults.rb +90 -0
- data/lib/xively-rb/templates/json/key_defaults.rb +39 -0
- data/lib/xively-rb/templates/json/search_result_defaults.rb +42 -0
- data/lib/xively-rb/templates/json/trigger_defaults.rb +21 -0
- data/lib/xively-rb/templates/xml/datapoint_defaults.rb +25 -0
- data/lib/xively-rb/templates/xml/datastream_defaults.rb +66 -0
- data/lib/xively-rb/templates/xml/feed_defaults.rb +112 -0
- data/lib/xively-rb/templates/xml/search_result_defaults.rb +118 -0
- data/lib/xively-rb/templates/xml_headers.rb +17 -0
- data/lib/xively-rb/trigger.rb +66 -0
- data/lib/xively-rb/validations.rb +9 -0
- data/lib/xively-rb/version.rb +3 -0
- data/spec/fixtures/models.rb +81 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/support/contain_datapoint_eeml_matcher.rb +16 -0
- data/spec/support/contain_datastream_eeml_matcher.rb +60 -0
- data/spec/support/contain_feed_eeml_matcher.rb +98 -0
- data/spec/support/datapoint_helper.rb +53 -0
- data/spec/support/datastream_helper.rb +324 -0
- data/spec/support/describe_eeml_matcher.rb +23 -0
- data/spec/support/feed_helper.rb +783 -0
- data/spec/support/fully_represent_datapoint_matcher.rb +30 -0
- data/spec/support/fully_represent_datastream_matcher.rb +96 -0
- data/spec/support/fully_represent_feed_matcher.rb +234 -0
- data/spec/support/fully_represent_key_matcher.rb +74 -0
- data/spec/support/fully_represent_search_result_matcher.rb +67 -0
- data/spec/support/fully_represent_trigger_matcher.rb +29 -0
- data/spec/support/key_helper.rb +74 -0
- data/spec/support/search_result_helper.rb +252 -0
- data/spec/support/trigger_helper.rb +51 -0
- data/spec/xively-rb/array_extensions_spec.rb +9 -0
- data/spec/xively-rb/base/instance_methods_spec.rb +109 -0
- data/spec/xively-rb/base_spec.rb +56 -0
- data/spec/xively-rb/client_spec.rb +51 -0
- data/spec/xively-rb/datapoint_spec.rb +187 -0
- data/spec/xively-rb/datastream_spec.rb +344 -0
- data/spec/xively-rb/feed_spec.rb +341 -0
- data/spec/xively-rb/hash_extensions_spec.rb +20 -0
- data/spec/xively-rb/helpers_spec.rb +56 -0
- data/spec/xively-rb/key_spec.rb +198 -0
- data/spec/xively-rb/parsers/csv/datastream_defaults_spec.rb +110 -0
- data/spec/xively-rb/parsers/csv/feed_defaults_spec.rb +234 -0
- data/spec/xively-rb/parsers/json/datapoint_defaults_spec.rb +21 -0
- data/spec/xively-rb/parsers/json/datastream_defaults_spec.rb +105 -0
- data/spec/xively-rb/parsers/json/feed_defaults_spec.rb +45 -0
- data/spec/xively-rb/parsers/json/key_defaults_spec.rb +14 -0
- data/spec/xively-rb/parsers/json/search_result_defaults_spec.rb +18 -0
- data/spec/xively-rb/parsers/json/trigger_defaults_spec.rb +22 -0
- data/spec/xively-rb/parsers/xml/datapoint_defaults_spec.rb +19 -0
- data/spec/xively-rb/parsers/xml/datastream_defaults_spec.rb +148 -0
- data/spec/xively-rb/parsers/xml/feed_defaults_spec.rb +254 -0
- data/spec/xively-rb/parsers/xml/key_defaults_spec.rb +22 -0
- data/spec/xively-rb/parsers/xml/trigger_defaults_spec.rb +22 -0
- data/spec/xively-rb/search_result_spec.rb +257 -0
- data/spec/xively-rb/string_extensions_spec.rb +12 -0
- data/spec/xively-rb/templates/csv/datapoint_defaults_spec.rb +41 -0
- data/spec/xively-rb/templates/csv/datastream_defaults_spec.rb +131 -0
- data/spec/xively-rb/templates/csv/feed_defaults_spec.rb +78 -0
- data/spec/xively-rb/templates/json/datapoint_defaults_spec.rb +14 -0
- data/spec/xively-rb/templates/json/datastream_defaults_spec.rb +170 -0
- data/spec/xively-rb/templates/json/feed_defaults_spec.rb +399 -0
- data/spec/xively-rb/templates/json/key_defaults_spec.rb +29 -0
- data/spec/xively-rb/templates/json/search_result_defaults_spec.rb +37 -0
- data/spec/xively-rb/templates/json/trigger_defaults_spec.rb +19 -0
- data/spec/xively-rb/templates/xml/datapoint_defaults_spec.rb +14 -0
- data/spec/xively-rb/templates/xml/datastream_defaults_spec.rb +113 -0
- data/spec/xively-rb/templates/xml/feed_defaults_spec.rb +131 -0
- data/spec/xively-rb/templates/xml/search_result_defaults_spec.rb +44 -0
- data/spec/xively-rb/trigger_spec.rb +157 -0
- data/xively-rb.gemspec +41 -0
- metadata +333 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require 'httparty'
|
|
2
|
+
module Xively
|
|
3
|
+
class Client
|
|
4
|
+
include HTTParty
|
|
5
|
+
base_uri 'https://api.xively.com'
|
|
6
|
+
|
|
7
|
+
attr_accessor :api_key
|
|
8
|
+
|
|
9
|
+
def self.user_agent
|
|
10
|
+
"xively-rb/#{Xively::VERSION}"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def initialize(api_key)
|
|
14
|
+
@api_key = api_key
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def get(url, options = {})
|
|
18
|
+
self.class.get(url, parse_options(options))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def delete(url, options = {})
|
|
22
|
+
self.class.delete(url, parse_options(options))
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def put(url, options = {})
|
|
26
|
+
self.class.put(url, parse_options(options))
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def post(url, options = {})
|
|
30
|
+
self.class.post(url, parse_options(options))
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def parse_options(options = {})
|
|
36
|
+
new_options = options.clone
|
|
37
|
+
new_options[:headers] ||= {}
|
|
38
|
+
new_options[:headers].merge!("User-Agent" => self.class.user_agent, "X-ApiKey" => api_key)
|
|
39
|
+
new_options
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
module Xively
|
|
2
|
+
class Datapoint
|
|
3
|
+
ALLOWED_KEYS = %w(feed_id datastream_id at value)
|
|
4
|
+
ALLOWED_KEYS.each { |key| attr_accessor(key.to_sym) }
|
|
5
|
+
|
|
6
|
+
include Xively::Templates::JSON::DatapointDefaults
|
|
7
|
+
include Xively::Templates::XML::DatapointDefaults
|
|
8
|
+
include Xively::Templates::CSV::DatapointDefaults
|
|
9
|
+
include Xively::Parsers::JSON::DatapointDefaults
|
|
10
|
+
include Xively::Parsers::XML::DatapointDefaults
|
|
11
|
+
|
|
12
|
+
# validates_presence_of :datastream_id
|
|
13
|
+
# validates_presence_of :value
|
|
14
|
+
|
|
15
|
+
include Validations
|
|
16
|
+
|
|
17
|
+
def valid?
|
|
18
|
+
pass = true
|
|
19
|
+
[:datastream_id, :value, :feed_id].each do |attr|
|
|
20
|
+
if self.send(attr).blank?
|
|
21
|
+
errors[attr] = ["can't be blank"]
|
|
22
|
+
pass = false
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
return pass
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def initialize(input = {}, format = nil)
|
|
29
|
+
raise InvalidFormatError, "Unknown format specified, currently we can only parse JSON or XML." unless [nil,:json,:xml].include?(format)
|
|
30
|
+
if input.is_a? Hash
|
|
31
|
+
self.attributes = input
|
|
32
|
+
elsif format == :json || (format.nil? && input.strip[0...1].to_s == "{")
|
|
33
|
+
self.attributes = from_json(input)
|
|
34
|
+
else
|
|
35
|
+
self.attributes = from_xml(input)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def attributes
|
|
40
|
+
h = {}
|
|
41
|
+
ALLOWED_KEYS.each do |key|
|
|
42
|
+
value = self.send(key)
|
|
43
|
+
h[key] = value unless value.nil?
|
|
44
|
+
end
|
|
45
|
+
return h
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def attributes=(input)
|
|
49
|
+
return if input.nil?
|
|
50
|
+
input.deep_stringify_keys!
|
|
51
|
+
ALLOWED_KEYS.each { |key| self.send("#{key}=", input[key]) }
|
|
52
|
+
return attributes
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def as_json(options = {})
|
|
56
|
+
generate_json(options[:version])
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def to_json(options = {})
|
|
60
|
+
MultiJson.dump as_json(options)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def to_xml(options = {})
|
|
64
|
+
generate_xml(options[:version])
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def to_csv(options = {})
|
|
68
|
+
generate_csv(options.delete(:version), options)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
module Xively
|
|
2
|
+
class Datastream
|
|
3
|
+
ALLOWED_KEYS = %w(feed_id id feed_creator current_value datapoints max_value min_value tags unit_label unit_symbol unit_type updated datapoints_function)
|
|
4
|
+
ALLOWED_KEYS.each { |key| attr_accessor(key.to_sym) }
|
|
5
|
+
VALID_UNIT_TYPES = %w(basicSI derivedSI conversionBasedUnits derivedUnits contextDependentUnits)
|
|
6
|
+
|
|
7
|
+
include Xively::Helpers
|
|
8
|
+
include Xively::Templates::JSON::DatastreamDefaults
|
|
9
|
+
include Xively::Templates::XML::DatastreamDefaults
|
|
10
|
+
include Xively::Templates::CSV::DatastreamDefaults
|
|
11
|
+
include Xively::Parsers::JSON::DatastreamDefaults
|
|
12
|
+
include Xively::Parsers::XML::DatastreamDefaults
|
|
13
|
+
include Xively::Parsers::CSV::DatastreamDefaults
|
|
14
|
+
|
|
15
|
+
include Validations
|
|
16
|
+
|
|
17
|
+
def valid?
|
|
18
|
+
pass = true
|
|
19
|
+
[:id].each do |attr|
|
|
20
|
+
if self.send(attr).blank?
|
|
21
|
+
errors[attr] = ["can't be blank"]
|
|
22
|
+
pass = false
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
if !unit_type.blank?
|
|
26
|
+
if !VALID_UNIT_TYPES.include?(unit_type)
|
|
27
|
+
errors[:unit_type] = ["is not a valid unit_type (pick one from #{VALID_UNIT_TYPES.join(', ')} or leave blank)"]
|
|
28
|
+
pass = false
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
if current_value && current_value.length > 255
|
|
32
|
+
errors[:current_value] = ["is too long (maximum is 255 characters)"]
|
|
33
|
+
pass = false
|
|
34
|
+
end
|
|
35
|
+
if tags
|
|
36
|
+
self.tags = join_tags(self.tags)
|
|
37
|
+
if tags && tags.length > 255
|
|
38
|
+
errors[:tags] = ["is too long (maximum is 255 characters)"]
|
|
39
|
+
pass = false
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
stream_id_regexp = RUBY_VERSION.to_f >= 1.9 ? /\A[\p{L}\w\-\+\.]+\Z/u : /\A[\w\-\+\.]+\Z/u
|
|
44
|
+
|
|
45
|
+
unless self.id =~ stream_id_regexp
|
|
46
|
+
errors[:id] = ["is invalid"]
|
|
47
|
+
pass = false
|
|
48
|
+
end
|
|
49
|
+
if self.id.blank?
|
|
50
|
+
errors[:id] = ["can't be blank"]
|
|
51
|
+
pass = false
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
unless self.feed_id.to_s =~ /\A\d*\Z/
|
|
55
|
+
errors[:feed_id] = ["is invalid"]
|
|
56
|
+
pass = false
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
return pass
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def initialize(input = {}, csv_version = nil, format = nil)
|
|
63
|
+
raise InvalidFormatError, "Unknown format specified, currently we can only parse JSON, XML or CSV." unless [nil,:json,:xml,:csv].include?(format)
|
|
64
|
+
if input.is_a? Hash
|
|
65
|
+
self.attributes = input
|
|
66
|
+
elsif format == :json || (format.nil? && input.strip[0...1].to_s == "{")
|
|
67
|
+
self.attributes = from_json(input)
|
|
68
|
+
elsif format == :xml || (format.nil? && input.strip[0...1].to_s == "<")
|
|
69
|
+
self.attributes = from_xml(input)
|
|
70
|
+
else
|
|
71
|
+
self.attributes = from_csv(input, csv_version)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def attributes
|
|
76
|
+
h = {}
|
|
77
|
+
ALLOWED_KEYS.each do |key|
|
|
78
|
+
value = self.send(key)
|
|
79
|
+
h[key] = value unless value.nil?
|
|
80
|
+
end
|
|
81
|
+
return h
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def attributes=(input)
|
|
85
|
+
return if input.nil?
|
|
86
|
+
input.deep_stringify_keys!
|
|
87
|
+
ALLOWED_KEYS.each { |key| self.send("#{key}=", input[key]) }
|
|
88
|
+
return attributes
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def datapoints
|
|
92
|
+
@datapoints.nil? ? [] : @datapoints
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def datapoints=(array)
|
|
96
|
+
return unless array.is_a?(Array)
|
|
97
|
+
@datapoints = []
|
|
98
|
+
array.each do |datapoint|
|
|
99
|
+
if datapoint.is_a?(Datapoint)
|
|
100
|
+
@datapoints << datapoint
|
|
101
|
+
elsif datapoint.is_a?(Hash)
|
|
102
|
+
@datapoints << Datapoint.new(datapoint)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def as_json(options = {})
|
|
108
|
+
options[:version] ||= "1.0.0"
|
|
109
|
+
generate_json(options.delete(:version), options)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def to_json(options = {})
|
|
113
|
+
MultiJson.dump as_json(options)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def to_xml(options = {})
|
|
117
|
+
options[:version] ||= "0.5.1"
|
|
118
|
+
generate_xml(options.delete(:version), options)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def to_csv(options = {})
|
|
122
|
+
options[:version] ||= "2"
|
|
123
|
+
generate_csv(options.delete(:version), options)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
module Xively
|
|
2
|
+
class Feed
|
|
3
|
+
# The order of these keys is the order attributes are assigned in. (i.e. id should come before datastreams)
|
|
4
|
+
ALLOWED_KEYS = %w(id creator owner_login datastreams description email feed icon location_disposition location_domain location_ele location_exposure location_lat location_lon location_name location_waypoints private status tags title updated created website auto_feed_url product_id device_serial csv_version)
|
|
5
|
+
ALLOWED_KEYS.each { |key| attr_accessor(key.to_sym) }
|
|
6
|
+
|
|
7
|
+
include Xively::Templates::JSON::FeedDefaults
|
|
8
|
+
include Xively::Templates::XML::FeedDefaults
|
|
9
|
+
include Xively::Templates::CSV::FeedDefaults
|
|
10
|
+
include Xively::Parsers::JSON::FeedDefaults
|
|
11
|
+
include Xively::Parsers::XML::FeedDefaults
|
|
12
|
+
include Xively::Parsers::CSV::FeedDefaults
|
|
13
|
+
|
|
14
|
+
include Validations
|
|
15
|
+
|
|
16
|
+
def valid?
|
|
17
|
+
pass = true
|
|
18
|
+
if title.blank?
|
|
19
|
+
errors[:title] = ["can't be blank"]
|
|
20
|
+
pass = false
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
duplicate_datastream_ids = datastreams.inject({}) {|h,v| h[v.id]=h[v.id].to_i+1; h}.reject{|k,v| v==1}.keys
|
|
24
|
+
if duplicate_datastream_ids.any?
|
|
25
|
+
errors[:datastreams] = ["can't have duplicate IDs: #{duplicate_datastream_ids.join(',')}"]
|
|
26
|
+
pass = false
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
datastreams.each do |ds|
|
|
30
|
+
unless ds.valid?
|
|
31
|
+
ds.errors.each { |attr, ds_errors|
|
|
32
|
+
errors["datastreams_#{attr}".to_sym] = ([*errors["datastreams_#{attr}".to_sym]] | [*ds_errors]).compact
|
|
33
|
+
}
|
|
34
|
+
pass = false
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
return pass
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def initialize(input = {}, csv_version = nil, format = nil)
|
|
42
|
+
raise InvalidFormatError, "Unknown format specified, currently we can only parse JSON, XML or CSV." unless [nil,:json,:xml,:csv].include?(format)
|
|
43
|
+
if input.is_a?(Hash)
|
|
44
|
+
self.attributes = input
|
|
45
|
+
elsif format == :json || (format.nil? && input.strip[0...1].to_s == "{")
|
|
46
|
+
self.attributes = from_json(input)
|
|
47
|
+
elsif format == :xml || (format.nil? && input.strip[0...5].to_s == "<?xml" || input.strip[0...5].to_s == "<eeml")
|
|
48
|
+
self.attributes = from_xml(input)
|
|
49
|
+
else
|
|
50
|
+
self.attributes = from_csv(input, csv_version)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def attributes
|
|
55
|
+
h = {}
|
|
56
|
+
ALLOWED_KEYS.each do |key|
|
|
57
|
+
value = self.send(key)
|
|
58
|
+
h[key] = value unless value.nil?
|
|
59
|
+
end
|
|
60
|
+
return h
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def datastreams
|
|
64
|
+
return [] if @datastreams.nil?
|
|
65
|
+
@datastreams
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def attributes=(input)
|
|
69
|
+
return if input.nil?
|
|
70
|
+
input.deep_stringify_keys!
|
|
71
|
+
ALLOWED_KEYS.each { |key| self.send("#{key}=", input[key]) }
|
|
72
|
+
return attributes
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def datastreams=(array)
|
|
76
|
+
return unless array.is_a?(Array)
|
|
77
|
+
@datastreams = []
|
|
78
|
+
array.each do |datastream|
|
|
79
|
+
if datastream.is_a?(Datastream)
|
|
80
|
+
@datastreams << datastream
|
|
81
|
+
elsif datastream.is_a?(Hash)
|
|
82
|
+
@datastreams << Datastream.new(datastream)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def as_json(options = {})
|
|
88
|
+
options[:version] ||= "1.0.0"
|
|
89
|
+
generate_json(options.delete(:version), options)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def to_json(options = {})
|
|
93
|
+
MultiJson.dump as_json(options)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def to_xml(options = {})
|
|
97
|
+
options[:version] ||= "0.5.1"
|
|
98
|
+
generate_xml(options.delete(:version), options)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def to_csv(options = {})
|
|
102
|
+
options[:version] ||= "2"
|
|
103
|
+
generate_csv(options.delete(:version), options)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
class Hash
|
|
2
|
+
def delete_if_nil_value
|
|
3
|
+
delete_if{|k,v| v.nil? || v.blank?}
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def deep_stringify_keys
|
|
7
|
+
inject({}) do |options, (key, value)|
|
|
8
|
+
options[key.to_s] = (value.is_a?(Hash) ? value.deep_stringify_keys : value)
|
|
9
|
+
options
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def deep_stringify_keys!
|
|
14
|
+
self.replace(self.deep_stringify_keys)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module Xively
|
|
2
|
+
module Helpers
|
|
3
|
+
def parse_tag_string(string)
|
|
4
|
+
return [] if string.blank?
|
|
5
|
+
string = string.join(',') if string.is_a?(Array)
|
|
6
|
+
tags = []
|
|
7
|
+
quoted_mode = false
|
|
8
|
+
tags << string.chars.reduce("") do |buffer, char|
|
|
9
|
+
if char == ','
|
|
10
|
+
if !quoted_mode
|
|
11
|
+
tags << buffer
|
|
12
|
+
buffer = ""
|
|
13
|
+
else
|
|
14
|
+
buffer << char
|
|
15
|
+
end
|
|
16
|
+
elsif char == '"'
|
|
17
|
+
if buffer.length > 0 && buffer[-1,1] == '\\'
|
|
18
|
+
buffer[-1] = char
|
|
19
|
+
else
|
|
20
|
+
quoted_mode = !quoted_mode
|
|
21
|
+
buffer << char
|
|
22
|
+
end
|
|
23
|
+
else
|
|
24
|
+
buffer << char
|
|
25
|
+
end
|
|
26
|
+
buffer
|
|
27
|
+
end
|
|
28
|
+
# strip the tags
|
|
29
|
+
tags.map { |t|
|
|
30
|
+
/\A\s*("(.*)"|(.*))\s*\Z/.match(t)
|
|
31
|
+
$2 || $3.strip
|
|
32
|
+
}.sort{|a,b| a.downcase <=> b.downcase}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def join_tags(tags)
|
|
36
|
+
return tags unless tags.is_a?(Array)
|
|
37
|
+
tags.sort{|a,b| a.downcase <=> b.downcase}.join(',')
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
module Xively
|
|
2
|
+
class Key
|
|
3
|
+
ALLOWED_KEYS = %w(id key label user expires_at permissions private_access)
|
|
4
|
+
ALLOWED_KEYS.each { |key| attr_accessor(key.to_sym) }
|
|
5
|
+
NESTED_KEYS = %w(permissions)
|
|
6
|
+
|
|
7
|
+
include Xively::Templates::JSON::KeyDefaults
|
|
8
|
+
#include Xively::Templates::XML::KeyDefaults
|
|
9
|
+
include Xively::Parsers::JSON::KeyDefaults
|
|
10
|
+
include Xively::Parsers::XML::KeyDefaults
|
|
11
|
+
|
|
12
|
+
include Validations
|
|
13
|
+
|
|
14
|
+
def valid?
|
|
15
|
+
pass = true
|
|
16
|
+
[:label, :permissions, :user].each do |attr|
|
|
17
|
+
if self.send(attr).blank?
|
|
18
|
+
errors[attr] = ["can't be blank"]
|
|
19
|
+
pass = false
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
permissions.each do |permission|
|
|
24
|
+
unless permission.valid?
|
|
25
|
+
permission.errors.each do |attr, permission_errors|
|
|
26
|
+
errors["permissions_#{attr}".to_sym] = ([*errors["permissions_#{attr}".to_sym]] | [*permission_errors]).compact
|
|
27
|
+
end
|
|
28
|
+
pass = false
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
return pass
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Build an instance from either a Hash, a JSON string, or an XML document
|
|
36
|
+
def initialize(input = {}, format = nil)
|
|
37
|
+
raise InvalidFormatError, "Unknown format specified, currently we can only parse JSON or XML." unless [nil,:json,:xml].include?(format)
|
|
38
|
+
if input.is_a?(Hash)
|
|
39
|
+
self.attributes = input
|
|
40
|
+
elsif format == :json || (format.nil? && input.strip[0...1].to_s == "{")
|
|
41
|
+
self.attributes = from_json(input)
|
|
42
|
+
else
|
|
43
|
+
self.attributes = from_xml(input)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def attributes
|
|
48
|
+
h = {}
|
|
49
|
+
ALLOWED_KEYS.each do |key|
|
|
50
|
+
value = self.send(key)
|
|
51
|
+
h[key] = value unless value.nil?
|
|
52
|
+
end
|
|
53
|
+
return h
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def attributes=(input)
|
|
57
|
+
return if input.nil?
|
|
58
|
+
input.deep_stringify_keys!
|
|
59
|
+
ALLOWED_KEYS.each { |key| self.send("#{key}=", input[key]) }
|
|
60
|
+
NESTED_KEYS.each { |key|
|
|
61
|
+
self.send("#{key}=".to_sym, input["#{key}_attributes"]) unless input["#{key}_attributes"].nil?
|
|
62
|
+
}
|
|
63
|
+
return attributes
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def as_json(options = nil)
|
|
67
|
+
generate_json(options || {})
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def to_json(options = nil)
|
|
71
|
+
MultiJson.dump(as_json(options))
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def permissions
|
|
75
|
+
return [] if @permissions.nil?
|
|
76
|
+
@permissions
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def permissions=(array)
|
|
80
|
+
return unless array.is_a?(Array)
|
|
81
|
+
@permissions = []
|
|
82
|
+
array.each do |permission|
|
|
83
|
+
if permission.is_a?(Permission)
|
|
84
|
+
@permissions << permission
|
|
85
|
+
elsif permission.is_a?(Hash)
|
|
86
|
+
@permissions << Permission.new(permission)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def private_access?
|
|
92
|
+
@private_access || false
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def id
|
|
96
|
+
@id.nil? ? @key : @id
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|