amee-data-persistence 1.0.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.
- data/.rvmrc +1 -0
- data/CHANGELOG.txt +4 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +48 -0
- data/LICENSE.txt +27 -0
- data/README.txt +89 -0
- data/Rakefile +102 -0
- data/VERSION +1 -0
- data/amee-data-persistence.gemspec +93 -0
- data/amee-data-persistence.tmproj +27 -0
- data/generators/persistence/persistence_generator.rb +97 -0
- data/generators/persistence/templates/config/persistence.yml.erb +1 -0
- data/generators/persistence/templates/db/migrate/001_create_persistence_tables.rb +29 -0
- data/generators/persistence/templates/db/migrate/002_add_unit_columns.rb +15 -0
- data/generators/persistence/templates/db/migrate/003_add_value_types.rb +9 -0
- data/init.rb +1 -0
- data/lib/amee-data-persistence.rb +12 -0
- data/lib/amee/data_abstraction/calculation_collection.rb +22 -0
- data/lib/amee/data_abstraction/persistence_support.rb +274 -0
- data/lib/amee/db/calculation.rb +156 -0
- data/lib/amee/db/config.rb +54 -0
- data/lib/amee/db/term.rb +72 -0
- data/rails/init.rb +31 -0
- data/spec/amee/db/calculation_spec.rb +176 -0
- data/spec/amee/db/config_spec.rb +92 -0
- data/spec/amee/db/persistence_support_spec.rb +356 -0
- data/spec/amee/db/term_spec.rb +147 -0
- data/spec/database.yml +4 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +136 -0
- metadata +239 -0
@@ -0,0 +1,54 @@
|
|
1
|
+
# Copyright (C) 2011 AMEE UK Ltd. - http://www.amee.com
|
2
|
+
# Released as Open Source Software under the BSD 3-Clause license. See LICENSE.txt for details.
|
3
|
+
|
4
|
+
# :title: Class: AMEE::Db::BaseConfig
|
5
|
+
|
6
|
+
require 'singleton'
|
7
|
+
|
8
|
+
module AMEE
|
9
|
+
module Db
|
10
|
+
|
11
|
+
# A singleton class for configuration. Automatically initialised on first use
|
12
|
+
# Use like so:
|
13
|
+
#
|
14
|
+
# AMEE::Db::Config.instance.store_everything?
|
15
|
+
#
|
16
|
+
# Separated into BaseConfig and Config to allow unit testing of singleton.
|
17
|
+
#
|
18
|
+
class BaseConfig
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
# Default is metadata
|
22
|
+
@storage_method = load_storage_method || :metadata
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_reader :storage_method
|
26
|
+
|
27
|
+
def store_metadata?
|
28
|
+
[:metadata, :outputs, :everything].include? storage_method
|
29
|
+
end
|
30
|
+
|
31
|
+
def store_outputs?
|
32
|
+
[:outputs, :everything].include? storage_method
|
33
|
+
end
|
34
|
+
|
35
|
+
def store_everything?
|
36
|
+
[:everything].include? storage_method
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def load_storage_method
|
42
|
+
m = YAML.load_file("#{RAILS_ROOT}/config/persistence.yml")['method'].to_sym rescue nil
|
43
|
+
raise "amee-data-persistence: Invalid storage method" unless [:metadata, :outputs, :everything].include? m
|
44
|
+
m
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
class Config < BaseConfig
|
50
|
+
include Singleton
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
data/lib/amee/db/term.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# Copyright (C) 2011 AMEE UK Ltd. - http://www.amee.com
|
2
|
+
# Released as Open Source Software under the BSD 3-Clause license. See LICENSE.txt for details.
|
3
|
+
|
4
|
+
# :title: Class AMEE::Db::Term
|
5
|
+
|
6
|
+
module AMEE
|
7
|
+
module Db
|
8
|
+
|
9
|
+
# This class represents a database record for a calculation term used with
|
10
|
+
# the <i>AMEE:DataAbstraction::OngoingCalculation</i> class. This class stores
|
11
|
+
# the label, value and unit attributes of specific calculation terms, and is
|
12
|
+
# owned by an associated <i>AMEE::Db::Calculation</i> record
|
13
|
+
#
|
14
|
+
# This class is typically used by proxy, via the <tt>#update_calculation!</tt>,
|
15
|
+
# and <tt>#to_hash</tt> methods of the <i>AMEE::Db::Calculation</i> class, and
|
16
|
+
# ultimately called from the <tt>find</tt>, <tt>find_by_type</tt>,
|
17
|
+
# <tt>#save</tt>, <tt>#delete</tt>, and <tt>#get_db_calculation</tt> methods
|
18
|
+
# associated with the <i>AMEE:DataAbstraction::OngoingCalculation</i> class.
|
19
|
+
#
|
20
|
+
class Term < ActiveRecord::Base
|
21
|
+
|
22
|
+
belongs_to :calculation, :class_name => "AMEE::Db::Calculation"
|
23
|
+
validates_presence_of :calculation_id, :label
|
24
|
+
before_save :initialize_units
|
25
|
+
before_save :initialize_value
|
26
|
+
|
27
|
+
# Returns a <i>Hash</i> representation of <tt>self</tt>, e.g.
|
28
|
+
#
|
29
|
+
# my_term.to_hash #=> { :value => 1600,
|
30
|
+
# :unit => <Quantify::Unit::SI> }
|
31
|
+
#
|
32
|
+
# my_term.to_hash #=> { :value => 234.1,
|
33
|
+
# :unit => <Quantify::Unit::NonSI>,
|
34
|
+
# :per_unit => <Quantify::Unit::SI> }
|
35
|
+
#
|
36
|
+
# This method is called as part of <tt>AMEE::Db::Calculation#to_hash</tt>
|
37
|
+
# in order to provide a full hash representation of a calculation.
|
38
|
+
#
|
39
|
+
def to_hash
|
40
|
+
sub_hash = {}
|
41
|
+
# Float method called on term value in order to initialize
|
42
|
+
# explicitly numeric values as numeric objects.
|
43
|
+
#
|
44
|
+
sub_hash[:value] = AMEE::DataAbstraction::Term.convert_value_to_type(self.value, self.value_type)
|
45
|
+
sub_hash[:unit] = Unit.for(unit) if unit
|
46
|
+
sub_hash[:per_unit] = Unit.for(per_unit) if per_unit
|
47
|
+
{ label.to_sym => sub_hash }
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
# Serialize all unit attributes using the string provided by the
|
53
|
+
# <tt>label</tt> attribute of a <i>Quantify::Unit::Base</i> object
|
54
|
+
#
|
55
|
+
def initialize_units
|
56
|
+
if unit
|
57
|
+
self.unit = unit.is_a?(Quantify::Unit::Base) ? unit.label : unit
|
58
|
+
end
|
59
|
+
if per_unit
|
60
|
+
self.per_unit = per_unit.is_a?(Quantify::Unit::Base) ? per_unit.label : per_unit
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def initialize_value
|
65
|
+
unless self.value.nil?
|
66
|
+
self.value_type = self.value.class.to_s
|
67
|
+
self.value = self.value.to_s
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/rails/init.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
# Authors:: James Hetherington, James Smith, Andrew Berkeley, George Palmer
|
3
|
+
# Copyright:: Copyright (c) 2011 AMEE UK Ltd
|
4
|
+
# License:: Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject
|
10
|
+
# to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included
|
13
|
+
# in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
18
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
19
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
20
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
21
|
+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#
|
23
|
+
|
24
|
+
require 'amee-data-abstraction'
|
25
|
+
require 'amee-data-persistence'
|
26
|
+
|
27
|
+
# include the <i>AMEE::DataAbstraction::PersistenceSupport</i> module within the
|
28
|
+
# <i>AMEE::DataAbstraction::OngoingCalculation</i> class providing interface
|
29
|
+
# methods for managing persistence of calculations.
|
30
|
+
#
|
31
|
+
::AMEE::DataAbstraction::OngoingCalculation.class_eval { include ::AMEE::DataAbstraction::PersistenceSupport }
|
@@ -0,0 +1,176 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
include AMEE::Db
|
4
|
+
|
5
|
+
describe Calculation do
|
6
|
+
|
7
|
+
valid_calculation_attributes = { :profile_item_uid => "G8T8E8SHSH46",
|
8
|
+
:calculation_type => :electricity }
|
9
|
+
|
10
|
+
after(:all) do
|
11
|
+
Calculation.delete_all
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "new calculation" do
|
15
|
+
|
16
|
+
before(:all) do
|
17
|
+
@attr = valid_calculation_attributes
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should be valid with profile item uid and calculation type" do
|
21
|
+
@calculation = Calculation.new @attr
|
22
|
+
@calculation.should be_valid
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should be valid without profile item uid" do
|
26
|
+
@calculation = Calculation.new @attr.merge(:profile_item_uid => "")
|
27
|
+
@calculation.should be_valid
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should not be valid without calculation type" do
|
31
|
+
@calculation = Calculation.new @attr.merge(:calculation_type => "")
|
32
|
+
@calculation.should_not be_valid
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should be valid with profile uid additionally specified" do
|
36
|
+
@calculation = Calculation.new @attr.merge(:profile_uid => "GFD8E8SHSH46")
|
37
|
+
@calculation.should be_valid
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should not be valid with non-canonical (short) profile item uid" do
|
41
|
+
@calculation = Calculation.new @attr.merge(:profile_item_uid => "GFD8E8SHS")
|
42
|
+
@calculation.should_not be_valid
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should not be valid with non-canonical (lowercase) profile item uid" do
|
46
|
+
@calculation = Calculation.new @attr.merge(:profile_item_uid => "gfd8e8shsh46")
|
47
|
+
@calculation.should_not be_valid
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should not be valid with non-canonical (short) profile uid" do
|
51
|
+
@calculation = Calculation.new @attr.merge(:profile_uid => "GFD8E8SHS")
|
52
|
+
@calculation.should_not be_valid
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should not be valid with non-canonical (lowercase) profile uid" do
|
56
|
+
@calculation = Calculation.new @attr.merge(:profile_uid => "gfd8e8shsh46")
|
57
|
+
@calculation.should_not be_valid
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should not be valid with non-canonical (invalid characters) profile uid" do
|
61
|
+
@calculation = Calculation.new @attr.merge(:profile_uid => "gfd8&sh*h4.")
|
62
|
+
@calculation.should_not be_valid
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should create a new calculation" do
|
66
|
+
@calculation = Calculation.create @attr
|
67
|
+
@calculation.is_a?(Calculation).should be_true
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should save calculation type as string" do
|
71
|
+
@calculation = Calculation.create! @attr
|
72
|
+
@calculation.reload
|
73
|
+
@calculation.calculation_type.should == 'electricity'
|
74
|
+
@calculation.calculation_type.class.should == String
|
75
|
+
@calculation.type.should == :electricity
|
76
|
+
@calculation.type.class.should == Symbol
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "updating calculation" do
|
82
|
+
|
83
|
+
valid_term_attributes = { :country => {:value => 'Argentina'},
|
84
|
+
:usage => {:value => 500, :unit => Unit.kWh},
|
85
|
+
:co2 => {:value => 1234.5, :unit => Unit.kg} }
|
86
|
+
|
87
|
+
before(:each) do
|
88
|
+
@calculation = Calculation.create valid_calculation_attributes
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should update primary attributes" do
|
92
|
+
@calculation.profile_item_uid.should == "G8T8E8SHSH46"
|
93
|
+
@calculation.profile_uid.should == nil
|
94
|
+
@calculation.update_calculation!(:profile_uid => "ASD603SHSHFD", :profile_item_uid => "ASN603DHSREW")
|
95
|
+
@calculation.profile_item_uid.should == "ASN603DHSREW"
|
96
|
+
@calculation.profile_uid.should == "ASD603SHSHFD"
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should not matter which order attributes updated" do
|
100
|
+
@calculation.profile_item_uid.should == "G8T8E8SHSH46"
|
101
|
+
@calculation.update_calculation!(:profile_uid => "ASD603SHSHFD",
|
102
|
+
:calculation_type => :energy,
|
103
|
+
:profile_item_uid => "ASN603DHSREW")
|
104
|
+
@calculation.profile_item_uid.should == "ASN603DHSREW"
|
105
|
+
@calculation.profile_uid.should == "ASD603SHSHFD"
|
106
|
+
@calculation.type.should == :energy
|
107
|
+
@calculation.update_calculation!(:profile_uid => nil,
|
108
|
+
:profile_item_uid => "ASN603DHSREW",
|
109
|
+
:calculation_type => :electricity)
|
110
|
+
@calculation.profile_item_uid.should == "ASN603DHSREW"
|
111
|
+
@calculation.profile_uid.should == nil
|
112
|
+
@calculation.type.should == :electricity
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should allow removal of profile item uid" do
|
116
|
+
@calculation.profile_item_uid.should == "G8T8E8SHSH46"
|
117
|
+
@calculation.profile_uid.should == nil
|
118
|
+
@calculation.update_calculation!(:profile_uid => "ASD603SHSHFD", :profile_item_uid => nil)
|
119
|
+
@calculation.profile_item_uid.should == nil
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should update associated terms" do
|
123
|
+
@calculation.to_hash.should == { :profile_item_uid => "G8T8E8SHSH46",
|
124
|
+
:profile_uid => nil }
|
125
|
+
@calculation.type.should == :electricity
|
126
|
+
@calculation.update_calculation! valid_term_attributes.merge :calculation_type => :power
|
127
|
+
hash = @calculation.to_hash
|
128
|
+
hash.keys.map!(&:to_s).sort!.should == [ :profile_item_uid, :usage, :co2, :country,
|
129
|
+
:profile_uid].map!(&:to_s).sort!
|
130
|
+
hash[:co2][:unit].should be_a Quantify::Unit::SI
|
131
|
+
hash[:co2][:value].should eql 1234.5
|
132
|
+
hash[:co2][:unit].name.should eql 'kilogram'
|
133
|
+
hash[:usage][:unit].should be_a Quantify::Unit::NonSI
|
134
|
+
hash[:usage][:value].should eql 500
|
135
|
+
hash[:usage][:unit].name.should eql 'kilowatt hour'
|
136
|
+
hash[:country][:value].should eql 'Argentina'
|
137
|
+
@calculation.calculation_type.should eql 'power'
|
138
|
+
@calculation.type.should eql :power
|
139
|
+
@calculation.update_calculation! valid_term_attributes.merge :calculation_type => :electricity
|
140
|
+
@calculation.calculation_type.should eql 'electricity'
|
141
|
+
@calculation.type.should eql :electricity
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should update associated terms, removing unspecified terms" do
|
145
|
+
@calculation.to_hash.should == { :profile_item_uid => "G8T8E8SHSH46",
|
146
|
+
:profile_uid => nil }
|
147
|
+
@calculation.type.should == :electricity
|
148
|
+
@calculation.update_calculation! valid_term_attributes
|
149
|
+
hash = @calculation.to_hash
|
150
|
+
hash.keys.map!(&:to_s).sort!.should == [:profile_item_uid, :usage, :co2, :country,
|
151
|
+
:profile_uid ].map!(&:to_s).sort!
|
152
|
+
@calculation.type.should == :electricity
|
153
|
+
@calculation.update_calculation! :usage => {:value => 600000, :unit => Unit.kWh}, :country => {:value =>'Argentina'}
|
154
|
+
hash = @calculation.to_hash
|
155
|
+
hash.keys.map!(&:to_s).sort!.should == [ :profile_item_uid, :usage, :country,
|
156
|
+
:profile_uid ].map!(&:to_s).sort!
|
157
|
+
hash[:co2].should be_a NilClass
|
158
|
+
hash[:usage][:unit].should be_a Quantify::Unit::NonSI
|
159
|
+
hash[:usage][:value].should == 600000
|
160
|
+
hash[:usage][:unit].name.should == 'kilowatt hour'
|
161
|
+
hash[:country][:value].should == 'Argentina'
|
162
|
+
@calculation.type.should == :electricity
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should find by atttribute" do
|
166
|
+
calc = Calculation.find :first, :conditions => {:calculation_type => 'electricity'}
|
167
|
+
calc.class.should == Calculation
|
168
|
+
calc.type.should == :electricity
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
|
174
|
+
|
175
|
+
end
|
176
|
+
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper.rb'
|
2
|
+
|
3
|
+
describe AMEE::Db::Config do
|
4
|
+
|
5
|
+
describe 'with everything stored' do
|
6
|
+
|
7
|
+
before :all do
|
8
|
+
flexmock(YAML) do |mock|
|
9
|
+
mock.should_receive(:load_file).and_return('method' => 'everything').once
|
10
|
+
end
|
11
|
+
@config = AMEE::Db::BaseConfig.new
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should load method from file' do
|
15
|
+
@config.storage_method.should be(:everything)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should correctly answer query methods' do
|
19
|
+
@config.store_metadata?.should be_true
|
20
|
+
@config.store_outputs?.should be_true
|
21
|
+
@config.store_everything?.should be_true
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'with metadata stored' do
|
27
|
+
|
28
|
+
before :all do
|
29
|
+
flexmock(YAML) do |mock|
|
30
|
+
mock.should_receive(:load_file).and_return('method' => 'metadata').once
|
31
|
+
end
|
32
|
+
@config = AMEE::Db::BaseConfig.new
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should correctly answer query methods' do
|
36
|
+
@config.store_metadata?.should be_true
|
37
|
+
@config.store_outputs?.should be_false
|
38
|
+
@config.store_everything?.should be_false
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'with outputs stored' do
|
44
|
+
|
45
|
+
before :all do
|
46
|
+
flexmock(YAML) do |mock|
|
47
|
+
mock.should_receive(:load_file).and_return('method' => 'outputs').once
|
48
|
+
end
|
49
|
+
@config = AMEE::Db::BaseConfig.new
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should correctly answer query methods' do
|
53
|
+
@config.store_metadata?.should be_true
|
54
|
+
@config.store_outputs?.should be_true
|
55
|
+
@config.store_everything?.should be_false
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'with invalid method' do
|
61
|
+
|
62
|
+
before :all do
|
63
|
+
flexmock(YAML) do |mock|
|
64
|
+
mock.should_receive(:load_file).and_return('method' => 'invalid').once
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should raise an exception on load' do
|
69
|
+
lambda {
|
70
|
+
AMEE::Db::BaseConfig.new
|
71
|
+
}.should raise_error
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
describe 'with invalid data in file' do
|
77
|
+
|
78
|
+
before :all do
|
79
|
+
flexmock(YAML) do |mock|
|
80
|
+
mock.should_receive(:load_file).and_return({}).once
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should raise an exception on load' do
|
85
|
+
lambda {
|
86
|
+
AMEE::Db::BaseConfig.new
|
87
|
+
}.should raise_error
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
@@ -0,0 +1,356 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe AMEE::DataAbstraction::OngoingCalculation do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
populate_db
|
7
|
+
initialize_calculation_set
|
8
|
+
end
|
9
|
+
|
10
|
+
after(:all) do
|
11
|
+
AMEE::Db::Calculation.delete_all
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "find" do
|
15
|
+
|
16
|
+
before(:each) do
|
17
|
+
choose_mock
|
18
|
+
yaml_load_mock(:everything)
|
19
|
+
@reference = AMEE::Db::Calculation.find(:first).id
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should create new ongoing calculation from db record" do
|
23
|
+
@db_calculation = AMEE::Db::Calculation.find :first
|
24
|
+
@ongoing_calculation = AMEE::DataAbstraction::OngoingCalculation.initialize_from_db_record @db_calculation
|
25
|
+
@ongoing_calculation.is_a?(AMEE::DataAbstraction::OngoingCalculation).should be_true
|
26
|
+
@ongoing_calculation.label.should == :electricity
|
27
|
+
@ongoing_calculation.profile_item_uid.should == "J38DY57SK591"
|
28
|
+
@ongoing_calculation.profile_uid.should be_nil
|
29
|
+
hash = @ongoing_calculation.to_hash
|
30
|
+
hash[:co2][:value].should == 1200
|
31
|
+
hash[:country][:value].should == 'Argentina'
|
32
|
+
hash[:usage][:value].should == 6000
|
33
|
+
hash[:profile_item_uid].should == "J38DY57SK591"
|
34
|
+
hash[:profile_uid].should be_nil
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should create new ongoing calculation from db record with find" do
|
38
|
+
@ongoing_calculation = AMEE::DataAbstraction::OngoingCalculation.find :first
|
39
|
+
@ongoing_calculation.is_a?(AMEE::DataAbstraction::OngoingCalculation).should be_true
|
40
|
+
@ongoing_calculation.label.should == :electricity
|
41
|
+
@ongoing_calculation.profile_item_uid.should == "J38DY57SK591"
|
42
|
+
@ongoing_calculation.profile_uid.should be_nil
|
43
|
+
hash = @ongoing_calculation.to_hash
|
44
|
+
hash[:co2][:value].should == 1200
|
45
|
+
hash[:country][:value].should == 'Argentina'
|
46
|
+
hash[:usage][:value].should == 6000
|
47
|
+
hash[:profile_item_uid].should == "J38DY57SK591"
|
48
|
+
hash[:profile_uid].should be_nil
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should create new ongoing calculation from db record with find and calculation type" do
|
52
|
+
@ongoing_calculation = AMEE::DataAbstraction::OngoingCalculation.find :first, :conditions => {:calculation_type => 'electricity'}
|
53
|
+
@ongoing_calculation.label.should == :electricity
|
54
|
+
@ongoing_calculation.is_a?(AMEE::DataAbstraction::OngoingCalculation).should be_true
|
55
|
+
@ongoing_calculation.profile_item_uid.should == "J38DY57SK591"
|
56
|
+
@ongoing_calculation.profile_uid.should be_nil
|
57
|
+
hash = @ongoing_calculation.to_hash
|
58
|
+
hash[:co2][:value].should == 1200
|
59
|
+
hash[:country][:value].should == 'Argentina'
|
60
|
+
hash[:usage][:value].should == 6000
|
61
|
+
hash[:profile_item_uid].should == "J38DY57SK591"
|
62
|
+
hash[:profile_uid].should be_nil
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should create new ongoing calculation from db record with find and profile item uid" do
|
66
|
+
@ongoing_calculation = AMEE::DataAbstraction::OngoingCalculation.find :first, :conditions => {:profile_item_uid => "K588DH47SMN5"}
|
67
|
+
@ongoing_calculation.label.should == :electricity
|
68
|
+
@ongoing_calculation.is_a?(AMEE::DataAbstraction::OngoingCalculation).should be_true
|
69
|
+
@ongoing_calculation.profile_item_uid.should == "K588DH47SMN5"
|
70
|
+
@ongoing_calculation.profile_uid.should == "H9KJ49FKIWO5"
|
71
|
+
hash = @ongoing_calculation.to_hash
|
72
|
+
hash[:co2][:value].should == 1.2
|
73
|
+
hash[:country][:value].should == 'Argentina'
|
74
|
+
hash[:usage][:value].should == 12345
|
75
|
+
hash[:profile_item_uid].should == "K588DH47SMN5"
|
76
|
+
hash[:profile_uid].should == "H9KJ49FKIWO5"
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should create multiple new ongoing calculations from db record with find" do
|
80
|
+
@ongoing_calculations = AMEE::DataAbstraction::OngoingCalculation.find :all
|
81
|
+
@ongoing_calculations.class.should == AMEE::DataAbstraction::CalculationCollection
|
82
|
+
@ongoing_calculations.each do |on_calc|
|
83
|
+
on_calc.label.should == :electricity
|
84
|
+
on_calc.is_a?(AMEE::DataAbstraction::OngoingCalculation).should be_true
|
85
|
+
on_calc.profile_item_uid.should_not be_nil
|
86
|
+
hash = on_calc.to_hash
|
87
|
+
hash[:co2][:value].should_not be_nil
|
88
|
+
hash[:country][:value].should == 'Argentina'
|
89
|
+
hash[:usage][:value].should_not be_nil
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should create new ongoing calculation from db record with #find_by_type" do
|
94
|
+
@ongoing_calculation = AMEE::DataAbstraction::OngoingCalculation.find_by_type :first, :electricity
|
95
|
+
@ongoing_calculation.label.should == :electricity
|
96
|
+
@ongoing_calculation.is_a?(AMEE::DataAbstraction::OngoingCalculation).should be_true
|
97
|
+
@ongoing_calculation.profile_item_uid.should == "J38DY57SK591"
|
98
|
+
@ongoing_calculation.profile_uid.should == nil
|
99
|
+
hash = @ongoing_calculation.to_hash
|
100
|
+
hash[:co2][:value].should == 1200
|
101
|
+
hash[:country][:value].should == 'Argentina'
|
102
|
+
hash[:usage][:value].should == 6000
|
103
|
+
hash[:profile_item_uid].should == "J38DY57SK591"
|
104
|
+
hash[:profile_uid].should == nil
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should create multiple new ongoing calculations from db record with #find_by_type" do
|
108
|
+
@ongoing_calculations = AMEE::DataAbstraction::OngoingCalculation.find_by_type :all, :electricity
|
109
|
+
@ongoing_calculations.class.should == AMEE::DataAbstraction::CalculationCollection
|
110
|
+
@ongoing_calculations.each do |on_calc|
|
111
|
+
on_calc.label.should == :electricity
|
112
|
+
on_calc.is_a?(AMEE::DataAbstraction::OngoingCalculation).should be_true
|
113
|
+
on_calc.profile_item_uid.should_not be_nil
|
114
|
+
hash = on_calc.to_hash
|
115
|
+
hash[:co2][:value].should_not be_nil
|
116
|
+
hash[:country][:value].should == 'Argentina'
|
117
|
+
hash[:usage][:value].should_not be_nil
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should instantiate record at ongoing calc #db_calculation attribute" do
|
122
|
+
@ongoing_calculation = AMEE::DataAbstraction::OngoingCalculation.find :first
|
123
|
+
@ongoing_calculation.label.should == :electricity
|
124
|
+
@ongoing_calculation.to_hash[:co2][:value].should == 1200
|
125
|
+
@ongoing_calculation.db_calculation.is_a?(AMEE::Db::Calculation).should be_true
|
126
|
+
@ongoing_calculation.db_calculation.id.should == @reference
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should find assocaited db instance by id" do
|
130
|
+
@ongoing_calculation = AMEE::DataAbstraction::OngoingCalculation.find @reference
|
131
|
+
@ongoing_calculation.id.should == @reference
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
it "should give nil id, if not saved" do
|
136
|
+
Calculations[:electricity].begin_calculation.db_calculation.should be_nil
|
137
|
+
Calculations[:electricity].begin_calculation.id.should be_nil
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe "when storage method is :everything" do
|
142
|
+
|
143
|
+
before(:each) do
|
144
|
+
choose_mock
|
145
|
+
yaml_load_mock(:everything)
|
146
|
+
@ongoing_calculation = AMEE::DataAbstraction::OngoingCalculation.find :first
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should find storage method" do
|
150
|
+
AMEE::DataAbstraction::OngoingCalculation.storage_method.should == :everything
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should start off dirty" do
|
154
|
+
@ongoing_calculation.should be_dirty
|
155
|
+
end
|
156
|
+
|
157
|
+
it "should establish whether inputs to be stored" do
|
158
|
+
AMEE::DataAbstraction::OngoingCalculation.store_inputs?.should be_true
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should establish whether outputs to be stored" do
|
162
|
+
AMEE::DataAbstraction::OngoingCalculation.store_outputs?.should be_true
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should establish whether metadata to be stored" do
|
166
|
+
AMEE::DataAbstraction::OngoingCalculation.store_metadata?.should be_true
|
167
|
+
end
|
168
|
+
|
169
|
+
it "should return array of terms for storing which includes all terms" do
|
170
|
+
@ongoing_calculation.stored_terms.should == @ongoing_calculation.terms
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should return hash with all terms" do
|
174
|
+
hash = @ongoing_calculation.to_hash
|
175
|
+
hash.is_a?(Hash).should be_true
|
176
|
+
hash.should == @ongoing_calculation.to_hash(:full)
|
177
|
+
hash.keys.map!(&:to_s).sort!.should == [:profile_item_uid, :profile_uid, :calculation_type,
|
178
|
+
:co2, :usage, :country ].map!(&:to_s).sort!
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should save all terms" do
|
182
|
+
record = @ongoing_calculation.db_calculation
|
183
|
+
# show that db record has values
|
184
|
+
record.to_hash.keys.map!(&:to_s).sort!.should == [:profile_item_uid, :profile_uid, :co2,
|
185
|
+
:usage, :country ].map!(&:to_s).sort!
|
186
|
+
record.to_hash[:co2][:value].should == 1200
|
187
|
+
record.to_hash[:usage][:value].should == 6000
|
188
|
+
# wipe terms from db record by updating with nothing
|
189
|
+
record.update_calculation!(options={})
|
190
|
+
# show that db record contains no terms
|
191
|
+
record.to_hash.keys.map!(&:to_s).sort!.should == [:profile_item_uid, :profile_uid ].map!(&:to_s).sort!
|
192
|
+
# show that by saving ongoing calculation, db record has terms
|
193
|
+
@ongoing_calculation.save
|
194
|
+
record = @ongoing_calculation.db_calculation
|
195
|
+
record.to_hash.keys.map!(&:to_s).sort!.should == [:profile_item_uid, :profile_uid, :co2,
|
196
|
+
:usage, :country ].map!(&:to_s).sort!
|
197
|
+
record.to_hash[:co2][:value].should == 1200
|
198
|
+
record.to_hash[:usage][:value].should == 6000
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
|
203
|
+
describe "when storage method is :metadata" do
|
204
|
+
|
205
|
+
before(:each) do
|
206
|
+
choose_mock
|
207
|
+
yaml_load_mock(:metadata)
|
208
|
+
@ongoing_calculation = AMEE::DataAbstraction::OngoingCalculation.find :first
|
209
|
+
end
|
210
|
+
|
211
|
+
it "should find storage method" do
|
212
|
+
AMEE::DataAbstraction::OngoingCalculation.storage_method.should == :metadata
|
213
|
+
end
|
214
|
+
|
215
|
+
it "should establish whether inputs to be stored" do
|
216
|
+
AMEE::DataAbstraction::OngoingCalculation.store_inputs?.should be_false
|
217
|
+
end
|
218
|
+
|
219
|
+
it "should establish whether outputs to be stored" do
|
220
|
+
AMEE::DataAbstraction::OngoingCalculation.store_outputs?.should be_false
|
221
|
+
end
|
222
|
+
|
223
|
+
it "should establish whether metadata to be stored" do
|
224
|
+
AMEE::DataAbstraction::OngoingCalculation.store_metadata?.should be_true
|
225
|
+
end
|
226
|
+
|
227
|
+
it "should start off dirty" do
|
228
|
+
@ongoing_calculation.should be_dirty
|
229
|
+
end
|
230
|
+
|
231
|
+
it "should return array of terms for storing which includes only metadata" do
|
232
|
+
@ongoing_calculation.stored_terms.should_not == @ongoing_calculation.terms
|
233
|
+
end
|
234
|
+
|
235
|
+
it "should return hash with only metadata terms" do
|
236
|
+
hash = @ongoing_calculation.to_hash
|
237
|
+
hash.is_a?(Hash).should be_true
|
238
|
+
hash.should_not == @ongoing_calculation.to_hash(:full)
|
239
|
+
hash.keys.map!(&:to_s).sort!.should == [:profile_item_uid, :profile_uid,
|
240
|
+
:calculation_type ].map!(&:to_s).sort!
|
241
|
+
end
|
242
|
+
|
243
|
+
it "should save only metadata terms" do
|
244
|
+
record = @ongoing_calculation.db_calculation
|
245
|
+
# show that db record has values
|
246
|
+
record.to_hash.keys.map!(&:to_s).sort!.should == [:profile_item_uid, :profile_uid, :co2,
|
247
|
+
:usage, :country ].map!(&:to_s).sort!
|
248
|
+
record.to_hash[:co2][:value].should == 1200
|
249
|
+
record.to_hash[:usage][:value].should == 6000
|
250
|
+
# show that db record contains no terms after save
|
251
|
+
@ongoing_calculation.save
|
252
|
+
record = @ongoing_calculation.db_calculation
|
253
|
+
record.to_hash.keys.map!(&:to_s).sort!.should == [:profile_item_uid, :profile_uid ].map!(&:to_s).sort!
|
254
|
+
record.to_hash[:co2].should == nil
|
255
|
+
record.to_hash[:usage].should == nil
|
256
|
+
end
|
257
|
+
|
258
|
+
end
|
259
|
+
|
260
|
+
describe "when storage method is :outputs" do
|
261
|
+
|
262
|
+
before(:each) do
|
263
|
+
choose_mock
|
264
|
+
yaml_load_mock(:outputs)
|
265
|
+
@ongoing_calculation = AMEE::DataAbstraction::OngoingCalculation.find :first
|
266
|
+
end
|
267
|
+
|
268
|
+
it "should find storage method" do
|
269
|
+
AMEE::DataAbstraction::OngoingCalculation.storage_method.should == :outputs
|
270
|
+
end
|
271
|
+
|
272
|
+
it "should establish whether inputs to be stored" do
|
273
|
+
AMEE::DataAbstraction::OngoingCalculation.store_inputs?.should be_false
|
274
|
+
end
|
275
|
+
|
276
|
+
it "should establish whether outputs to be stored" do
|
277
|
+
AMEE::DataAbstraction::OngoingCalculation.store_outputs?.should be_true
|
278
|
+
end
|
279
|
+
|
280
|
+
it "should establish whether metadata to be stored" do
|
281
|
+
AMEE::DataAbstraction::OngoingCalculation.store_metadata?.should be_true
|
282
|
+
end
|
283
|
+
|
284
|
+
it "should start off dirty" do
|
285
|
+
@ongoing_calculation.should be_dirty
|
286
|
+
end
|
287
|
+
|
288
|
+
it "should return array of terms for storing which includes only outputs and metadata" do
|
289
|
+
@ongoing_calculation.stored_terms.should_not == @ongoing_calculation.terms
|
290
|
+
end
|
291
|
+
|
292
|
+
it "should return hash with only output and metadata terms" do
|
293
|
+
hash = @ongoing_calculation.to_hash
|
294
|
+
hash.is_a?(Hash).should be_true
|
295
|
+
hash.should_not == @ongoing_calculation.to_hash(:full)
|
296
|
+
hash.keys.map!(&:to_s).sort!.should == [:profile_item_uid, :profile_uid,
|
297
|
+
:calculation_type, :co2 ].map!(&:to_s).sort!
|
298
|
+
end
|
299
|
+
|
300
|
+
it "should save only output terms" do
|
301
|
+
record = @ongoing_calculation.db_calculation
|
302
|
+
# show that db record has all values
|
303
|
+
record.to_hash.keys.map!(&:to_s).sort!.should == [:profile_item_uid, :profile_uid, :co2,
|
304
|
+
:usage, :country ].map!(&:to_s).sort!
|
305
|
+
record.to_hash[:co2][:value].should == 1200
|
306
|
+
record.to_hash[:usage][:value].should == 6000
|
307
|
+
# show that db record contains only output terms after save
|
308
|
+
@ongoing_calculation.save
|
309
|
+
record = @ongoing_calculation.db_calculation
|
310
|
+
record.to_hash.keys.map!(&:to_s).sort!.should == [:profile_item_uid, :profile_uid, :co2 ].map!(&:to_s).sort!
|
311
|
+
record.to_hash[:co2][:value].should == 1200
|
312
|
+
record.to_hash[:usage].should == nil
|
313
|
+
end
|
314
|
+
|
315
|
+
end
|
316
|
+
|
317
|
+
describe "saving" do
|
318
|
+
|
319
|
+
before :each do
|
320
|
+
choose_mock
|
321
|
+
yaml_load_mock(:outputs)
|
322
|
+
@ongoing_calculation = AMEE::DataAbstraction::OngoingCalculation.find :first
|
323
|
+
end
|
324
|
+
|
325
|
+
it "should return true if successful" do
|
326
|
+
@ongoing_calculation.save.should eql true
|
327
|
+
end
|
328
|
+
|
329
|
+
it "should return false if unsuccessful" do
|
330
|
+
# Mock to make save fail
|
331
|
+
flexmock(@ongoing_calculation.db_calculation).should_receive(:save!).and_raise(ActiveRecord::RecordNotSaved)
|
332
|
+
# Saving should now return false, propogating errors from AR::Base
|
333
|
+
@ongoing_calculation.save.should eql false
|
334
|
+
end
|
335
|
+
|
336
|
+
end
|
337
|
+
|
338
|
+
describe "deleting calculation" do
|
339
|
+
|
340
|
+
before(:all) do
|
341
|
+
choose_mock
|
342
|
+
delete_mock
|
343
|
+
@ongoing_calculation = AMEE::DataAbstraction::OngoingCalculation.find :first
|
344
|
+
end
|
345
|
+
|
346
|
+
it "should remove record from db" do
|
347
|
+
db_reference = @ongoing_calculation.db_calculation.id
|
348
|
+
item_uid = @ongoing_calculation.send :profile_item_uid
|
349
|
+
@ongoing_calculation.delete
|
350
|
+
@ongoing_calculation.db_calculation.should be_nil
|
351
|
+
AMEE::Db::Calculation.find_by_profile_item_uid(item_uid).should be_nil
|
352
|
+
lambda{AMEE::Db::Calculation.find(db_reference)}.should raise_error
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
end
|