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.
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,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,5 @@
1
+ module Xively
2
+ class Error < StandardError; end
3
+ class InvalidFormatError < Error; end
4
+ class ParserError < Error; end
5
+ end
@@ -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