cosm-rb 0.0.3 → 0.0.5

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/.travis.yml CHANGED
@@ -1,8 +1,3 @@
1
- branches:
2
- only:
3
- - cosm-rb
4
- - master
5
- - version_0.3.xx_branch
6
1
  language: ruby
7
2
  rvm:
8
3
  - 1.8.7
@@ -14,3 +9,4 @@ matrix:
14
9
  allow_failures:
15
10
  - rvm: jruby-18mode
16
11
  - rvm: jruby-19mode
12
+ env: COVERAGE=on
data/Rakefile CHANGED
@@ -20,10 +20,12 @@ desc "Run all specs in spec directory"
20
20
  RSpec::Core::RakeTask.new do |t|
21
21
  end
22
22
 
23
- desc "Run all specs with rcov"
24
- RSpec::Core::RakeTask.new(:rcov => :clean) do |t|
25
- t.rcov = true
26
- t.rcov_opts = '--exclude .gem/*,spec/*,.bundle/*,config/*,.rvm/*'
23
+ if RUBY_VERSION.to_f < 1.9
24
+ desc "Run all specs with rcov"
25
+ RSpec::Core::RakeTask.new(:rcov => :clean) do |t|
26
+ t.rcov = true
27
+ t.rcov_opts = '--exclude .gem/*,spec/*,.bundle/*,config/*,.rvm/*,lib/cosm-rb.rb'
28
+ end
27
29
  end
28
30
 
29
31
  namespace :spec do
data/cosm-rb.gemspec CHANGED
@@ -25,10 +25,18 @@ Gem::Specification.new do |s|
25
25
  s.add_dependency("nokogiri", ">=1.4.4")
26
26
  s.add_dependency("httparty", ">=0.8.3")
27
27
 
28
+ if RUBY_VERSION.to_f < 1.9
29
+ s.add_dependency("fastercsv", ">=1.5.x")
30
+ end
31
+
28
32
  begin
29
- if RUBY_VERSION < "1.9" && !defined?(JRUBY_VERSION)
30
- s.add_development_dependency("ruby-debug")
31
- s.add_development_dependency("rcov", ">=0.9.9")
33
+ if !defined?(JRUBY_VERSION)
34
+ if RUBY_VERSION.to_f < 1.9
35
+ s.add_development_dependency("ruby-debug")
36
+ s.add_development_dependency("rcov", ">=0.9.9")
37
+ else
38
+ s.add_development_dependency("simplecov")
39
+ end
32
40
  end
33
41
  rescue
34
42
  p "Could not detect ruby version"
data/lib/cosm-rb.rb CHANGED
@@ -4,7 +4,6 @@ if defined?(JRUBY_VERSION)
4
4
  else
5
5
  require 'yajl/json_gem'
6
6
  end
7
- require 'csv'
8
7
 
9
8
  $:.unshift(File.dirname(File.expand_path(__FILE__)))
10
9
 
@@ -31,3 +30,12 @@ require 'cosm-rb/permission'
31
30
  require 'cosm-rb/resource'
32
31
 
33
32
  require 'cosm-rb/client'
33
+
34
+ if RUBY_VERSION.to_f < 1.9
35
+ require 'fastercsv'
36
+ Cosm::CSV = FasterCSV
37
+ else
38
+ require 'csv'
39
+ Cosm::CSV = CSV
40
+ end
41
+
@@ -13,16 +13,6 @@ module Cosm
13
13
  include Cosm::Parsers::CSV::DatastreamDefaults
14
14
 
15
15
  include Validations
16
- # validate :before, :join_tags
17
-
18
- # validates_presence_of :id
19
- # validates_length_of :current_value, :maximum => 255
20
- # validates_length_of :tags, :maximum => 255
21
- # validates_inclusion_of :unit_type, :in => VALID_UNIT_TYPES,
22
- # :allow_nil => true,
23
- # :message => "is not a valid unit_type (pick one from #{VALID_UNIT_TYPES} or leave blank)"
24
- # validates_format_of :id, :with => /\A[\w\-\+\.]+\Z/
25
- #
26
16
 
27
17
  def valid?
28
18
  pass = true
@@ -2,8 +2,16 @@ module Cosm
2
2
  module Parsers
3
3
  module CSV
4
4
  module DatastreamDefaults
5
- def from_csv(csv)
6
- {"current_value" => ::CSV.parse(csv.strip).first.first.to_s}
5
+ def from_csv(csv, csv_version = nil)
6
+ rows = Cosm::CSV.parse(csv.strip)
7
+ raise InvalidCSVError, "CSV is invalid. Can only construct a Cosm::Datastream object from a single row of data" if rows.size > 1
8
+ row = rows.first
9
+ raise InvalidCSVError, "CSV is invalid. Too many fields; must only be a single value, or a timestamp and a value" if row.size > 2
10
+ if row.size == 2
11
+ return { "updated" => row[0], "current_value" => row[1].to_s }
12
+ else
13
+ return { "current_value" => row[0].to_s }
14
+ end
7
15
  end
8
16
  end
9
17
  end
@@ -2,20 +2,25 @@ module Cosm
2
2
  module Parsers
3
3
  module CSV
4
4
  class UnknownVersionError < StandardError ; end
5
+ class InvalidCSVError < StandardError ; end
6
+
5
7
  module FeedDefaults
6
8
  def from_csv(csv, csv_version = nil)
7
- array = ::CSV.parse(csv.strip)
8
- version = detect_version(array, csv_version)
9
+ rows = Cosm::CSV.parse(csv.strip)
10
+ version = detect_version(rows, csv_version)
9
11
  hash = Hash.new
10
12
  if version == :v2
11
- hash["datastreams"] = array.collect {|row|
12
- { "id" => row.first.to_s,
13
- "current_value" => row.last.to_s
14
- }
13
+ raise InvalidCSVError, "CSV is invalid. Incorrect number of fields" if rows.sort { |a,b| a.length <=> b.length }.reverse.first.length > 3
14
+ hash["datastreams"] = rows.collect {|row|
15
+ timestamp = {}
16
+ if row.size == 3
17
+ timestamp["updated"] = row[1]
18
+ end
19
+ { "id" => row.first.to_s, "current_value" => row.last.to_s }.merge(timestamp)
15
20
  }
16
21
  elsif version == :v1
17
22
  hash["datastreams"] = []
18
- array.first.each_with_index do |current_value, stream_id|
23
+ rows.first.each_with_index do |current_value, stream_id|
19
24
  hash["datastreams"] << { "id" => stream_id.to_s, "current_value" => current_value }
20
25
  end
21
26
  end
@@ -25,10 +30,10 @@ module Cosm
25
30
 
26
31
  private
27
32
 
28
- def detect_version(array, version = nil)
33
+ def detect_version(rows, version = nil)
29
34
  return version if version
30
- return :v2 if array.size >= 2
31
- return :v1 if array.size == 1 && array.first.size != 2
35
+ return :v2 if rows.size >= 2
36
+ return :v1 if rows.size == 1 && rows.first.size != 2
32
37
  raise UnknownVersionError, "CSV Version could not be detected"
33
38
  end
34
39
  end
@@ -10,7 +10,7 @@ module Cosm
10
10
  case hash['version']
11
11
  when '1.0.0'
12
12
  transform_1_0_0(hash)
13
- when '0.6-alpha'
13
+ when '0.6-alpha', '0.6'
14
14
  transform_0_6_alpha(hash)
15
15
  end
16
16
  end
@@ -59,30 +59,35 @@ module Cosm
59
59
  def transform_0_6_alpha(hash)
60
60
  hash["retrieved_at"] = hash["updated"]
61
61
  hash["state"] = hash["status"]
62
- hash["datastreams"] = hash["datastreams"].collect do |datastream|
63
- unit_hash = {}
64
- if unit = datastream.delete('unit')
65
- unit_hash['unit_type'] = unit['type']
66
- unit_hash['unit_symbol'] = unit['symbol']
67
- unit_hash['unit_label'] = unit['label']
62
+ if hash["datastreams"]
63
+ hash["datastreams"] = hash["datastreams"].collect do |datastream|
64
+ unit_hash = {}
65
+ if unit = datastream.delete('unit')
66
+ unit_hash['unit_type'] = unit['type']
67
+ unit_hash['unit_symbol'] = unit['symbol']
68
+ unit_hash['unit_label'] = unit['label']
69
+ end
70
+ value_hash = {}
71
+ if datastream["values"].size >= 1
72
+ value_hash["current_value"] = datastream["values"].first["value"]
73
+ value_hash["min_value"] = datastream["values"].first["min_value"]
74
+ value_hash["max_value"] = datastream["values"].first["max_value"]
75
+ value_hash["updated"] = datastream["values"].first["recorded_at"]
76
+ end
77
+ {
78
+ "id" => datastream["id"],
79
+ "tags" => join_tags(datastream["tags"]),
80
+ }.merge(value_hash).merge(unit_hash)
81
+ end
82
+ if location = hash.delete("location")
83
+ hash["location_disposition"] = location["disposition"]
84
+ hash["location_domain"] = location["domain"]
85
+ hash["location_ele"] = location["ele"]
86
+ hash["location_exposure"] = location["exposure"]
87
+ hash["location_lat"] = location["lat"]
88
+ hash["location_lon"] = location["lon"]
89
+ hash["location_name"] = location["name"]
68
90
  end
69
- {
70
- "id" => datastream["id"],
71
- "current_value" => datastream["values"].first["value"],
72
- "min_value" => datastream["values"].first["min_value"],
73
- "max_value" => datastream["values"].first["max_value"],
74
- "updated" => datastream["values"].first["recorded_at"],
75
- "tags" => join_tags(datastream["tags"]),
76
- }.merge(unit_hash)
77
- end
78
- if location = hash.delete("location")
79
- hash["location_disposition"] = location["disposition"]
80
- hash["location_domain"] = location["domain"]
81
- hash["location_ele"] = location["ele"]
82
- hash["location_exposure"] = location["exposure"]
83
- hash["location_lat"] = location["lat"]
84
- hash["location_lon"] = location["lon"]
85
- hash["location_name"] = location["name"]
86
91
  end
87
92
  hash
88
93
  end
@@ -6,6 +6,7 @@ module Cosm
6
6
  xml = Nokogiri.parse(xml)
7
7
  hash = {}
8
8
  environment = xml.at_xpath("//xmlns:environment")
9
+ raise InvalidXMLError, "Missing 'environment' node from base node" if environment.nil?
9
10
  data = environment.at_xpath("xmlns:data")
10
11
  datapoint = data.at_xpath("xmlns:datapoints")
11
12
  value = datapoint.at_xpath("xmlns:value")
@@ -18,12 +18,13 @@ module Cosm
18
18
  def transform_0_5_1(xml)
19
19
  hash = {}
20
20
  environment = xml.at_xpath("//xmlns:environment")
21
+ raise InvalidXMLError, "Missing 'environment' node from base node" if environment.nil?
21
22
  data = environment.at_xpath("xmlns:data")
22
23
  hash["feed_id"] = environment.attributes["id"].value
23
24
  hash["feed_creator"] = environment.attributes["creator"].value
24
25
  hash["id"] = data.attributes["id"].value
25
- if (tags = data.xpath("xmlns:tag").collect(&:content)).any?
26
- hash["tags"] = tags.sort{|a,b| a.downcase <=> b.downcase}.join(',')
26
+ if (tags = data.xpath("xmlns:tag").collect { |t| t.content.strip }).any?
27
+ hash["tags"] = Cosm::CSV.generate_line(tags.sort{|a,b| a.downcase <=> b.downcase}).strip
27
28
  end
28
29
  current_value = data.at_xpath("xmlns:current_value")
29
30
  hash["current_value"] = current_value.content
@@ -40,7 +41,7 @@ module Cosm
40
41
  value = datapoint.at_xpath("xmlns:value")
41
42
  {
42
43
  "value" => value.content,
43
- "at" => value.attributes["at"].content
44
+ "at" => value.attributes["at"].value
44
45
  }
45
46
  end
46
47
  hash
@@ -50,13 +51,14 @@ module Cosm
50
51
  def transform_5(xml)
51
52
  hash = {}
52
53
  environment = xml.at_xpath("//xmlns:environment")
54
+ raise InvalidXMLError, "Missing 'environment' node from base node" if environment.nil?
53
55
  data = environment.at_xpath("xmlns:data")
54
56
  hash["feed_id"] = environment.attributes["id"].value
55
57
  hash["feed_creator"] = "http://www.haque.co.uk"
56
58
  hash["updated"] = environment.attributes["updated"].value
57
59
  hash["id"] = data.attributes["id"].value
58
- if (tags = data.xpath("xmlns:tag").collect(&:content)).any?
59
- hash["tags"] = tags.sort{|a,b| a.downcase <=> b.downcase}.join(',')
60
+ if (tags = data.xpath("xmlns:tag").collect { |t| t.content.strip }).any?
61
+ hash["tags"] = Cosm::CSV.generate_line(tags.sort{ |a,b| a.downcase <=> b.downcase }).strip
60
62
  end
61
63
  current_value = data.at_xpath("xmlns:value")
62
64
  hash["current_value"] = current_value.content
@@ -1,13 +1,14 @@
1
1
  module Cosm
2
2
  module Parsers
3
3
  module XML
4
+ class InvalidXMLError < StandardError; end
4
5
  module FeedDefaults
5
6
  def from_xml(xml)
6
7
  xml = Nokogiri.parse(xml)
7
8
  case xml.root.attributes["version"].value
8
9
  when "0.5.1"
9
10
  transform_0_5_1(xml)
10
- else # "5"
11
+ else
11
12
  transform_5(xml)
12
13
  end
13
14
  end
@@ -16,60 +17,73 @@ module Cosm
16
17
  def transform_0_5_1(xml)
17
18
  hash = {}
18
19
  environment = xml.at_xpath("//xmlns:environment")
20
+ raise InvalidXMLError, "Missing 'environment' node from base node" if environment.nil?
19
21
  hash["updated"] = environment.attributes["updated"].value
20
22
  hash["created"] = environment.attributes["created"].value
21
23
  hash["creator"] = environment.attributes["creator"].value
22
- hash["title"] = environment.at_xpath("xmlns:title").content
23
- hash["feed"] = environment.at_xpath("xmlns:feed").content
24
- hash["auto_feed_url"] = environment.at_xpath("xmlns:auto_feed_url").content
25
- hash["status"] = environment.at_xpath("xmlns:status").content
26
- hash["description"] = environment.at_xpath("xmlns:description").content
27
- hash["icon"] = environment.at_xpath("xmlns:icon").content
28
- hash["website"] = environment.at_xpath("xmlns:website").content
29
- hash["email"] = environment.at_xpath("xmlns:email").content
30
- hash["private"] = environment.at_xpath("xmlns:private").content
31
- hash["tags"] = environment.xpath("xmlns:tag").collect(&:content).sort{|a,b| a.downcase <=> b.downcase}.join(',')
24
+ hash["title"] = strip(environment.at_xpath("xmlns:title").content)
25
+ hash["feed"] = strip(environment.at_xpath("xmlns:feed").content)
26
+ hash["auto_feed_url"] = strip(environment.at_xpath("xmlns:auto_feed_url").content)
27
+ hash["status"] = strip(environment.at_xpath("xmlns:status").content)
28
+ hash["description"] = strip(environment.at_xpath("xmlns:description").content)
29
+ hash["icon"] = strip(environment.at_xpath("xmlns:icon").content)
30
+ hash["website"] = strip(environment.at_xpath("xmlns:website").content)
31
+ hash["email"] = strip(environment.at_xpath("xmlns:email").content)
32
+ hash["private"] = strip(environment.at_xpath("xmlns:private").content)
33
+ if (tags = environment.xpath("xmlns:tag").collect { |t| t.content.strip }).any?
34
+ hash["tags"] = Cosm::CSV.generate_line(tags.sort{|a,b| a.downcase <=> b.downcase}).strip
35
+ end
32
36
  location = environment.at_xpath("xmlns:location")
33
37
  if location
34
- hash["location_name"] = location.at_xpath("xmlns:name").content
35
- hash["location_lat"] = location.at_xpath("xmlns:lat").content
36
- hash["location_lon"] = location.at_xpath("xmlns:lon").content
37
- hash["location_ele"] = location.at_xpath("xmlns:ele").content
38
+ hash["location_name"] = strip(location.at_xpath("xmlns:name").content)
39
+ hash["location_lat"] = strip(location.at_xpath("xmlns:lat").content)
40
+ hash["location_lon"] = strip(location.at_xpath("xmlns:lon").content)
41
+ hash["location_ele"] = strip(location.at_xpath("xmlns:ele").content)
38
42
  hash["location_domain"] = location.attributes["domain"].value
39
43
  hash["location_exposure"] = location.attributes["exposure"].value
40
44
  hash["location_disposition"] = location.attributes["disposition"].value
41
45
  end
42
46
  owner = environment.at_xpath("xmlns:user")
43
47
  if owner
44
- hash["owner_login"] = owner.at_xpath("xmlns:login").content
48
+ hash["owner_login"] = strip(owner.at_xpath("xmlns:login").content)
45
49
  end
46
50
  hash["datastreams"] = environment.xpath("xmlns:data").collect do |datastream|
47
51
  current_value = datastream.at_xpath("xmlns:current_value")
52
+ if current_value
53
+ value_hash = {
54
+ "current_value" => strip(current_value.content),
55
+ "updated" => current_value.attributes["at"].value,
56
+ }
57
+ else
58
+ value_hash = {}
59
+ end
48
60
  unit = datastream.at_xpath("xmlns:unit")
49
61
  if unit
50
62
  unit_hash = {
51
- "unit_label" => unit.content,
63
+ "unit_label" => strip(unit.content),
52
64
  "unit_type" => unit.attributes["type"].value,
53
65
  "unit_symbol" => unit.attributes["symbol"].value,
54
66
  }
55
67
  else
56
68
  unit_hash = {}
57
69
  end
70
+ if (tags = datastream.xpath("xmlns:tag").collect { |t| t.content.strip }).any?
71
+ tags_hash = { "tags" => Cosm::CSV.generate_line(tags.sort { |a, b| a.downcase <=> b.downcase }).strip }
72
+ else
73
+ tags_hash = {}
74
+ end
58
75
  {
59
76
  "id" => datastream.attributes["id"].value,
60
- "tags" => datastream.xpath("xmlns:tag").collect(&:content).sort{|a,b| a.downcase <=> b.downcase}.join(','),
61
- "current_value" => current_value.content,
62
- "updated" => current_value.attributes["at"].value,
63
- "min_value" => datastream.at_xpath("xmlns:min_value").content,
64
- "max_value" => datastream.at_xpath("xmlns:max_value").content,
77
+ "min_value" => strip(datastream.at_xpath("xmlns:min_value").content),
78
+ "max_value" => strip(datastream.at_xpath("xmlns:max_value").content),
65
79
  "datapoints" => datastream.xpath("xmlns:datapoints").collect do |datapoint|
66
80
  value = datapoint.at_xpath("xmlns:value")
67
81
  {
68
82
  "at" => value.attributes["at"].value,
69
- "value" => value.content,
83
+ "value" => strip(value.content),
70
84
  }
71
85
  end
72
- }.merge(unit_hash)
86
+ }.merge(value_hash).merge(unit_hash).merge(tags_hash)
73
87
  end
74
88
  hash
75
89
  end
@@ -78,21 +92,22 @@ module Cosm
78
92
  def transform_5(xml)
79
93
  hash = {}
80
94
  environment = xml.at_xpath("//xmlns:environment")
95
+ raise InvalidXMLError, "Missing 'environment' node from base node" if environment.nil?
81
96
  hash["updated"] = environment.attributes["updated"].value
82
97
  hash["creator"] = "http://www.haque.co.uk"
83
- hash["title"] = environment.at_xpath("xmlns:title").content
84
- hash["feed"] = environment.at_xpath("xmlns:feed").content
85
- hash["status"] = environment.at_xpath("xmlns:status").content
86
- hash["description"] = environment.at_xpath("xmlns:description").content
87
- hash["icon"] = environment.at_xpath("xmlns:icon").content
88
- hash["website"] = environment.at_xpath("xmlns:website").content
89
- hash["email"] = environment.at_xpath("xmlns:email").content
98
+ hash["title"] = strip(environment.at_xpath("xmlns:title").content)
99
+ hash["feed"] = strip(environment.at_xpath("xmlns:feed").content)
100
+ hash["status"] = strip(environment.at_xpath("xmlns:status").content)
101
+ hash["description"] = strip(environment.at_xpath("xmlns:description").content)
102
+ hash["icon"] = strip(environment.at_xpath("xmlns:icon").content)
103
+ hash["website"] = strip(environment.at_xpath("xmlns:website").content)
104
+ hash["email"] = strip(environment.at_xpath("xmlns:email").content)
90
105
  location = environment.at_xpath("xmlns:location")
91
106
  if location
92
- hash["location_name"] = location.at_xpath("xmlns:name").content
93
- hash["location_lat"] = location.at_xpath("xmlns:lat").content
94
- hash["location_lon"] = location.at_xpath("xmlns:lon").content
95
- hash["location_ele"] = location.at_xpath("xmlns:ele").content
107
+ hash["location_name"] = strip(location.at_xpath("xmlns:name").content)
108
+ hash["location_lat"] = strip(location.at_xpath("xmlns:lat").content)
109
+ hash["location_lon"] = strip(location.at_xpath("xmlns:lon").content)
110
+ hash["location_ele"] = strip(location.at_xpath("xmlns:ele").content)
96
111
  hash["location_domain"] = location.attributes["domain"].value
97
112
  hash["location_exposure"] = location.attributes["exposure"].value
98
113
  hash["location_disposition"] = location.attributes["disposition"].value
@@ -102,24 +117,33 @@ module Cosm
102
117
  unit = datastream.at_xpath("xmlns:unit")
103
118
  if unit
104
119
  unit_hash = {
105
- "unit_label" => unit.content,
120
+ "unit_label" => strip(unit.content),
106
121
  "unit_type" => unit.attributes["type"].value,
107
122
  "unit_symbol" => unit.attributes["symbol"].value,
108
123
  }
109
124
  else
110
125
  unit_hash = {}
111
126
  end
127
+ if (tags = datastream.xpath("xmlns:tag").collect { |t| t.content.strip }).any?
128
+ tags_hash = { "tags" => Cosm::CSV.generate_line(tags.sort { |a, b| a.downcase <=> b.downcase }).strip }
129
+ else
130
+ tags_hash = {}
131
+ end
112
132
  {
113
133
  "id" => datastream.attributes["id"].value,
114
- "tags" => datastream.xpath("xmlns:tag").collect(&:content).sort{|a,b| a.downcase <=> b.downcase}.join(','),
115
- "current_value" => current_value.content,
134
+ "current_value" => strip(current_value.content),
116
135
  "updated" => environment.attributes["updated"].value,
117
136
  "min_value" => current_value.attributes["minValue"].value,
118
137
  "max_value" => current_value.attributes["maxValue"].value,
119
- }.merge(unit_hash)
138
+ }.merge(unit_hash).merge(tags_hash)
120
139
  end
121
140
  hash
122
141
  end
142
+
143
+ def strip(value)
144
+ return value.nil? ? nil : value.strip
145
+ end
146
+ private :strip
123
147
  end
124
148
  end
125
149
  end
@@ -6,13 +6,13 @@ module Cosm
6
6
  options[:depth] = 4 if options[:full]
7
7
  case options[:depth].to_i
8
8
  when 4
9
- ::CSV.generate_line([feed_id, datastream_id, at.iso8601(6), value]).strip
9
+ Cosm::CSV.generate_line([feed_id, datastream_id, at.iso8601(6), value]).strip
10
10
  when 3
11
- ::CSV.generate_line([datastream_id, at.iso8601(6), value]).strip
11
+ Cosm::CSV.generate_line([datastream_id, at.iso8601(6), value]).strip
12
12
  when 2
13
- ::CSV.generate_line([at.iso8601(6), value]).strip
13
+ Cosm::CSV.generate_line([at.iso8601(6), value]).strip
14
14
  else
15
- ::CSV.generate_line([value]).strip
15
+ Cosm::CSV.generate_line([value]).strip
16
16
  end
17
17
  end
18
18
  end
@@ -30,11 +30,11 @@ module Cosm
30
30
  datapoints.collect {|datapoint| csv << [datapoint.at.iso8601(6), datapoint.value] }
31
31
  csv << [updated.iso8601(6), current_value] if csv.empty?
32
32
  end
33
- csv.collect {|row| ::CSV.generate_line(row).strip }.join("\n")
33
+ csv.collect {|row| Cosm::CSV.generate_line(row).strip }.join("\n")
34
34
  end
35
35
 
36
36
  def csv_1
37
- ::CSV.generate_line([current_value]).strip
37
+ Cosm::CSV.generate_line([current_value]).strip
38
38
  end
39
39
  end
40
40
  end
@@ -18,9 +18,9 @@ module Cosm
18
18
  if options[:full]
19
19
  datastreams.collect do |datastream|
20
20
  if datastream.datapoints.any?
21
- datastream.datapoints.collect { |datapoint| csv << ::CSV.generate_line([id, datastream.id, datapoint.at.iso8601(6), datapoint.value]).strip }
21
+ datastream.datapoints.collect { |datapoint| csv << Cosm::CSV.generate_line([id, datastream.id, datapoint.at.iso8601(6), datapoint.value]).strip }
22
22
  else
23
- csv << ::CSV.generate_line([id, datastream.id, datastream.updated.iso8601(6), datastream.current_value]).strip
23
+ csv << Cosm::CSV.generate_line([id, datastream.id, datastream.updated.iso8601(6), datastream.current_value]).strip
24
24
  end
25
25
 
26
26
 
@@ -28,9 +28,9 @@ module Cosm
28
28
  else
29
29
  datastreams.collect do |datastream|
30
30
  if datastream.datapoints.any?
31
- datastream.datapoints.collect { |datapoint| csv << ::CSV.generate_line([datastream.id, datapoint.at.iso8601(6), datapoint.value]).strip }
31
+ datastream.datapoints.collect { |datapoint| csv << Cosm::CSV.generate_line([datastream.id, datapoint.at.iso8601(6), datapoint.value]).strip }
32
32
  else
33
- csv << ::CSV.generate_line([datastream.id, datastream.updated.iso8601(6), datastream.current_value]).strip
33
+ csv << Cosm::CSV.generate_line([datastream.id, datastream.updated.iso8601(6), datastream.current_value]).strip
34
34
  end
35
35
  end
36
36
  end
@@ -38,7 +38,7 @@ module Cosm
38
38
  end
39
39
 
40
40
  def csv_1
41
- ::CSV.generate_line(datastreams.collect {|ds| ds.current_value }).strip
41
+ Cosm::CSV.generate_line(datastreams.collect {|ds| ds.current_value }).strip
42
42
  end
43
43
  end
44
44
  end
@@ -1,3 +1,3 @@
1
1
  module Cosm #:nodoc:
2
- VERSION = '0.0.3'
2
+ VERSION = '0.0.5'
3
3
  end
@@ -93,6 +93,7 @@ describe Cosm::Datastream do
93
93
  @datastream.errors[:unit_type].should == ["is not a valid unit_type (pick one from #{Cosm::Datastream::VALID_UNIT_TYPES.join(', ')} or leave blank)"]
94
94
  end
95
95
  end
96
+
96
97
  end
97
98
 
98
99
  describe "#initialize" do
@@ -7,6 +7,28 @@ describe "default datastream csv parser" do
7
7
  datastream = Cosm::Datastream.new(csv)
8
8
  datastream.should fully_represent_datastream(:csv, csv)
9
9
  end
10
+
11
+ it "should capture timestamp if present" do
12
+ timestamp = Time.now.iso8601(6)
13
+ csv = "#{timestamp},123"
14
+ datastream = Cosm::Datastream.new(csv)
15
+ datastream.updated.should == timestamp
16
+ datastream.current_value.should == "123"
17
+ end
18
+
19
+ it "should raise error if passed more than a single row" do
20
+ csv = "12\n13"
21
+ expect {
22
+ Cosm::Datastream.new(csv)
23
+ }.to raise_error(Cosm::Parsers::CSV::InvalidCSVError)
24
+ end
25
+
26
+ it "should raise error passed more than three values in a row" do
27
+ csv = "#{Time.now.iso8601(6)},123,456"
28
+ expect {
29
+ Cosm::Datastream.new(csv)
30
+ }.to raise_error(Cosm::Parsers::CSV::InvalidCSVError)
31
+ end
10
32
  end
11
33
  end
12
34
 
@@ -8,6 +8,12 @@ describe "default feed csv parser" do
8
8
  feed.should fully_represent_feed(:csv_v2, csv)
9
9
  end
10
10
 
11
+ it "should convert no timestamp v2 CSV into attributes hash" do
12
+ csv = feed_as_(:csv, :version => 'v2_notimestamp')
13
+ feed = Cosm::Feed.new(csv)
14
+ feed.should fully_represent_feed(:csv_v2, csv)
15
+ end
16
+
11
17
  it "should convert Pachube CSV v1 into attributes hash" do
12
18
  csv = feed_as_(:csv, :version => 'v1')
13
19
  feed = Cosm::Feed.new(csv)
@@ -30,6 +36,18 @@ describe "default feed csv parser" do
30
36
  feed = Cosm::Feed.new(csv, :v1)
31
37
  feed.should fully_represent_feed(:csv_v1, csv)
32
38
  end
39
+
40
+ it "should raise an error if passed some wild csv with more than max permitted three columns" do
41
+ csv =<<-CSV
42
+ Date-Time, System HOA,Jockey Pump HOA,VFD Pump HOA,Lag Pump HOA,Lag Pump 2 HOA,Power Monitor,Water Level Relay,High Discharge Pressure,Reset Function,Jockey Running,VFD Run,Lag Pump Run,VFD Fault,Filter In Auto,Filter In Hand,Differential Press 1,Filter 1 Running,High Limit Switch,Low Limit Switch,Lag Pump Running,VFD Run Output Auto,VFD Pump On,Lag Pump,Lag Pump 1 On,System Auto Mode,Fault,Lag Pump 2 Run,Jockey On,Jockey Pump Run,Lag Pump 2,Filter Forward,Filter Reverse,Filter Solenoid,Pressure,Flow,Unknown?,VFD Input,VFD Output,
43
+ 2009;Apr;19;12;44;15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
44
+ 2009;Apr;19;12;44;30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
45
+ 2009;Apr;19;12;48;52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
46
+ CSV
47
+ expect {
48
+ Cosm::Feed.new(csv)
49
+ }.to raise_error(Cosm::Parsers::CSV::InvalidCSVError)
50
+ end
33
51
  end
34
52
  end
35
53
 
@@ -13,6 +13,28 @@ describe "default feed json parser" do
13
13
  feed = Cosm::Feed.new(json)
14
14
  feed.should fully_represent_feed(:json, json)
15
15
  end
16
+
17
+ it "should convert Pachube JSON 0.6-alpha (used by API v1) into attributes hash" do
18
+ json = feed_as_(:json, :version => "0.6")
19
+ feed = Cosm::Feed.new(json)
20
+ feed.should fully_represent_feed(:json, json)
21
+ end
22
+
23
+ it "should handle json if no value present" do
24
+ json = "{\"version\":\"0.6-alpha\",\"datastreams\":[{\"unit\":{\"label\":\"Tmax\",\"symbol\":\"C\"},\"values\":{},\"id\":\"1\"}]}"
25
+ expect {
26
+ feed = Cosm::Feed.new(json)
27
+ feed.datastreams.size.should == 1
28
+ }.to_not raise_error
29
+ end
30
+
31
+ it "should capture empty fields if present" do
32
+ json = "{\"version\":\"1.0.0\",\"description\":\"\",\"feed\":\"\",\"location\":{\"name\":\"\"}}"
33
+ feed = Cosm::Feed.new(json)
34
+ feed.description.should == ""
35
+ feed.feed.should == ""
36
+ feed.location_name.should == ""
37
+ end
16
38
  end
17
39
  end
18
40
 
@@ -27,6 +27,38 @@ describe "default feed xml parser" do
27
27
  Cosm::Feed.new(@xml).should fully_represent_feed(:xml, @xml)
28
28
  end
29
29
 
30
+ it "should gracefully handle 0.5.1 xml missing the base environment node" do
31
+ xml = <<-EOXML
32
+ <?xml version="1.0" encoding="UTF-8"?>
33
+ <eeml xmlns="http://www.eeml.org/xsd/0.5.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="0.5.1" xsi:schemaLocation="http://www.eeml.org/xsd/005 http://www.eeml.org/xsd/005/005.xsd">
34
+ <title>ohai</title>
35
+ </eeml>
36
+ EOXML
37
+ expect {
38
+ Cosm::Feed.new(xml)
39
+ }.to raise_error(Cosm::Parsers::XML::InvalidXMLError)
40
+ end
41
+
42
+ it "should handle datastream with no current_value" do
43
+ xml = <<-EOXML
44
+ <?xml version="1.0" encoding="UTF-8"?>
45
+ <eeml xmlns="http://www.eeml.org/xsd/0.5.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="0.5.1" xsi:schemaLocation="http://www.eeml.org/xsd/0.5.1 http://www.eeml.org/xsd/0.5.1/0.5.1.xsd">
46
+ <environment updated="2011-02-16T16:21:01.834174Z" id="504" creator="http://test.host/users/fred">
47
+ <title>Cosm Office environment</title>
48
+ <data id="0">
49
+ <tag>freakin lasers</tag>
50
+ <tag>humidity</tag>
51
+ <tag>Temperature</tag>
52
+ </data>
53
+ </environment>
54
+ </eeml>
55
+ EOXML
56
+
57
+ feed = Cosm::Feed.new(xml)
58
+ feed.datastreams.size.should == 1
59
+ feed.datastreams.first.tags.should == "freakin lasers,humidity,Temperature"
60
+ end
61
+
30
62
  end
31
63
 
32
64
  context "5 (used by API v1)" do
@@ -57,9 +89,47 @@ describe "default feed xml parser" do
57
89
 
58
90
  it "should handle missing value attributes" do
59
91
  @xml = feed_as_(:xml, :version => "5", :except_node => :value_attributes)
92
+ feed = Cosm::Feed.new(@xml)
60
93
  Cosm::Feed.new(@xml).should fully_represent_feed(:xml, @xml)
61
94
  end
62
95
 
96
+ it "should gracefully handle 0.5.1 xml missing the base environment node" do
97
+ xml = <<-EOXML
98
+ <?xml version="1.0" encoding="UTF-8"?>
99
+ <eeml xmlns="http://www.eeml.org/xsd/005" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="5" xsi:schemaLocation="http://www.eeml.org/xsd/005 http://www.eeml.org/xsd/005/005.xsd">
100
+ <title>ohai</title>
101
+ </eeml>
102
+ EOXML
103
+ expect {
104
+ Cosm::Feed.new(xml)
105
+ }.to raise_error(Cosm::Parsers::XML::InvalidXMLError)
106
+ end
107
+
108
+ it "should gracefully handle our oddly whitespaced real example" do
109
+ xml = <<-EOXML
110
+ <?xml version="1.0" encoding="UTF-8"?>
111
+ <eeml version="5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.eeml.org/xsd/005" xsi:schemaLocation="http://www.eeml.org/xsd/005 http://www.eeml.org/xsd/005/005.xsd">
112
+ <environment>
113
+ <data id="4773635294300160">
114
+ <tag>
115
+ 10.F59894010800</tag>
116
+ <tag>
117
+ Living Room, S wall</tag>
118
+ <value>
119
+ 24.1875</value>
120
+ <unit type="derivedSI">
121
+ celsius</unit>
122
+ </data>
123
+ </environment>
124
+ </eeml>
125
+ EOXML
126
+ feed = Cosm::Feed.new(xml)
127
+
128
+ datastream = feed.datastreams.first
129
+ datastream.tags.should == "10.F59894010800,\"Living Room, S wall\""
130
+ datastream.current_value.should == "24.1875"
131
+ datastream.unit_label.should == "celsius"
132
+ end
63
133
  end
64
134
  end
65
135
 
@@ -29,13 +29,13 @@ describe "default datapoint json templates" do
29
29
  it "should escape stuff that could upset csv parsers" do
30
30
  @datapoint.value = "I \n , am not a csv"
31
31
  csv = @datapoint.generate_csv("2")
32
- csv.should == CSV.generate_line([@datapoint.value]).strip
32
+ csv.should == Cosm::CSV.generate_line([@datapoint.value]).strip
33
33
  end
34
34
 
35
35
  it "should escape characters that could upset csv parsers via full" do
36
36
  @datapoint.value = "I \n , am not a csv"
37
37
  csv = @datapoint.generate_csv("2", :full => true)
38
- csv.should == CSV.generate_line([@datapoint.feed_id, @datapoint.datastream_id, @datapoint.at.iso8601(6), @datapoint.value]).strip
38
+ csv.should == Cosm::CSV.generate_line([@datapoint.feed_id, @datapoint.datastream_id, @datapoint.at.iso8601(6), @datapoint.value]).strip
39
39
  end
40
40
  end
41
41
 
@@ -85,7 +85,7 @@ describe "default datastream json templates" do
85
85
  @datastream.current_value = "one,field"
86
86
  @datastream.datapoints = []
87
87
  csv = @datastream.generate_csv("2")
88
- csv.should == CSV.generate_line([@datastream.updated.iso8601(6),@datastream.current_value]).strip
88
+ csv.should == Cosm::CSV.generate_line([@datastream.updated.iso8601(6),@datastream.current_value]).strip
89
89
  end
90
90
 
91
91
  it "should escape characters that could upset csv parsers with datapoints" do
@@ -94,14 +94,14 @@ describe "default datastream json templates" do
94
94
  dp.value = "1,field"
95
95
  end
96
96
  csv = @datastream.generate_csv("2")
97
- csv.should == @datastream.datapoints.collect {|dp| CSV.generate_line([dp.at.iso8601(6),dp.value]).strip }.join("\n")
97
+ csv.should == @datastream.datapoints.collect {|dp| Cosm::CSV.generate_line([dp.at.iso8601(6),dp.value]).strip }.join("\n")
98
98
  end
99
99
 
100
100
  it "should escape characters that could upset csv parsers without datapoints via full" do
101
101
  @datastream.current_value = "one,field"
102
102
  @datastream.datapoints = []
103
103
  csv = @datastream.generate_csv("2", :full => true)
104
- csv.should == CSV.generate_line([@datastream.feed_id,@datastream.id,@datastream.updated.iso8601(6),@datastream.current_value]).strip
104
+ csv.should == Cosm::CSV.generate_line([@datastream.feed_id,@datastream.id,@datastream.updated.iso8601(6),@datastream.current_value]).strip
105
105
  end
106
106
 
107
107
  it "should escape characters that could upset csv parsers with datapoints via full" do
@@ -110,7 +110,7 @@ describe "default datastream json templates" do
110
110
  dp.value = "1,field"
111
111
  end
112
112
  csv = @datastream.generate_csv("2", :full => true)
113
- csv.should == @datastream.datapoints.collect {|dp| CSV.generate_line([@datastream.feed_id,@datastream.id,dp.at.iso8601(6),dp.value]).strip }.join("\n")
113
+ csv.should == @datastream.datapoints.collect {|dp| Cosm::CSV.generate_line([@datastream.feed_id,@datastream.id,dp.at.iso8601(6),dp.value]).strip }.join("\n")
114
114
  end
115
115
  end
116
116
 
@@ -124,7 +124,7 @@ describe "default datastream json templates" do
124
124
  it "should escape characters that could upset csv parsers" do
125
125
  @datastream.current_value = "I \n am full of c,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, evil"
126
126
  csv = @datastream.generate_csv("1")
127
- csv.should == CSV.generate_line([@datastream.current_value]).strip
127
+ csv.should == Cosm::CSV.generate_line([@datastream.current_value]).strip
128
128
  end
129
129
  end
130
130
  end
@@ -22,7 +22,7 @@ describe "default feed json templates" do
22
22
  end
23
23
  csv = @feed.generate_csv("2")
24
24
  expected_csv = @feed.datastreams.collect do |datastream|
25
- CSV.generate_line([datastream.id, datastream.updated.iso8601(6), datastream.current_value]).strip
25
+ Cosm::CSV.generate_line([datastream.id, datastream.updated.iso8601(6), datastream.current_value]).strip
26
26
  end.join("\n")
27
27
  csv.should == expected_csv
28
28
  end
@@ -33,7 +33,7 @@ describe "default feed json templates" do
33
33
  end
34
34
  csv = @feed.generate_csv("2", :full => true)
35
35
  expected_csv = @feed.datastreams.collect do |datastream|
36
- CSV.generate_line([@feed.id, datastream.id, datastream.updated.iso8601(6), datastream.current_value]).strip
36
+ Cosm::CSV.generate_line([@feed.id, datastream.id, datastream.updated.iso8601(6), datastream.current_value]).strip
37
37
  end.join("\n")
38
38
  csv.should == expected_csv
39
39
  end
@@ -42,9 +42,9 @@ describe "default feed json templates" do
42
42
  csv = @feed.generate_csv("2")
43
43
  expected_csv = @feed.datastreams.collect do |datastream|
44
44
  if datastream.datapoints.any?
45
- datastream.datapoints.collect {|dp| CSV.generate_line([datastream.id, dp.at.iso8601(6), dp.value]).strip }
45
+ datastream.datapoints.collect {|dp| Cosm::CSV.generate_line([datastream.id, dp.at.iso8601(6), dp.value]).strip }
46
46
  else
47
- CSV.generate_line([datastream.id, datastream.updated.iso8601(6), datastream.current_value]).strip
47
+ Cosm::CSV.generate_line([datastream.id, datastream.updated.iso8601(6), datastream.current_value]).strip
48
48
  end
49
49
  end.join("\n")
50
50
  csv.should == expected_csv
@@ -54,9 +54,9 @@ describe "default feed json templates" do
54
54
  csv = @feed.generate_csv("2", :full => true)
55
55
  expected_csv = @feed.datastreams.collect do |datastream|
56
56
  if datastream.datapoints.any?
57
- datastream.datapoints.collect {|dp| CSV.generate_line([@feed.id, datastream.id, dp.at.iso8601(6), dp.value]).strip }
57
+ datastream.datapoints.collect {|dp| Cosm::CSV.generate_line([@feed.id, datastream.id, dp.at.iso8601(6), dp.value]).strip }
58
58
  else
59
- CSV.generate_line([@feed.id, datastream.id, datastream.updated.iso8601(6), datastream.current_value]).strip
59
+ Cosm::CSV.generate_line([@feed.id, datastream.id, datastream.updated.iso8601(6), datastream.current_value]).strip
60
60
  end
61
61
  end.join("\n")
62
62
  csv.should == expected_csv
@@ -68,7 +68,7 @@ describe "default feed json templates" do
68
68
  it "should represent Pachube JSON" do
69
69
  csv = @feed.generate_csv("1")
70
70
  expected_csv = @feed.datastreams.collect do |datastream|
71
- CSV.generate_line([datastream.current_value]).strip
71
+ Cosm::CSV.generate_line([datastream.current_value]).strip
72
72
  end.join(",")
73
73
  csv.should == expected_csv
74
74
  end
data/spec/spec_helper.rb CHANGED
@@ -5,6 +5,20 @@ require 'rspec'
5
5
 
6
6
  require 'time'
7
7
 
8
+ if !defined?(JRUBY_VERSION)
9
+ if RUBY_VERSION < "1.9"
10
+ require 'ruby-debug'
11
+ else
12
+ if ENV["COVERAGE"] == "on"
13
+ require 'simplecov'
14
+ SimpleCov.start do
15
+ add_filter "/spec/"
16
+ add_filter "/lib/cosm-rb.rb"
17
+ end
18
+ end
19
+ end
20
+ end
21
+
8
22
  Dir['./spec/support/**/*.rb'].map {|f| require f}
9
23
 
10
24
  $:.push File.expand_path("../lib", __FILE__)
@@ -159,6 +159,16 @@ def feed_as_csv(version)
159
159
  4,2011-06-13T12:30:04.714629Z,0
160
160
  5,2011-06-13T12:30:04.714629Z,0
161
161
  6,2011-06-13T12:30:04.714629Z,-30362
162
+ }
163
+ when 'v2_notimestamp'
164
+ %Q{
165
+ 0,15
166
+ 1,905
167
+ 2,326
168
+ 3,0
169
+ 4,0
170
+ 5,0
171
+ 6,-30362
162
172
  }
163
173
  when 'unknown'
164
174
  '34,98'
@@ -265,7 +275,7 @@ def feed_as_json(version)
265
275
  }
266
276
  ]
267
277
  }
268
- when "0.6-alpha"
278
+ when "0.6-alpha", "0.6"
269
279
  {
270
280
  "datastreams" => [{
271
281
  "tags" => ["humidity"],
@@ -14,7 +14,7 @@ RSpec::Matchers.define :fully_represent_feed do |format, formatted_feed|
14
14
  end
15
15
 
16
16
  failure_message_for_should do |feed|
17
- "expected #{feed} to fully represent #{formatted_feed}"
17
+ "expected #{feed.attributes.inspect} to fully represent #{formatted_feed}"
18
18
  end
19
19
 
20
20
  description do
@@ -22,7 +22,7 @@ RSpec::Matchers.define :fully_represent_feed do |format, formatted_feed|
22
22
  end
23
23
 
24
24
  def match_csv_v1_feed(feed, formatted_feed)
25
- csv = CSV.parse(formatted_feed.strip)
25
+ csv = Cosm::CSV.parse(formatted_feed.strip)
26
26
  csv.length.should == 1
27
27
  csv = csv.first
28
28
  feed.datastreams.length.should == csv.length
@@ -33,11 +33,14 @@ RSpec::Matchers.define :fully_represent_feed do |format, formatted_feed|
33
33
  end
34
34
 
35
35
  def match_csv_v2_feed(feed, formatted_feed)
36
- csv = CSV.parse(formatted_feed.strip)
36
+ csv = Cosm::CSV.parse(formatted_feed.strip)
37
37
  feed.datastreams.length.should == csv.length
38
38
  feed.datastreams.each do |datastream|
39
39
  row = csv.detect {|d| d.first == datastream.id}
40
40
  datastream.current_value.should == row.last
41
+ if row.size == 3
42
+ datastream.updated.iso8601.should == row[1]
43
+ end
41
44
  end
42
45
  end
43
46
 
@@ -60,7 +63,9 @@ RSpec::Matchers.define :fully_represent_feed do |format, formatted_feed|
60
63
  feed.website.should == environment.at_xpath("xmlns:website").content
61
64
  feed.email.should == environment.at_xpath("xmlns:email").content
62
65
  feed.private.should == environment.at_xpath("xmlns:private").content
63
- feed.tags.should == environment.xpath("xmlns:tag").map(&:content).sort{|a,b| a.downcase<=>b.downcase}.join(',')
66
+ if feed.tags
67
+ feed.tags.should == environment.xpath("xmlns:tag").map(&:content).sort{|a,b| a.downcase<=>b.downcase}.join(',')
68
+ end
64
69
  owner = environment.at_xpath("xmlns:user")
65
70
  if owner
66
71
  feed.owner_login.should == owner.at_xpath("xmlns:login").content
@@ -78,7 +83,9 @@ RSpec::Matchers.define :fully_represent_feed do |format, formatted_feed|
78
83
  feed.datastreams.each do |ds|
79
84
  data = environment.at_xpath("xmlns:data[@id=\"#{ds.id}\"]")
80
85
  ds.id.should == data.attributes["id"].value
81
- ds.tags.should == data.xpath("xmlns:tag").map(&:content).sort{|a,b| a.downcase<=>b.downcase}.join(',')
86
+ if (tags = data.xpath("xmlns:tag").collect { |t| t.content.strip }).any?
87
+ ds.tags.should == tags.sort{|a,b| a.downcase<=>b.downcase}.join(',')
88
+ end
82
89
  current_value = data.at_xpath("xmlns:current_value")
83
90
  ds.current_value.should == current_value.content
84
91
  ds.updated.should == current_value.attributes["at"].value
@@ -120,7 +127,9 @@ RSpec::Matchers.define :fully_represent_feed do |format, formatted_feed|
120
127
  feed.datastreams.each do |ds|
121
128
  data = environment.at_xpath("xmlns:data[@id=\"#{ds.id}\"]")
122
129
  ds.id.should == data.attributes["id"].value
123
- ds.tags.should == data.xpath("xmlns:tag").map(&:content).sort{|a,b| a.downcase<=>b.downcase}.join(',')
130
+ if (tags = data.xpath("xmlns:tag").collect { |t| t.content.strip }).any?
131
+ ds.tags.should == tags.sort{ |a,b| a.downcase <=> b.downcase }.join(',')
132
+ end
124
133
  current_value = data.at_xpath("xmlns:value")
125
134
  ds.current_value.should == current_value.content
126
135
  ds.updated.should == environment.attributes["updated"].value
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cosm-rb
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 21
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 3
10
- version: 0.0.3
9
+ - 5
10
+ version: 0.0.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Paul Bellamy
@@ -17,12 +17,9 @@ autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
19
 
20
- date: 2012-06-11 00:00:00 +01:00
21
- default_executable:
20
+ date: 2012-07-10 00:00:00 Z
22
21
  dependencies:
23
22
  - !ruby/object:Gem::Dependency
24
- prerelease: false
25
- type: :runtime
26
23
  version_requirements: &id001 !ruby/object:Gem::Requirement
27
24
  none: false
28
25
  requirements:
@@ -34,11 +31,11 @@ dependencies:
34
31
  - 8
35
32
  - 1
36
33
  version: 0.8.1
34
+ type: :runtime
35
+ prerelease: false
37
36
  requirement: *id001
38
37
  name: yajl-ruby
39
38
  - !ruby/object:Gem::Dependency
40
- prerelease: false
41
- type: :runtime
42
39
  version_requirements: &id002 !ruby/object:Gem::Requirement
43
40
  none: false
44
41
  requirements:
@@ -50,11 +47,11 @@ dependencies:
50
47
  - 4
51
48
  - 4
52
49
  version: 1.4.4
50
+ type: :runtime
51
+ prerelease: false
53
52
  requirement: *id002
54
53
  name: nokogiri
55
54
  - !ruby/object:Gem::Dependency
56
- prerelease: false
57
- type: :runtime
58
55
  version_requirements: &id003 !ruby/object:Gem::Requirement
59
56
  none: false
60
57
  requirements:
@@ -66,12 +63,28 @@ dependencies:
66
63
  - 8
67
64
  - 3
68
65
  version: 0.8.3
66
+ type: :runtime
67
+ prerelease: false
69
68
  requirement: *id003
70
69
  name: httparty
71
70
  - !ruby/object:Gem::Dependency
72
- prerelease: false
73
- type: :development
74
71
  version_requirements: &id004 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ hash: 121
77
+ segments:
78
+ - 1
79
+ - 5
80
+ - x
81
+ version: 1.5.x
82
+ type: :runtime
83
+ prerelease: false
84
+ requirement: *id004
85
+ name: fastercsv
86
+ - !ruby/object:Gem::Dependency
87
+ version_requirements: &id005 !ruby/object:Gem::Requirement
75
88
  none: false
76
89
  requirements:
77
90
  - - ">="
@@ -80,12 +93,12 @@ dependencies:
80
93
  segments:
81
94
  - 0
82
95
  version: "0"
83
- requirement: *id004
96
+ type: :development
97
+ prerelease: false
98
+ requirement: *id005
84
99
  name: ruby-debug
85
100
  - !ruby/object:Gem::Dependency
86
- prerelease: false
87
- type: :development
88
- version_requirements: &id005 !ruby/object:Gem::Requirement
101
+ version_requirements: &id006 !ruby/object:Gem::Requirement
89
102
  none: false
90
103
  requirements:
91
104
  - - ">="
@@ -96,12 +109,12 @@ dependencies:
96
109
  - 9
97
110
  - 9
98
111
  version: 0.9.9
99
- requirement: *id005
112
+ type: :development
113
+ prerelease: false
114
+ requirement: *id006
100
115
  name: rcov
101
116
  - !ruby/object:Gem::Dependency
102
- prerelease: false
103
- type: :development
104
- version_requirements: &id006 !ruby/object:Gem::Requirement
117
+ version_requirements: &id007 !ruby/object:Gem::Requirement
105
118
  none: false
106
119
  requirements:
107
120
  - - "="
@@ -112,12 +125,12 @@ dependencies:
112
125
  - 8
113
126
  - 7
114
127
  version: 0.8.7
115
- requirement: *id006
128
+ type: :development
129
+ prerelease: false
130
+ requirement: *id007
116
131
  name: rake
117
132
  - !ruby/object:Gem::Dependency
118
- prerelease: false
119
- type: :development
120
- version_requirements: &id007 !ruby/object:Gem::Requirement
133
+ version_requirements: &id008 !ruby/object:Gem::Requirement
121
134
  none: false
122
135
  requirements:
123
136
  - - "="
@@ -128,7 +141,9 @@ dependencies:
128
141
  - 6
129
142
  - 0
130
143
  version: 2.6.0
131
- requirement: *id007
144
+ type: :development
145
+ prerelease: false
146
+ requirement: *id008
132
147
  name: rspec
133
148
  description: A library for communicating with the Cosm REST API, parsing and rendering Cosm feed formats
134
149
  email:
@@ -265,7 +280,6 @@ files:
265
280
  - spec/support/key_helper.rb
266
281
  - spec/support/search_result_helper.rb
267
282
  - spec/support/trigger_helper.rb
268
- has_rdoc: true
269
283
  homepage: http://github.com/cosm/cosm-rb
270
284
  licenses: []
271
285
 
@@ -296,66 +310,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
296
310
  requirements: []
297
311
 
298
312
  rubyforge_project:
299
- rubygems_version: 1.6.2
313
+ rubygems_version: 1.8.22
300
314
  signing_key:
301
315
  specification_version: 3
302
316
  summary: A library for communicating with the Cosm REST API, parsing and rendering Cosm feed formats
303
- test_files:
304
- - spec/cosm-rb/array_extensions_spec.rb
305
- - spec/cosm-rb/base/instance_methods_spec.rb
306
- - spec/cosm-rb/base_spec.rb
307
- - spec/cosm-rb/client_spec.rb
308
- - spec/cosm-rb/datapoint_spec.rb
309
- - spec/cosm-rb/datastream_spec.rb
310
- - spec/cosm-rb/feed_spec.rb
311
- - spec/cosm-rb/hash_extensions_spec.rb
312
- - spec/cosm-rb/helpers_spec.rb
313
- - spec/cosm-rb/key_spec.rb
314
- - spec/cosm-rb/parsers/csv/datastream_defaults_spec.rb
315
- - spec/cosm-rb/parsers/csv/feed_defaults_spec.rb
316
- - spec/cosm-rb/parsers/json/datapoint_defaults_spec.rb
317
- - spec/cosm-rb/parsers/json/datastream_defaults_spec.rb
318
- - spec/cosm-rb/parsers/json/feed_defaults_spec.rb
319
- - spec/cosm-rb/parsers/json/key_defaults_spec.rb
320
- - spec/cosm-rb/parsers/json/search_result_defaults_spec.rb
321
- - spec/cosm-rb/parsers/json/trigger_defaults_spec.rb
322
- - spec/cosm-rb/parsers/xml/datapoint_defaults_spec.rb
323
- - spec/cosm-rb/parsers/xml/datastream_defaults_spec.rb
324
- - spec/cosm-rb/parsers/xml/feed_defaults_spec.rb
325
- - spec/cosm-rb/parsers/xml/key_defaults_spec.rb
326
- - spec/cosm-rb/parsers/xml/trigger_defaults_spec.rb
327
- - spec/cosm-rb/search_result_spec.rb
328
- - spec/cosm-rb/string_extensions_spec.rb
329
- - spec/cosm-rb/template_spec.rb
330
- - spec/cosm-rb/templates/csv/datapoint_defaults_spec.rb
331
- - spec/cosm-rb/templates/csv/datastream_defaults_spec.rb
332
- - spec/cosm-rb/templates/csv/feed_defaults_spec.rb
333
- - spec/cosm-rb/templates/json/datapoint_defaults_spec.rb
334
- - spec/cosm-rb/templates/json/datastream_defaults_spec.rb
335
- - spec/cosm-rb/templates/json/feed_defaults_spec.rb
336
- - spec/cosm-rb/templates/json/key_defaults_spec.rb
337
- - spec/cosm-rb/templates/json/search_result_defaults_spec.rb
338
- - spec/cosm-rb/templates/json/trigger_defaults_spec.rb
339
- - spec/cosm-rb/templates/xml/datapoint_defaults_spec.rb
340
- - spec/cosm-rb/templates/xml/datastream_defaults_spec.rb
341
- - spec/cosm-rb/templates/xml/feed_defaults_spec.rb
342
- - spec/cosm-rb/templates/xml/search_result_defaults_spec.rb
343
- - spec/cosm-rb/trigger_spec.rb
344
- - spec/fixtures/models.rb
345
- - spec/spec_helper.rb
346
- - spec/support/contain_datapoint_eeml_matcher.rb
347
- - spec/support/contain_datastream_eeml_matcher.rb
348
- - spec/support/contain_feed_eeml_matcher.rb
349
- - spec/support/datapoint_helper.rb
350
- - spec/support/datastream_helper.rb
351
- - spec/support/describe_eeml_matcher.rb
352
- - spec/support/feed_helper.rb
353
- - spec/support/fully_represent_datapoint_matcher.rb
354
- - spec/support/fully_represent_datastream_matcher.rb
355
- - spec/support/fully_represent_feed_matcher.rb
356
- - spec/support/fully_represent_key_matcher.rb
357
- - spec/support/fully_represent_search_result_matcher.rb
358
- - spec/support/fully_represent_trigger_matcher.rb
359
- - spec/support/key_helper.rb
360
- - spec/support/search_result_helper.rb
361
- - spec/support/trigger_helper.rb
317
+ test_files: []
318
+