amee-data-abstraction 2.1.1 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. data/CHANGELOG.txt +3 -0
  2. data/README.txt +26 -14
  3. data/VERSION +1 -1
  4. data/amee-data-abstraction.gemspec +7 -6
  5. data/lib/amee-data-abstraction/calculation.rb +1 -1
  6. data/lib/amee-data-abstraction/calculation_set.rb +152 -10
  7. data/lib/amee-data-abstraction/input.rb +10 -0
  8. data/lib/amee-data-abstraction/ongoing_calculation.rb +1 -1
  9. data/lib/amee-data-abstraction/term.rb +31 -13
  10. data/spec/amee-data-abstraction/calculation_set_spec.rb +247 -9
  11. data/spec/amee-data-abstraction/calculation_spec.rb +24 -19
  12. data/spec/amee-data-abstraction/drill_spec.rb +14 -9
  13. data/spec/amee-data-abstraction/input_spec.rb +113 -73
  14. data/spec/amee-data-abstraction/metadatum_spec.rb +1 -1
  15. data/spec/amee-data-abstraction/ongoing_calculation_spec.rb +38 -30
  16. data/spec/amee-data-abstraction/profile_spec.rb +4 -2
  17. data/spec/amee-data-abstraction/prototype_calculation_spec.rb +13 -8
  18. data/spec/amee-data-abstraction/term_spec.rb +45 -4
  19. data/spec/amee-data-abstraction/terms_list_spec.rb +23 -12
  20. data/spec/config/amee_units_spec.rb +1 -2
  21. data/spec/core-extensions/class_spec.rb +18 -18
  22. data/spec/core-extensions/hash_spec.rb +1 -2
  23. data/spec/core-extensions/ordered_hash_spec.rb +1 -2
  24. data/spec/core-extensions/proc_spec.rb +1 -1
  25. data/spec/fixtures/config/calculations/electricity.rb +35 -0
  26. data/spec/fixtures/config/calculations/electricity_and_transport.rb +53 -0
  27. data/spec/fixtures/{transport.rb → config/calculations/transport.rb} +2 -2
  28. data/spec/fixtures/{electricity.rb → config/electricity.rb} +1 -1
  29. data/spec/spec_helper.rb +30 -2
  30. metadata +28 -27
  31. data/spec/fixtures/electricity_and_transport.rb +0 -55
@@ -1,16 +1,18 @@
1
- require File.dirname(File.dirname(__FILE__)) + '/spec_helper.rb'
1
+ require 'spec_helper'
2
2
 
3
3
  describe Profile do
4
+
4
5
  it 'defaults to be a text-box' do
5
6
  i=Profile.new
6
7
  i.text_box?.should be_true
7
8
  end
9
+
8
10
  it 'can know if it belongs to a particular usage' do
9
11
  mocker=AMEEMocker.new self,:path=>'transport/car/generic'
10
12
  mocker.item_value_definitions.
11
13
  item_definition.data_category.
12
14
  item_value_definition('distance',['someusage'],['someotherusage'])
13
- t=Transport.clone
15
+ t=CalculationSet.find("transport")[:transport].clone
14
16
  t[:distance].compulsory?('someusage').should eql true
15
17
  t[:distance].compulsory?('someotherusage').should eql false
16
18
  t[:distance].optional?('someotherusage').should eql true
@@ -1,4 +1,4 @@
1
- require File.dirname(File.dirname(__FILE__)) + '/spec_helper.rb'
1
+ require 'spec_helper'
2
2
 
3
3
  class PrototypeCalculation
4
4
  def call_me
@@ -10,8 +10,13 @@ class PrototypeCalculation
10
10
  end
11
11
  end
12
12
  describe PrototypeCalculation do
13
+
14
+ before :all do
15
+ @calc = CalculationSet.find("transport")[:transport]
16
+ end
17
+
13
18
  it 'can create an instance' do
14
- Transport.should be_a PrototypeCalculation
19
+ @calc.should be_a PrototypeCalculation
15
20
  end
16
21
  it 'can be initialized with a DSL block' do
17
22
  PrototypeCalculation.new {call_me}
@@ -40,17 +45,17 @@ describe PrototypeCalculation do
40
45
  pc[:alpha].should be_a Output
41
46
  end
42
47
  it 'can construct an ongoing calculation' do
43
- Transport.begin_calculation.should be_a OngoingCalculation
48
+ @calc.begin_calculation.should be_a OngoingCalculation
44
49
  end
45
50
  it 'should make the terms of the ongoing calculation be their own instances' do
46
- oc=Transport.begin_calculation
51
+ oc=@calc.begin_calculation
47
52
  oc[:distance].value :somevalue
48
53
  oc[:distance].value.should eql :somevalue
49
- Transport[:distance].value.should be_nil
54
+ @calc[:distance].value.should be_nil
50
55
  end
51
56
  it 'should copy name, path, label when cloning ongoing' do
52
57
  [:path,:name,:label].each do |property|
53
- Transport.begin_calculation.send(property).should eql Transport.send(property)
58
+ @calc.begin_calculation.send(property).should eql @calc.send(property)
54
59
  end
55
60
  end
56
61
  it 'can autogenerate drill terms for itself, based on talking to amee' do
@@ -229,7 +234,7 @@ describe PrototypeCalculation do
229
234
  pc.terms.default_per_units.compact.map(&:name).should include 'hour'
230
235
  end
231
236
  it 'transfers memoised amee information to constructed ongoing calculations' do
232
- t=Transport.clone
237
+ t=@calc.clone
233
238
  flexmock(AMEE::Data::Category).should_receive(:get).
234
239
  with(AMEE::DataAbstraction.connection,'/data/transport/car/generic').
235
240
  once.and_return(true)
@@ -237,7 +242,7 @@ describe PrototypeCalculation do
237
242
  t.begin_calculation.send(:amee_data_category)
238
243
  end
239
244
  it 'can auto-create start and end date metadata' do
240
- t=Transport.clone
245
+ t=@calc.clone
241
246
  t.instance_eval{
242
247
  start_and_end_dates
243
248
  }
@@ -1,4 +1,4 @@
1
- require File.dirname(File.dirname(__FILE__)) + '/spec_helper.rb'
1
+ require 'spec_helper'
2
2
 
3
3
  class Term
4
4
  def call_me
@@ -11,6 +11,11 @@ class Term
11
11
  end
12
12
 
13
13
  describe Term do
14
+
15
+ before :all do
16
+ @calc = CalculationSet.find("transport")[:transport]
17
+ end
18
+
14
19
  it 'can be initialized via DSL block' do
15
20
  Term.new {call_me}
16
21
  Term.called.should be_true
@@ -32,8 +37,12 @@ describe Term do
32
37
  Term.new {note 'hello'}.note.should eql 'hello'
33
38
  end
34
39
 
40
+ it "has note with no '\"' character" do
41
+ Term.new {note 'hello "some quote"'}.note.should eql "hello 'some quote'"
42
+ end
43
+
35
44
  it 'has parent' do
36
- Transport[:distance].parent.should eql Transport
45
+ @calc[:distance].parent.should eql @calc
37
46
  end
38
47
  it "has name defaulting to label" do
39
48
  Term.new {label :hello}.name.should eql 'Hello'
@@ -87,10 +96,10 @@ describe Term do
87
96
  t.hidden?.should be_false
88
97
  end
89
98
  it 'knows which terms come before or after it' do
90
- Transport.terms.
99
+ @calc.terms.
91
100
  select{|x|x.before?(:distance)}.map(&:label).
92
101
  should eql [:fuel,:size]
93
- Transport.terms.
102
+ @calc.terms.
94
103
  select{|x|x.after?(:distance)}.map(&:label).
95
104
  should eql [:co2]
96
105
  end
@@ -137,6 +146,26 @@ describe Term do
137
146
  per_units.should include "joule", "british thermal unit", "megawatt hour"
138
147
  end
139
148
 
149
+ it "has unit choices which include default and alternative" do
150
+ term = Term.new {path :hello; default_unit :kg; default_per_unit :kWh}
151
+ units = term.alternative_units.map(&:name)
152
+ units.should include "gigagram", "pound", "tonne"
153
+ units.should_not include "kilogram", "kelvin"
154
+
155
+ units = term.unit_choices.map(&:name)
156
+ units.first.should eql "kilogram"
157
+ units.should include "kilogram", "gigagram", "pound", "tonne"
158
+ units.should_not include "kelvin"
159
+
160
+ per_units = term.alternative_per_units.map(&:name)
161
+ per_units.should include "joule", "british thermal unit", "megawatt hour"
162
+ per_units.should_not include "kilowatt hour"
163
+
164
+ per_units = term.per_unit_choices.map(&:name)
165
+ per_units.first.should eql "kilowatt hour"
166
+ per_units.should include "kilowatt hour", "joule", "british thermal unit", "megawatt hour"
167
+ end
168
+
140
169
  it "has limited set of alternative units if specified" do
141
170
  term = Term.new {path :hello; default_unit :kg; alternative_units :t, :ton_us, :lb}
142
171
  units = term.alternative_units.map(&:name)
@@ -144,6 +173,18 @@ describe Term do
144
173
  units.should_not include "gigagram", "ounce", "gram"
145
174
  end
146
175
 
176
+ it "has unit choices which include default and alternative with limited set of alternative units" do
177
+ term = Term.new {path :hello; default_unit :kg; alternative_units :t, :ton_us, :lb}
178
+ units = term.alternative_units.map(&:name)
179
+ units.should include "tonne", "pound", "short ton"
180
+ units.should_not include "kilogram", "gigagram", "ounce", "gram"
181
+
182
+ units = term.unit_choices.map(&:name)
183
+ units.first.should eql "kilogram"
184
+ units.should include "kilogram", "tonne", "pound", "short ton"
185
+ units.should_not include "gigagram", "ounce", "gram"
186
+ end
187
+
147
188
  it "should raise error when specifying incompatible alternative units" do
148
189
  lambda{Term.new {path :hello; default_unit :kg; alternative_units :kWh, :km}}.should raise_error
149
190
  end
@@ -1,46 +1,57 @@
1
- require File.dirname(File.dirname(__FILE__)) + '/spec_helper.rb'
1
+ require 'spec_helper'
2
2
 
3
3
  describe TermsList do
4
+
5
+ before :all do
6
+ @calc = CalculationSet.find("transport")[:transport]
7
+ end
8
+
4
9
  it 'should be returned from calculations' do
5
- Transport.terms.should be_a TermsList
10
+ @calc.terms.should be_a TermsList
6
11
  end
12
+
7
13
  it 'should give properties' do
8
- Transport.terms.labels.should eql [:fuel,:size,:distance,:co2]
9
- Transport.terms.paths.should eql ['fuel','size','distance',:default]
10
- Transport.terms.names.should eql ['Fuel Type','Vehicle Size','Distance Driven','Carbon Dioxide']
14
+ @calc.terms.labels.should eql [:fuel,:size,:distance,:co2]
15
+ @calc.terms.paths.should eql ['fuel','size','distance','default']
16
+ @calc.terms.names.should eql ['Fuel Type','Vehicle Size','Distance Driven','Carbon Dioxide']
11
17
  end
18
+
12
19
  it 'should select by class' do
13
- Transport.terms.drills.labels.should eql [:fuel,:size]
14
- Transport.terms.profiles.labels.should eql [:distance]
15
- Transport.terms.outputs.labels.should eql [:co2]
20
+ @calc.terms.drills.labels.should eql [:fuel,:size]
21
+ @calc.terms.profiles.labels.should eql [:distance]
22
+ @calc.terms.outputs.labels.should eql [:co2]
16
23
  end
24
+
17
25
  it 'should select by property' do
18
- t=Transport.begin_calculation
26
+ t=@calc.begin_calculation
19
27
  t[:distance].value 5
20
28
  t.terms.set.labels.should eql [:distance]
21
29
  t.terms.unset.labels.should eql [:fuel,:size,:co2]
22
30
  end
31
+
23
32
  it 'should select by chain' do
24
- t=Transport.begin_calculation
33
+ t=@calc.begin_calculation
25
34
  t[:fuel].value 'diesel'
26
35
  t.terms.drills.set.labels.should eql [:fuel]
27
36
  t.terms.drills.unset.labels.should eql [:size]
28
37
  t.terms.set.drills.labels.should eql [:fuel]
29
38
  t.terms.unset.drills.labels.should eql [:size]
30
39
  end
40
+
31
41
  it 'should select by order' do
32
- t=Transport.clone
42
+ t=@calc.clone
33
43
  t.terms.before(:distance).labels.
34
44
  should eql [:fuel,:size]
35
45
  t.terms.after(:distance).labels.
36
46
  should eql [:co2]
37
47
  end
48
+
38
49
  it 'can select terms by usage' do
39
50
  mocker=AMEEMocker.new self,:path=>'transport/car/generic'
40
51
  mocker.item_value_definitions.
41
52
  item_definition.data_category.
42
53
  item_value_definition('distance',['usage1'],['usage2'],['usage3'])
43
- t=Transport.clone
54
+ t=@calc.clone
44
55
  t.profiles.compulsory('usage1').labels.should eql [:distance]
45
56
  t.profiles.optional('usage2').labels.should eql [:distance]
46
57
  t.profiles.compulsory('usage2').labels.should be_empty
@@ -1,5 +1,4 @@
1
-
2
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
3
2
 
4
3
  describe "AMEE units" do
5
4
 
@@ -1,25 +1,25 @@
1
- require File.dirname(File.dirname(__FILE__)) + '/spec_helper.rb'
1
+ require 'spec_helper'
2
2
 
3
- class Myclass
4
- attr_property :prop
5
- end
3
+ class Myclass
4
+ attr_property :prop
5
+ end
6
6
 
7
7
  describe Class do
8
8
  before :all do
9
9
  @it=Myclass.new
10
10
  end
11
- it 'can have a property defined' do
12
- @it.prop 5
13
- @it.prop.should eql 5
14
- end
15
- it 'can have a prop unset' do
16
- @it.prop 5
17
- @it.prop nil
18
- @it.prop.should be_nil
19
- end
20
- it 'does not unset by query' do
21
- @it.prop 5
22
- @it.prop
23
- @it.prop.should_not be_nil
24
- end
11
+ it 'can have a property defined' do
12
+ @it.prop 5
13
+ @it.prop.should eql 5
14
+ end
15
+ it 'can have a prop unset' do
16
+ @it.prop 5
17
+ @it.prop nil
18
+ @it.prop.should be_nil
19
+ end
20
+ it 'does not unset by query' do
21
+ @it.prop 5
22
+ @it.prop
23
+ @it.prop.should_not be_nil
24
+ end
25
25
  end
@@ -1,5 +1,4 @@
1
-
2
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
3
2
 
4
3
  describe Hash do
5
4
  before(:each) do
@@ -1,5 +1,4 @@
1
- require File.dirname(File.dirname(__FILE__)) + '/spec_helper.rb'
2
-
1
+ require 'spec_helper'
3
2
 
4
3
  describe ActiveSupport::OrderedHash do
5
4
  it 'Can insert at start' do
@@ -1,4 +1,4 @@
1
- require File.dirname(File.dirname(__FILE__)) + '/spec_helper.rb'
1
+ require 'spec_helper'
2
2
 
3
3
  describe Proc do
4
4
  before :all do
@@ -0,0 +1,35 @@
1
+ calculation { # The application has support for an electricity calculation. :electricity is the internal label used to refer to it
2
+ label :electricity
3
+ name "Electricity Consumption"
4
+ path '/business/energy/electricity/grid'
5
+
6
+ drill {
7
+ fixed 'argentina' #Not to be unset, value pre-given
8
+ label :country #Name will default to label.humanize if not given
9
+ path 'country' #Some of the fields on the form are drill-downs, but the application doesn't need to display these differently
10
+ #type :autocompleting_text_box #default for a drill with entries is probably a dropdown
11
+ }
12
+
13
+ profile {
14
+ label :energy_used
15
+ # Symbol provided here is used in generating html ids for elements etc
16
+ path 'energyPerTime' #The amee profile item value corresponding to the field
17
+ name "Energy Used" #The display name used on the form
18
+ unit "kWh" #Default unit choice
19
+ interface :text_box #Probably not needed, as likely to be the default for profile item value unsets
20
+ validation lambda{|x|x.is_a? Float} #Probably not needed, as default can be deduced from PIV TYPE in API. Here as illustrative.
21
+ alternative_units :MWh, :MBTU, :BTU # If these are explcitly specified then the alternatives are limited to only these units. Otherwise all dimensionally equivalent units are available as alternatives by default
22
+ }
23
+
24
+ # Alternatively, the drill might be fixed
25
+ #permanent :country {
26
+ # drill_path 'country'
27
+ # value 'Argentina'
28
+
29
+ output { #A marv output value
30
+ label :co2
31
+ path 'default' #It's not a marv, use the default output
32
+ name "Carbon Dioxide"
33
+ }
34
+ }
35
+
@@ -0,0 +1,53 @@
1
+ all_calculations {
2
+ metadatum {
3
+ label :department
4
+ choices %w{stuff things more_stuff meta_things}
5
+ }
6
+ }
7
+
8
+ calculation{
9
+ name 'electricity'
10
+ label :electricity
11
+ path '/business/energy/electricity/grid'
12
+ profile {
13
+ label :usage
14
+ name 'Electricity Used'
15
+ path 'energyPerTime'
16
+ }
17
+ drill {
18
+ label :country
19
+ path 'country'
20
+ fixed 'Argentina'
21
+ }
22
+ output {
23
+ label :co2
24
+ path 'default'
25
+ }
26
+ }
27
+
28
+ calculation {
29
+ name 'transport'
30
+ label :transport
31
+ path '/transport/car/generic'
32
+
33
+ drill {
34
+ path 'fuel'
35
+ label :fuel
36
+ name 'Fuel Type'
37
+ }
38
+ drill {
39
+ path 'size'
40
+ label :size
41
+ name 'Vehicle Size'
42
+ }
43
+ profile {
44
+ path 'distance'
45
+ label :distance
46
+ name 'Distance Driven'
47
+ }
48
+ output {
49
+ label :co2
50
+ path 'default'
51
+ name 'Carbon Dioxide'
52
+ }
53
+ }
@@ -1,4 +1,4 @@
1
- Transport=AMEE::DataAbstraction::PrototypeCalculation.new{
1
+ calculation {
2
2
  name 'transport'
3
3
  label :transport
4
4
  path '/transport/car/generic'
@@ -20,7 +20,7 @@ Transport=AMEE::DataAbstraction::PrototypeCalculation.new{
20
20
  }
21
21
  output {
22
22
  label :co2
23
- path :default
23
+ path 'default'
24
24
  name 'Carbon Dioxide'
25
25
  }
26
26
  }
@@ -28,7 +28,7 @@ Electricity=AMEE::DataAbstraction::PrototypeCalculation.new { # The application
28
28
 
29
29
  output { #A marv output value
30
30
  label :co2
31
- path :default #It's not a marv, use the default output
31
+ path 'default' #It's not a marv, use the default output
32
32
  name "Carbon Dioxide"
33
33
  }
34
34
  }
@@ -1,15 +1,43 @@
1
1
  require 'rubygems'
2
2
  require 'rspec'
3
+
4
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
3
5
  require 'amee-data-abstraction'
4
6
 
7
+ # Fake up Rails.root to be fixtures directory
8
+ class Rails
9
+ def self.root
10
+ File.dirname(__FILE__) + '/fixtures'
11
+ end
12
+ def self.logger
13
+ nil
14
+ end
15
+ end
16
+
5
17
  RSpec.configure do |config|
6
18
  config.mock_with :flexmock
19
+ config.after(:each) do
20
+ delete_lock_files
21
+ end
22
+ end
23
+
24
+ def delete_lock_files
25
+ config_dir = Dir.new("#{Rails.root}/config/calculations")
26
+ config_dir.each do |file|
27
+ File.delete("#{config_dir.path}/#{file}") if file =~ /lock/
28
+ end
7
29
  end
8
30
 
9
31
  AMEE::DataAbstraction.connection=FlexMock.new('connection') #Global connection mock, shouldn't receive anything, as we mock the individual amee-ruby calls in the tests
10
32
 
11
- Dir.glob(File.dirname(__FILE__) + '/fixtures/*') do |filename|
12
- require filename
33
+ # Fake up Rails.root to be fixtures directory
34
+ class Rails
35
+ def self.root
36
+ File.dirname(__FILE__) + '/fixtures'
37
+ end
38
+ def self.logger
39
+ nil
40
+ end
13
41
  end
14
42
 
15
43
  include AMEE::DataAbstraction