bio-publisci 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/Gemfile +1 -1
  2. data/Rakefile +1 -1
  3. data/features/orm_steps.rb +4 -4
  4. data/features/reader.feature +3 -3
  5. data/features/reader_steps.rb +1 -0
  6. data/features/writer.feature +7 -2
  7. data/features/writer_steps.rb +8 -1
  8. data/lib/bio-publisci.rb +3 -1
  9. data/lib/bio-publisci/datacube_model.rb +46 -20
  10. data/lib/bio-publisci/dataset/ORM/data_cube_orm.rb +196 -194
  11. data/lib/bio-publisci/dataset/ORM/observation.rb +15 -13
  12. data/lib/bio-publisci/dataset/data_cube.rb +3 -3
  13. data/lib/bio-publisci/dataset/dataset_for.rb +25 -4
  14. data/lib/bio-publisci/dsl/dataset_dsl.rb +4 -2
  15. data/lib/bio-publisci/dsl/dsl.rb +3 -0
  16. data/lib/bio-publisci/metadata/generator.rb +1 -1
  17. data/lib/bio-publisci/metadata/metadata_model.rb +27 -0
  18. data/lib/bio-publisci/metadata/prov/activity.rb +1 -0
  19. data/lib/bio-publisci/metadata/prov/model/prov_models.rb +33 -2
  20. data/lib/bio-publisci/query/query_helper.rb +5 -1
  21. data/lib/bio-publisci/readers/arff.rb +2 -40
  22. data/lib/bio-publisci/readers/dataframe.rb +1 -1
  23. data/lib/bio-publisci/writers/arff.rb +42 -16
  24. data/lib/bio-publisci/writers/base.rb +77 -0
  25. data/lib/bio-publisci/writers/csv.rb +31 -0
  26. data/lib/bio-publisci/writers/dataframe.rb +2 -2
  27. data/resources/queries/codes.rq +10 -5
  28. data/resources/queries/dimensions.rq +9 -4
  29. data/resources/queries/measures.rq +7 -2
  30. data/resources/queries/observations.rq +5 -4
  31. data/resources/weather.numeric.arff +26 -21
  32. data/spec/ORM/data_cube_orm_spec.rb +23 -3
  33. data/spec/ORM/prov_model_spec.rb +53 -0
  34. data/spec/dataset_for_spec.rb +21 -0
  35. data/spec/dsl_spec.rb +5 -2
  36. data/spec/metadata/metadata_dsl_spec.rb +1 -1
  37. data/spec/r_builder_spec.rb +2 -2
  38. data/spec/turtle/bacon +1 -1
  39. data/spec/turtle/reference +1 -1
  40. data/spec/turtle/weather +275 -0
  41. data/spec/writer_spec.rb +61 -0
  42. metadata +66 -28
  43. checksums.yaml +0 -7
data/Gemfile CHANGED
@@ -14,7 +14,7 @@ group :development do
14
14
  gem "bio", ">= 1.4.2"
15
15
  gem "rdoc", "~> 3.12"
16
16
  gem "spoon"
17
- gem "spira"
17
+ gem "spira", git: "https://github.com/ruby-rdf/spira.git"
18
18
  end
19
19
 
20
20
 
data/Rakefile CHANGED
@@ -21,7 +21,7 @@ Jeweler::Tasks.new do |gem|
21
21
  gem.description = %Q{A toolkit for publishing scientific results and datasets using RDF, OWL, and related technologies }
22
22
  gem.email = "wstrinz@gmail.com"
23
23
  gem.authors = ["Will Strinz"]
24
- gem.version = "0.0.7"
24
+ gem.version = "0.0.8"
25
25
 
26
26
  # dependencies defined in Gemfile
27
27
  end
@@ -1,7 +1,7 @@
1
1
  require_relative '../lib/bio-publisci.rb'
2
2
 
3
3
  Given /^an ORM::DataCube entitled "(.*?)"$/ do |name|
4
- @cube = PubliSci::ORM::DataCube.new(name: name)
4
+ @cube = PubliSci::DataSet::ORM::DataCube.new(name: name)
5
5
  end
6
6
 
7
7
  Given /^an ORM::DataCube entitled "(.*?)" with the following options:$/ do |name, opts|
@@ -18,7 +18,7 @@ Given /^an ORM::DataCube entitled "(.*?)" with the following options:$/ do |name
18
18
 
19
19
  options_hash[k] = v
20
20
  }
21
- @cube = PubliSci::ORM::DataCube.new(options_hash)
21
+ @cube = PubliSci::DataSet::ORM::DataCube.new(options_hash)
22
22
  end
23
23
 
24
24
  Given(/^a turtle string from file (.*)$/) do |file|
@@ -30,7 +30,7 @@ Given(/^the URI string "(.*?)"$/) do |uri|
30
30
  end
31
31
 
32
32
  When(/^I call the ORM::DataCube class method load on it$/) do
33
- @cube = PubliSci::ORM::DataCube.load(@string)
33
+ @cube = PubliSci::DataSet::ORM::DataCube.load(@string)
34
34
  end
35
35
 
36
36
  When /^I add a "(.*?)" dimension$/ do |dim|
@@ -70,5 +70,5 @@ Then /^the to_n3 method should return a string with a "(.*?)"$/ do |search|
70
70
  end
71
71
 
72
72
  Then(/^I should receive an ORM::DataCube object$/) do
73
- @cube.is_a?(PubliSci::ORM::DataCube).should == true
73
+ @cube.is_a?(PubliSci::DataSet::ORM::DataCube).should == true
74
74
  end
@@ -6,20 +6,20 @@ Feature: generate RDF
6
6
  Scenario: generate turtle RDF from a Dataframe
7
7
  Given a Dataframe generator
8
8
  When I provide an R dataframe and the label "mr"
9
- And generate a turtle string from it
9
+ And generate a turtle string from it
10
10
  Then the result should contain a "qb:dataSet"
11
11
  And the result should contain some "qb:Observation"s
12
12
 
13
13
  Scenario: generate turtle RDF from a CSV
14
14
  Given a CSV generator
15
15
  When I provide the reference file spec/csv/bacon.csv and the label "bacon"
16
- And generate a turtle string from it
16
+ And generate a turtle string from it
17
17
  Then the result should contain a "qb:dataSet"
18
18
  And the result should contain some "qb:Observation"s
19
19
 
20
20
  Scenario: generate turtle RDF from an ARFF file
21
21
  Given a ARFF generator
22
22
  When I provide the file resources/weather.numeric.arff
23
- And generate a turtle string from it
23
+ And generate a turtle string from it
24
24
  Then the result should contain a "qb:dataSet"
25
25
  And the result should contain some "qb:Observation"s
@@ -41,6 +41,7 @@ end
41
41
 
42
42
  When /^generate a turtle string from it$/ do
43
43
  @turtle_string = @generator.send :generate_n3, *@attr
44
+ # open('weather.ttl','w'){|f| f.write @turtle_string}
44
45
  end
45
46
 
46
47
  Then /^I should have access to a (.*) method$/ do |method|
@@ -1,9 +1,14 @@
1
1
  Feature: export to various formats using writers
2
2
 
3
3
  In order to use RDF encoded data in other applications
4
- I want to export domain objects using an PubliSci::Writer object
4
+ I want to export domain objects using an PubliSci::Writers object
5
5
 
6
6
  Scenario: write to ARFF format
7
7
  Given a ARFF writer
8
8
  When I call its from_turtle method on the file spec/turtle/bacon
9
- Then I should receive a .arff file as a string
9
+ Then I should receive a .arff file as a string
10
+
11
+ Scenario: write to CSV
12
+ Given a CSV writer
13
+ When I call its from_turtle method on the file spec/turtle/bacon
14
+ Then I should receive a .csv file as a string
@@ -1,5 +1,5 @@
1
1
  Given(/^a (.*) writer$/) do |type|
2
- @writer = PubliSci::Writer.const_get(type).new
2
+ @writer = PubliSci::Writers.const_get(type).new
3
3
  end
4
4
 
5
5
  When(/^I call its from_turtle method on the file (.*)$/) do |file|
@@ -13,5 +13,12 @@ When(/^I call its from_turtle method on the turtle string$/) do
13
13
  end
14
14
 
15
15
  Then(/^I should receive a \.arff file as a string$/) do
16
+ puts @result
16
17
  @result.is_a?(String).should be true
17
18
  end
19
+
20
+ Then(/^I should receive a \.csv file as a string$/) do
21
+ puts @result
22
+ @result.is_a?(String).should be true
23
+ end
24
+
@@ -34,9 +34,11 @@ load File.dirname(__FILE__) + '/bio-publisci/dataset/data_cube.rb'
34
34
  load File.dirname(__FILE__) + '/bio-publisci/dataset/dataset_for.rb'
35
35
  load File.dirname(__FILE__) + '/bio-publisci/dataset/configuration.rb'
36
36
  load File.dirname(__FILE__) + '/bio-publisci/dataset/dataset.rb'
37
+ load File.dirname(__FILE__) + '/bio-publisci/datacube_model.rb'
37
38
  load File.dirname(__FILE__) + '/bio-publisci/output.rb'
38
39
  load File.dirname(__FILE__) + '/bio-publisci/metadata/prov/element.rb'
39
40
  load File.dirname(__FILE__) + '/bio-publisci/metadata/prov/prov.rb'
41
+ load File.dirname(__FILE__) + '/bio-publisci/writers/base.rb'
40
42
 
41
43
 
42
44
  load_folder('bio-publisci/dsl')
@@ -47,7 +49,7 @@ load_folder('bio-publisci/readers')
47
49
  load_folder('bio-publisci/writers')
48
50
  load_folder('bio-publisci/dataset/ORM')
49
51
  # Dir.foreach(File.dirname(__FILE__) + '/generators') do |file|
50
- # unless file == "." or file == ".."
52
+ # unless file == "." or file == ".."
51
53
  # load File.dirname(__FILE__) + '/generators/' + file
52
54
  # end
53
55
  # end
@@ -2,14 +2,6 @@ require 'rdf/4store'
2
2
 
3
3
  module PubliSci
4
4
  module ORM
5
-
6
- # class Person < Spira::Base
7
- # configure :base_uri => "http://example.org/example/people"
8
-
9
- # property :name, :predicate => FOAF.name, :type => String
10
-
11
- # end
12
-
13
5
  # class Observation < Spira::Base
14
6
  # type RDF::URI.new('http://purl.org/linked-data/cube#Observation')
15
7
  # property :label, predicate: RDFS.label
@@ -25,13 +17,14 @@ module PubliSci
25
17
 
26
18
  class DataStructureDefinition < Spira::Base
27
19
  type QB.DataStructureDefinition
20
+ property :label, predicate: RDFS.label
28
21
  has_many :component, predicate: QB.component
29
22
  end
30
23
 
31
24
  class DataSet < Spira::Base
32
25
  type QB.DataSet
33
26
  property :label, predicate: RDFS.label
34
-
27
+ property :structure, predicate: QB.structure
35
28
  end
36
29
 
37
30
  class Dimension < Spira::Base
@@ -51,20 +44,53 @@ module PubliSci
51
44
  Spira.add_repository :default, repo
52
45
  end
53
46
 
54
- def observation
55
- unless PubliSci::ORM.const_defined?("Observation")
56
- obs = Class.new(Spira::Base) do
57
- type RDF::URI.new('http://purl.org/linked-data/cube#Observation')
47
+ # def observation
48
+ # unless PubliSci::ORM.const_defined?("Observation")
49
+ # obs = Class.new(Spira::Base) do
50
+ # type RDF::URI.new('http://purl.org/linked-data/cube#Observation')
58
51
 
59
- property :structure, predicate: QB.dataSet
52
+ # property :structure, predicate: QB.dataSet
60
53
 
61
- ((Dimension.each.to_a | Measure.each.to_a) || []).each{|component|
62
- property strip_uri(component.subject.to_s), predicate: component.subject
63
- }
64
- end
65
- PubliSci::ORM.const_set("Observation",obs)
54
+ # ((Dimension.each.to_a | Measure.each.to_a) || []).each{|component|
55
+ # property strip_uri(component.subject.to_s), predicate: component.subject
56
+ # }
57
+ # end
58
+ # PubliSci::ORM.const_set("Observation",obs)
59
+ # end
60
+ # Observation
61
+ # end
62
+
63
+ class Observation < Spira::Base
64
+ type QB.Observation
65
+ property :label, predicate: RDFS.label
66
+ property :dataset, predicate: QB.dataSet
67
+
68
+ def load_properties
69
+ comps = dataset.as(DataSet).structure.as(DataStructureDefinition).component.map{|comp| comp.as(Component)}
70
+ props = comps.map{|comp| comp.dimension ? comp.dimension.as(Dimension) : comp.measure.as(Measure) }
71
+ props.each{|prop|
72
+ ss = strip_uri(prop.subject.to_s)
73
+
74
+ self.class.property ss.to_sym, predicate: prop.subject
75
+ }
66
76
  end
67
- Observation
77
+
78
+ # for testing; DRY up eventually
79
+ def strip_uri(uri)
80
+ uri = uri.to_s.dup
81
+ uri[-1] = '' if uri[-1] == '>'
82
+ uri.to_s.split('/').last.split('#').last
83
+ end
84
+
85
+ # def method_missing(meth, *args, &block)
86
+ # if meth.to_s =~ /^find_by_(.+)$/
87
+ # run_find_by_method($1, *args, &block)
88
+ # else
89
+ # super # You *must* call super if you don't handle the
90
+ # # method, otherwise you'll mess up Ruby's method
91
+ # # lookup.
92
+ # end
93
+ # end
68
94
  end
69
95
 
70
96
  def reload_observation
@@ -1,238 +1,240 @@
1
1
  module PubliSci
2
- module ORM
3
- class DataCube
4
- extend PubliSci::Dataset::DataCube
5
- extend PubliSci::Analyzer
6
- # extend PubliSci::Metadata
7
- extend PubliSci::Query
8
- extend PubliSci::Parser
9
-
10
- include PubliSci::Dataset::DataCube
11
- include PubliSci::Analyzer
12
- include PubliSci::Metadata::Generator
13
- include PubliSci::Query
14
- include PubliSci::Parser
15
-
16
- attr_accessor :labels
17
- attr_accessor :dimensions
18
- attr_accessor :measures
19
- attr_accessor :obs
20
- attr_accessor :meta
21
-
22
- def initialize(options={},do_parse = true)
23
- @dimensions = {}
24
- @measures = []
25
- @obs = []
26
- @generator_options = {}
27
- @options = {}
28
-
29
- @meta = {}
30
-
31
- parse_options options if do_parse
32
- end
2
+ module DataSet
3
+ module ORM
4
+ class DataCube
5
+ extend PubliSci::Dataset::DataCube
6
+ extend PubliSci::Analyzer
7
+ # extend PubliSci::Metadata
8
+ extend PubliSci::Query
9
+ extend PubliSci::Parser
10
+
11
+ include PubliSci::Dataset::DataCube
12
+ include PubliSci::Analyzer
13
+ include PubliSci::Metadata::Generator
14
+ include PubliSci::Query
15
+ include PubliSci::Parser
16
+
17
+ attr_accessor :labels
18
+ attr_accessor :dimensions
19
+ attr_accessor :measures
20
+ attr_accessor :obs
21
+ attr_accessor :meta
22
+
23
+ def initialize(options={},do_parse = true)
24
+ @dimensions = {}
25
+ @measures = []
26
+ @obs = []
27
+ @generator_options = {}
28
+ @options = {}
29
+
30
+ @meta = {}
31
+
32
+ parse_options options if do_parse
33
+ end
33
34
 
34
- def self.load(graph,options={},verbose=false)
35
+ def self.load(graph,options={},verbose=false)
35
36
 
36
37
 
37
- graph = load_string(graph) unless graph =~ /^http/
38
+ graph = load_string(graph) unless graph =~ /^http/
38
39
 
39
- # puts get_hashes(execute_from_file('dimension_ranges.rq',graph))
40
- dimensions = Hash[get_hashes(execute_from_file('dimension_ranges.rq',graph),"to_s").map{|solution|
41
- #TODO coded properties should be found via SPARQL queries
42
- if solution[:range].split('/')[-2] == "code"
43
- type = :coded
44
- else
45
- type = solution[:range].to_s
46
- end
47
- [solution[:dimension], {type: type}]
48
- }]
49
- puts "dimensions: #{dimensions}" if verbose
50
-
51
- codes = execute_from_file('code_resources.rq',graph).to_h.map{|sol|
52
- [sol[:dimension].to_s, sol[:codeList].to_s, sol[:class].to_s]
53
- }
54
- puts "codes: #{codes}" if verbose
55
-
56
- measures = execute_from_file('measures.rq',graph).to_h.map{|m| m[:measure].to_s}
57
- puts "measures: #{measures}" if verbose
58
-
59
- name = execute_from_file('dataset.rq',graph).to_h.first[:label]
60
- puts "dataset: #{name}" if verbose
61
-
62
- obs = execute_from_file('observations.rq',graph)
63
- observations = observation_hash(obs)
64
- puts "observations: #{observations}" if verbose
65
-
66
- # simple_observations = observation_hash(obs,true)
67
-
68
- labels = execute_from_file('observation_labels.rq', graph)
69
- labels = Hash[labels.map{|sol|
70
- [sol[:observation].to_s, sol[:label].to_s]
71
- }]
72
-
73
- new_opts = {
74
- measures: measures,
75
- dimensions: dimensions,
76
- observations: observations.values,
77
- name: name,
78
- labels: labels.values,
79
- codes: codes
80
- }
81
-
82
- options = options.merge(new_opts)
83
- puts "creating #{options}" if verbose
84
- self.new(options)
85
- end
40
+ # puts get_hashes(execute_from_file('dimension_ranges.rq',graph))
41
+ dimensions = Hash[get_hashes(execute_from_file('dimension_ranges.rq',graph),"to_s").map{|solution|
42
+ #TODO coded properties should be found via SPARQL queries
43
+ if solution[:range].split('/')[-2] == "code"
44
+ type = :coded
45
+ else
46
+ type = solution[:range].to_s
47
+ end
48
+ [solution[:dimension], {type: type}]
49
+ }]
50
+ puts "dimensions: #{dimensions}" if verbose
86
51
 
87
- def parse_options(options)
88
- if options[:dimensions]
89
- options[:dimensions].each{|name,details|
90
- add_dimension(name, details[:type] || :coded)
52
+ codes = execute_from_file('code_resources.rq',graph).to_h.map{|sol|
53
+ [sol[:dimension].to_s, sol[:codeList].to_s, sol[:class].to_s]
91
54
  }
92
- end
55
+ puts "codes: #{codes}" if verbose
93
56
 
94
- if options[:measures]
95
- options[:measures].each{|m| @measures << m}
96
- end
57
+ measures = execute_from_file('measures.rq',graph).to_h.map{|m| m[:measure].to_s}
58
+ puts "measures: #{measures}" if verbose
97
59
 
98
- if options[:observations]
99
- options[:observations].each{|obs_data| add_observation obs_data}
100
- end
60
+ name = execute_from_file('dataset.rq',graph).to_h.first[:label]
61
+ puts "dataset: #{name}" if verbose
101
62
 
102
- @generator_options = options[:generator_options] if options[:generator_options]
103
- @options[:skip_metadata] = options[:skip_metadata] if options[:skip_metadata]
63
+ obs = execute_from_file('observations.rq',graph)
64
+ observations = observation_hash(obs)
65
+ puts "observations: #{observations}" if verbose
104
66
 
105
- if options[:name]
106
- @name = options[:name]
107
- else
108
- raise "No dataset name specified!"
109
- end
67
+ # simple_observations = observation_hash(obs,true)
110
68
 
111
- if options[:validate_each]
112
- @options[:validate_each] = options[:validate_each]
113
- end
69
+ labels = execute_from_file('observation_labels.rq', graph)
70
+ labels = Hash[labels.map{|sol|
71
+ [sol[:observation].to_s, sol[:label].to_s]
72
+ }]
114
73
 
115
- if options[:labels]
116
- @labels = options[:labels]
117
- end
74
+ new_opts = {
75
+ measures: measures,
76
+ dimensions: dimensions,
77
+ observations: observations.values,
78
+ name: name,
79
+ labels: labels.values,
80
+ codes: codes
81
+ }
118
82
 
119
- if options[:codes]
120
- @codes = options[:codes]
83
+ options = options.merge(new_opts)
84
+ puts "creating #{options}" if verbose
85
+ self.new(options)
121
86
  end
122
- end
123
87
 
124
- def to_n3
88
+ def parse_options(options)
89
+ if options[:dimensions]
90
+ options[:dimensions].each{|name,details|
91
+ add_dimension(name, details[:type] || :coded)
92
+ }
93
+ end
94
+
95
+ if options[:measures]
96
+ options[:measures].each{|m| @measures << m}
97
+ end
98
+
99
+ if options[:observations]
100
+ options[:observations].each{|obs_data| add_observation obs_data}
101
+ end
102
+
103
+ @generator_options = options[:generator_options] if options[:generator_options]
104
+ @options[:skip_metadata] = options[:skip_metadata] if options[:skip_metadata]
125
105
 
126
- #create labels if not specified
127
- unless @labels.is_a?(Array) && @labels.size == @obs.size
128
- if @labels.is_a? Symbol
129
- #define some automatic labeling methods
106
+ if options[:name]
107
+ @name = options[:name]
130
108
  else
131
- @labels = (1..@obs.size).to_a.map(&:to_s)
109
+ raise "No dataset name specified!"
110
+ end
111
+
112
+ if options[:validate_each]
113
+ @options[:validate_each] = options[:validate_each]
114
+ end
115
+
116
+ if options[:labels]
117
+ @labels = options[:labels]
118
+ end
119
+
120
+ if options[:codes]
121
+ @codes = options[:codes]
132
122
  end
133
123
  end
134
- data = {}
135
124
 
125
+ def to_n3
136
126
 
137
- #collect observation data
138
- check_integrity(@obs.map{|o| o.data}, @dimensions.keys, @measures)
139
- @obs.map{|obs|
140
- (@measures | @dimensions.keys).map{ |component|
141
- (data[component] ||= []) << obs.data[component]
142
- }
143
- }
144
-
145
-
146
- @codes = @dimensions.map{|d,v| d if v[:type] == :coded}.compact unless @codes
147
- str = generate(@measures, @dimensions.keys, @codes, data, @labels, @name, @generator_options)
148
- unless @options[:skip_metadata]
149
- fields = {
150
- publishers: publishers(),
151
- subject: subjects(),
152
- author: author(),
153
- description: description(),
154
- date: date(),
155
- var: @name,
127
+ #create labels if not specified
128
+ unless @labels.is_a?(Array) && @labels.size == @obs.size
129
+ if @labels.is_a? Symbol
130
+ #define some automatic labeling methods
131
+ else
132
+ @labels = (1..@obs.size).to_a.map(&:to_s)
133
+ end
134
+ end
135
+ data = {}
136
+
137
+
138
+ #collect observation data
139
+ check_integrity(@obs.map{|o| o.data}, @dimensions.keys, @measures)
140
+ @obs.map{|obs|
141
+ (@measures | @dimensions.keys).map{ |component|
142
+ (data[component] ||= []) << obs.data[component]
143
+ }
156
144
  }
157
- # puts basic(fields,@generator_options)
158
- str += "\n" + basic(fields)
145
+
146
+
147
+ @codes = @dimensions.map{|d,v| d if v[:type] == :coded}.compact unless @codes
148
+ str = generate(@measures, @dimensions.keys, @codes, data, @labels, @name, @generator_options)
149
+ unless @options[:skip_metadata]
150
+ fields = {
151
+ publishers: publishers(),
152
+ subject: subjects(),
153
+ author: author(),
154
+ description: description(),
155
+ date: date(),
156
+ var: @name,
157
+ }
158
+ # puts basic(fields,@generator_options)
159
+ str += "\n" + basic(fields)
160
+ end
161
+ str
159
162
  end
160
- str
161
- end
162
163
 
163
- def add_dimension(name, type=:coded)
164
- @dimensions[name.to_s] = {type: type}
165
- end
164
+ def add_dimension(name, type=:coded)
165
+ @dimensions[name.to_s] = {type: type}
166
+ end
166
167
 
167
- def add_measure(name)
168
- @measures << name
169
- end
168
+ def add_measure(name)
169
+ @measures << name
170
+ end
170
171
 
171
- def add_observation(data)
172
- data = Hash[data.map{|k,v| [k.to_s, v]}]
173
- obs = Observation.new(data)
174
- check_integrity([obs.data],@dimensions.keys,@measures) if @options[:validate_each]
175
- @obs << obs
176
- end
172
+ def add_observation(data)
173
+ data = Hash[data.map{|k,v| [k.to_s, v]}]
174
+ obs = Observation.new(data)
175
+ check_integrity([obs.data],@dimensions.keys,@measures) if @options[:validate_each]
176
+ @obs << obs
177
+ end
177
178
 
178
- def insert(observation)
179
- @obs << observation
180
- end
179
+ def insert(observation)
180
+ @obs << observation
181
+ end
181
182
 
182
- def publishers
183
- @meta[:publishers] ||= []
184
- end
183
+ def publishers
184
+ @meta[:publishers] ||= []
185
+ end
185
186
 
186
- def publishers=(publishers)
187
- @meta[:publishers] = publishers
188
- end
187
+ def publishers=(publishers)
188
+ @meta[:publishers] = publishers
189
+ end
189
190
 
190
- def subjects
191
- @meta[:subject] ||= []
192
- end
191
+ def subjects
192
+ @meta[:subject] ||= []
193
+ end
193
194
 
194
- def subjects=(subjects)
195
- @meta[:subject]=subjects
196
- end
195
+ def subjects=(subjects)
196
+ @meta[:subject]=subjects
197
+ end
197
198
 
198
- def add_publisher(label,uri)
199
- publishers << {label: label, uri: uri}
200
- end
199
+ def add_publisher(label,uri)
200
+ publishers << {label: label, uri: uri}
201
+ end
201
202
 
202
- def add_subject(id)
203
- subject << id
204
- end
203
+ def add_subject(id)
204
+ subject << id
205
+ end
205
206
 
206
- def author
207
- @meta[:creator] ||= ""
208
- end
207
+ def author
208
+ @meta[:creator] ||= ""
209
+ end
209
210
 
210
- def author=(author)
211
- @meta[:creator] = author
212
- end
211
+ def author=(author)
212
+ @meta[:creator] = author
213
+ end
213
214
 
214
- def description
215
- @meta[:description] ||= ""
216
- end
215
+ def description
216
+ @meta[:description] ||= ""
217
+ end
217
218
 
218
- def description=(description)
219
- @meta[:description] = description
220
- end
219
+ def description=(description)
220
+ @meta[:description] = description
221
+ end
221
222
 
222
- def date
223
- @meta[:date] ||= "#{Time.now.day}-#{Time.now.month}-#{Time.now.year}"
224
- end
223
+ def date
224
+ @meta[:date] ||= "#{Time.now.day}-#{Time.now.month}-#{Time.now.year}"
225
+ end
225
226
 
226
- def date=(date)
227
- @meta[:date] = date
228
- end
227
+ def date=(date)
228
+ @meta[:date] = date
229
+ end
229
230
 
230
- def to_h
231
- {
232
- measures: @measures,
233
- dimensions: @dimensions,
234
- observations: @obs.map{|o| o.data}
235
- }
231
+ def to_h
232
+ {
233
+ measures: @measures,
234
+ dimensions: @dimensions,
235
+ observations: @obs.map{|o| o.data}
236
+ }
237
+ end
236
238
  end
237
239
  end
238
240
  end