amee-data-abstraction 2.1.1 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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