cosm-rb 0.0.3 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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
+