amee-data-abstraction 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.rvmrc +1 -0
- data/CHANGELOG.txt +4 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +41 -0
- data/LICENSE.txt +27 -0
- data/README.txt +188 -0
- data/Rakefile +102 -0
- data/VERSION +1 -0
- data/amee-data-abstraction.gemspec +115 -0
- data/examples/_calculator_form.erb +27 -0
- data/examples/calculation_controller.rb +16 -0
- data/init.rb +4 -0
- data/lib/amee-data-abstraction.rb +30 -0
- data/lib/amee-data-abstraction/calculation.rb +236 -0
- data/lib/amee-data-abstraction/calculation_set.rb +101 -0
- data/lib/amee-data-abstraction/drill.rb +63 -0
- data/lib/amee-data-abstraction/exceptions.rb +47 -0
- data/lib/amee-data-abstraction/input.rb +197 -0
- data/lib/amee-data-abstraction/metadatum.rb +58 -0
- data/lib/amee-data-abstraction/ongoing_calculation.rb +545 -0
- data/lib/amee-data-abstraction/output.rb +16 -0
- data/lib/amee-data-abstraction/profile.rb +108 -0
- data/lib/amee-data-abstraction/prototype_calculation.rb +350 -0
- data/lib/amee-data-abstraction/term.rb +506 -0
- data/lib/amee-data-abstraction/terms_list.rb +150 -0
- data/lib/amee-data-abstraction/usage.rb +90 -0
- data/lib/config/amee_units.rb +129 -0
- data/lib/core-extensions/class.rb +27 -0
- data/lib/core-extensions/hash.rb +43 -0
- data/lib/core-extensions/ordered_hash.rb +21 -0
- data/lib/core-extensions/proc.rb +15 -0
- data/rails/init.rb +32 -0
- data/spec/amee-data-abstraction/calculation_set_spec.rb +54 -0
- data/spec/amee-data-abstraction/calculation_spec.rb +75 -0
- data/spec/amee-data-abstraction/drill_spec.rb +38 -0
- data/spec/amee-data-abstraction/input_spec.rb +77 -0
- data/spec/amee-data-abstraction/metadatum_spec.rb +17 -0
- data/spec/amee-data-abstraction/ongoing_calculation_spec.rb +494 -0
- data/spec/amee-data-abstraction/profile_spec.rb +39 -0
- data/spec/amee-data-abstraction/prototype_calculation_spec.rb +256 -0
- data/spec/amee-data-abstraction/term_spec.rb +385 -0
- data/spec/amee-data-abstraction/terms_list_spec.rb +53 -0
- data/spec/config/amee_units_spec.rb +71 -0
- data/spec/core-extensions/class_spec.rb +25 -0
- data/spec/core-extensions/hash_spec.rb +44 -0
- data/spec/core-extensions/ordered_hash_spec.rb +12 -0
- data/spec/core-extensions/proc_spec.rb +12 -0
- data/spec/fixtures/electricity.rb +35 -0
- data/spec/fixtures/electricity_and_transport.rb +55 -0
- data/spec/fixtures/transport.rb +26 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +244 -0
- metadata +262 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
<% form_id = "drill-form-#{rand(1e8)}" %>
|
2
|
+
<% form_tag({:action=>nil},{:id=>form_id}) do%>
|
3
|
+
<%= hidden_field_tag 'form_id', form_id %>
|
4
|
+
<table>
|
5
|
+
<%@calculation.drills.each_value do |input|%>
|
6
|
+
<tr>
|
7
|
+
<td><%=label :entry,input.label,input.name%></td>
|
8
|
+
<td>
|
9
|
+
<%= select_tag "entry[#{input.label}]",
|
10
|
+
options_for_select(input.options_for_select,input.set? ? input.value : nil),:disabled=>input.disabled?%>
|
11
|
+
</td>
|
12
|
+
</tr>
|
13
|
+
<%end%>
|
14
|
+
<%@calculation.profiles.each_value do |input|%>
|
15
|
+
<tr><td><%=label :entry,input.label,input.name%></td><td><%= text_field :entry, input.label, "size" => 20, :value => input.value_if_given %></td></tr>
|
16
|
+
<%end%>
|
17
|
+
<%@calculation.chosen_outputs.each_value do |result|%>
|
18
|
+
<tr><td><%=label :entry,result.label,result.name%></td><td><%= result.value_if_given %></td></tr>
|
19
|
+
<%end%>
|
20
|
+
</table>
|
21
|
+
<%end%>
|
22
|
+
<%= observe_form form_id, :url => {:action => 'result'}%>
|
23
|
+
<% javascript_tag do %>
|
24
|
+
$('#<%=form_id%>').submit(function() {
|
25
|
+
return false;
|
26
|
+
});
|
27
|
+
<%end%>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class CalculationController < ApplicationController
|
2
|
+
def index
|
3
|
+
@calculations=Calculations.calculations.values
|
4
|
+
end
|
5
|
+
|
6
|
+
def enter
|
7
|
+
@calculation=Calculations[params[:calculation]]
|
8
|
+
end
|
9
|
+
|
10
|
+
def result
|
11
|
+
@calculation=Calculations[params[:calculation]].clone
|
12
|
+
@calculation.choose!(params['entry'])
|
13
|
+
@calculation.calculate!
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1,30 @@
|
|
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
|
+
require 'amee'
|
5
|
+
require 'uuidtools'
|
6
|
+
require 'quantify'
|
7
|
+
|
8
|
+
require File.dirname(__FILE__) + '/core-extensions/class'
|
9
|
+
require File.dirname(__FILE__) + '/core-extensions/ordered_hash'
|
10
|
+
require File.dirname(__FILE__) + '/core-extensions/hash'
|
11
|
+
require File.dirname(__FILE__) + '/core-extensions/proc'
|
12
|
+
require File.dirname(__FILE__) + '/config/amee_units'
|
13
|
+
require File.dirname(__FILE__) + '/amee-data-abstraction/exceptions'
|
14
|
+
require File.dirname(__FILE__) + '/amee-data-abstraction/terms_list'
|
15
|
+
require File.dirname(__FILE__) + '/amee-data-abstraction/calculation'
|
16
|
+
require File.dirname(__FILE__) + '/amee-data-abstraction/ongoing_calculation'
|
17
|
+
require File.dirname(__FILE__) + '/amee-data-abstraction/prototype_calculation'
|
18
|
+
require File.dirname(__FILE__) + '/amee-data-abstraction/calculation_set'
|
19
|
+
require File.dirname(__FILE__) + '/amee-data-abstraction/term'
|
20
|
+
require File.dirname(__FILE__) + '/amee-data-abstraction/input'
|
21
|
+
require File.dirname(__FILE__) + '/amee-data-abstraction/drill'
|
22
|
+
require File.dirname(__FILE__) + '/amee-data-abstraction/profile'
|
23
|
+
require File.dirname(__FILE__) + '/amee-data-abstraction/usage'
|
24
|
+
require File.dirname(__FILE__) + '/amee-data-abstraction/output'
|
25
|
+
require File.dirname(__FILE__) + '/amee-data-abstraction/metadatum'
|
26
|
+
|
27
|
+
module AMEE::DataAbstraction
|
28
|
+
# Connection to AMEE server.
|
29
|
+
mattr_accessor :connection
|
30
|
+
end
|
@@ -0,0 +1,236 @@
|
|
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::DataAbstraction::Calculation
|
5
|
+
|
6
|
+
module AMEE
|
7
|
+
module DataAbstraction
|
8
|
+
|
9
|
+
# Base class providing attributes and methods for representing a calculation
|
10
|
+
# which can be made using the AMEE platform. An instance of <i>Calculation</i>
|
11
|
+
# will typically be associated with a specific AMEE category.
|
12
|
+
#
|
13
|
+
# Instances of <i>Calculation</i> are represented by several primary attributes:
|
14
|
+
#
|
15
|
+
# label:: Symbol representing the unique, machine-readable name for the
|
16
|
+
# calculation
|
17
|
+
#
|
18
|
+
# name:: String representing a human-readable name for the calculation
|
19
|
+
#
|
20
|
+
# path:: String representing the AMEE platform path to the data category
|
21
|
+
# which is associated with <tt>self</tt>
|
22
|
+
#
|
23
|
+
# fixed_usage:: String representing the AMEE platform path for the usage to
|
24
|
+
# be used by <tt>self</tt>, if defined
|
25
|
+
#
|
26
|
+
# An instance of <i>Calculation</i> also holds an arbitrary number of objects
|
27
|
+
# of the class <i>Term</i>. These represent values associated with the
|
28
|
+
# calculation, e.g. inputs, outputs, metadatum, etc. These can be accessed
|
29
|
+
# using the <tt>#terms</tt> methods or the term subset methods provided by
|
30
|
+
# the <tt>TermsList</tt> class (e.g. <tt>#profiles</tt>, <tt>#visible</tt>)
|
31
|
+
#
|
32
|
+
# Two classes inherit the <i>Calculation</i> class:
|
33
|
+
# * <i>PrototypeCalculation</i> : provides a templating for a specific calculation
|
34
|
+
# type with defined, but blank, terms (i.e. inputs, outputs, etc.)
|
35
|
+
#
|
36
|
+
# * <i>OngoingCalculation</i> : represents a particular calculation - possibly
|
37
|
+
# incomplete - which can be updated, submitted for calculation, and saved
|
38
|
+
#
|
39
|
+
class Calculation
|
40
|
+
|
41
|
+
public
|
42
|
+
|
43
|
+
# Symbol representing the unique, machine-readable name for <tt>self</tt>.
|
44
|
+
# Set a value by passing an argument. Retrieve a value by calling without
|
45
|
+
# an argument, e.g.,
|
46
|
+
#
|
47
|
+
# my_calculation.label :fuel
|
48
|
+
#
|
49
|
+
# my_calculation.label #=> :fuel
|
50
|
+
#
|
51
|
+
attr_property :label
|
52
|
+
|
53
|
+
# String representing a human-readable name for <tt>self</tt>. Set a
|
54
|
+
# value by passing an argument. Retrieve a value by calling without an
|
55
|
+
# argument, e.g.,
|
56
|
+
#
|
57
|
+
# my_calculation.name 'Domestic fuel consumption'
|
58
|
+
#
|
59
|
+
# my_calculation.name #=> 'Domestic fuel consumption'
|
60
|
+
#
|
61
|
+
attr_property :name
|
62
|
+
|
63
|
+
# String representing the AMEE platform path to the data category which is
|
64
|
+
# associated with <tt>self</tt>. Set a value by passing an argument. Retrieve
|
65
|
+
# a value by calling without an argument, e.g.,
|
66
|
+
#
|
67
|
+
# my_calculation.path '/some/path/in/amee/'
|
68
|
+
#
|
69
|
+
# my_calculation.path #=> '/some/path/in/amee/'
|
70
|
+
#
|
71
|
+
attr_property :path
|
72
|
+
|
73
|
+
# String representing the AMEE platform path for the usage to be used by
|
74
|
+
# <tt>self</tt>, if defined. Set a value by passing an argument. Retrieve
|
75
|
+
# a value by calling without an argument, e.g.,
|
76
|
+
#
|
77
|
+
# my_calculation.fixed_usage 'byMass'
|
78
|
+
#
|
79
|
+
# my_calculation.fixed_usage #=> 'byMass'
|
80
|
+
#
|
81
|
+
attr_property :fixed_usage
|
82
|
+
|
83
|
+
# Calculations contain a list of "terms" of the base class <i>Term</i>,
|
84
|
+
# representing inputs, outputs, metadatum, etc. which are associated with
|
85
|
+
# <tt>self</tt>.
|
86
|
+
#
|
87
|
+
# Returns all associated terms as an instance of the <i>TermsList</i> class
|
88
|
+
#
|
89
|
+
def terms
|
90
|
+
TermsList.new(@contents.values)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Retrieve the terms associated with <tt>self</tt> as a hash from labels to terms.
|
94
|
+
attr_accessor :contents
|
95
|
+
|
96
|
+
# Shorthand method for retrieving the term assocaited with <tt>self</tt> which has a
|
97
|
+
# label matching <tt>sym</tt>
|
98
|
+
#
|
99
|
+
def [](sym)
|
100
|
+
@contents[sym.to_sym]
|
101
|
+
end
|
102
|
+
|
103
|
+
# Syntactic sugar to enable the return of a subset of associated terms according
|
104
|
+
# to their type or status (e.g. drills, profiles, set, unset, visible). See
|
105
|
+
# <i>TermsList::Selectors</i> for valid variants
|
106
|
+
#
|
107
|
+
TermsList::Selectors.each do |sel|
|
108
|
+
delegate sel,:to=>:terms
|
109
|
+
end
|
110
|
+
|
111
|
+
# Prettyprint a string representation of <tt>self</tt>, together with associated terms
|
112
|
+
def inspect
|
113
|
+
elements = {:label => label.inspect, :terms => terms.map{|t| "<#{t.class.name.demodulize} label:#{t.label}, value:#{t.value.inspect}>"}}
|
114
|
+
attr_list = elements.map {|k,v| "#{k}: #{v}" } * ', '
|
115
|
+
"<#{self.class.name} #{attr_list}>"
|
116
|
+
end
|
117
|
+
|
118
|
+
def initialize_copy(source)
|
119
|
+
super
|
120
|
+
@contents=ActiveSupport::OrderedHash.new
|
121
|
+
source.contents.each do |k,v|
|
122
|
+
@contents[k]=v.clone
|
123
|
+
@contents[k].parent=self
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# Return a string representing the AMEE Explorer URL which is assocaited
|
128
|
+
# with <tt>self</tt>
|
129
|
+
#
|
130
|
+
def explorer_url
|
131
|
+
"http://explorer.amee.com/categories#{path}"
|
132
|
+
end
|
133
|
+
|
134
|
+
protected
|
135
|
+
|
136
|
+
def initialize
|
137
|
+
@contents=ActiveSupport::OrderedHash.new
|
138
|
+
end
|
139
|
+
|
140
|
+
# Methods which will be memoized at application start, as they do not
|
141
|
+
# change over application instance lifetime
|
142
|
+
#
|
143
|
+
AmeeMemoised=[:amee_data_category, :amee_item_definition, :amee_ivds,
|
144
|
+
:amee_return_values, :amee_usages]
|
145
|
+
|
146
|
+
# Return all the values of the memoized quantities
|
147
|
+
def saved_amee
|
148
|
+
AmeeMemoised.map{|x|instance_variable_get("@#{x.to_s}")}
|
149
|
+
end
|
150
|
+
|
151
|
+
# Save the memoized quantities
|
152
|
+
def save_amee(values)
|
153
|
+
AmeeMemoised.zip(values).each do |prop,val|
|
154
|
+
instance_variable_set("@#{prop.to_s}",val)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
private
|
159
|
+
|
160
|
+
# Return the global <i>AMEE::Connection</i> object. This is configured in
|
161
|
+
# /config/amee.yml
|
162
|
+
#
|
163
|
+
def connection
|
164
|
+
AMEE::DataAbstraction.connection
|
165
|
+
end
|
166
|
+
|
167
|
+
# Return the <i>AMEE::Data::Category</i> object associated with <tt>self</tt>
|
168
|
+
def amee_data_category
|
169
|
+
@amee_data_category||=AMEE::Data::Category.get(connection, "/data#{path}")
|
170
|
+
end
|
171
|
+
|
172
|
+
# Return the <i>AMEE::Admin::ItemDefinition</i> object associated with <tt>self</tt>
|
173
|
+
def amee_item_definition
|
174
|
+
@amee_item_definition||=amee_data_category.item_definition
|
175
|
+
end
|
176
|
+
|
177
|
+
# Return the <i>AMEE::Admin::ReturnValueDefinitionList</i> object associated
|
178
|
+
# with <tt>self</tt>. This represents each of the return value definitions which are
|
179
|
+
# associated with the calculation
|
180
|
+
#
|
181
|
+
def amee_return_values
|
182
|
+
@amee_return_values||=AMEE::Admin::ReturnValueDefinitionList.new(connection,amee_item_definition.uid)
|
183
|
+
end
|
184
|
+
|
185
|
+
# Return the instance of <i>Term</i> class associated with <tt>self</tt> and contains
|
186
|
+
# a path attribute matching <tt>path</tt>, e.g.
|
187
|
+
#
|
188
|
+
# my_calculation.by_path('distance') #=> <AMEE::DataAbstraction::Profile ... >
|
189
|
+
#
|
190
|
+
# my_calculation.by_path('type') #=> <AMEE::DataAbstraction::Drill ... >
|
191
|
+
#
|
192
|
+
def by_path(path)
|
193
|
+
terms.detect { |v| v.path==path }
|
194
|
+
end
|
195
|
+
|
196
|
+
# Return the instance of <i>Drill</i> class associated with <tt>self</tt> and contains
|
197
|
+
# a path attribute matching <tt>path</tt>, e.g.
|
198
|
+
#
|
199
|
+
# my_calculation.by_path('type') #=> <AMEE::DataAbstraction::Drill ... >
|
200
|
+
#
|
201
|
+
def drill_by_path(path)
|
202
|
+
drills.detect { |v| v.path==path }
|
203
|
+
end
|
204
|
+
|
205
|
+
public
|
206
|
+
|
207
|
+
# Return the <i>AMEE::Admin::ItemValueDefinitionList</i> object associated
|
208
|
+
# with <tt>self</tt>. This represents each of the item value definitions which are
|
209
|
+
# associated with the calculation
|
210
|
+
#
|
211
|
+
def amee_ivds
|
212
|
+
@amee_ivds||=amee_item_definition.item_value_definition_list.select{|x|x.versions.include?("2.0")}
|
213
|
+
end
|
214
|
+
|
215
|
+
# Returns a String representing the AMEE platform path for the usage currently
|
216
|
+
# used by <tt>self</tt>. If not usage is defined, returns nil
|
217
|
+
#
|
218
|
+
# my_calculation.current_usage #=> 'byMass'
|
219
|
+
#
|
220
|
+
def current_usage
|
221
|
+
usages.empty? ? fixed_usage : usages.first.value
|
222
|
+
end
|
223
|
+
|
224
|
+
# Returns an Array containing the AMEE platform paths for all valid usage
|
225
|
+
# available to <tt>self</tt> according to those defined under #item_definition. If
|
226
|
+
# no usage(s) is defined, returns nil, e.g.
|
227
|
+
#
|
228
|
+
# my_calculation.amee_usages #=> [ 'byMass', 'byEnergy' ]
|
229
|
+
#
|
230
|
+
def amee_usages
|
231
|
+
@amee_usages||=amee_item_definition.usages
|
232
|
+
end
|
233
|
+
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
@@ -0,0 +1,101 @@
|
|
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::DataAbstraction::CalculationSet
|
5
|
+
|
6
|
+
module AMEE
|
7
|
+
module DataAbstraction
|
8
|
+
|
9
|
+
# The <i>CalculationSet</i> class represents a collection of prototype
|
10
|
+
# calculations (of the class <i>ProtptypeCalculation</i>.
|
11
|
+
#
|
12
|
+
# Prototype calculations are contained within the @calculations instance variable
|
13
|
+
# ordered hash. Calculations can be added manually to the @calculations hash or
|
14
|
+
# initialized in place using the <tt>#calculation</tt> method which takes an
|
15
|
+
# options hash or block for specifying the prototype calculation properties.
|
16
|
+
#
|
17
|
+
# Typical usage is to initialize the <i>CalculationSet</i> and its daughter
|
18
|
+
# prototype calculations together using block syntax, thus:
|
19
|
+
#
|
20
|
+
# Calculations = CalculationSet.new {
|
21
|
+
#
|
22
|
+
# calculation {
|
23
|
+
# label :electricity
|
24
|
+
# path "/some/path/for/electricity"
|
25
|
+
# ...
|
26
|
+
# }
|
27
|
+
#
|
28
|
+
# calculation {
|
29
|
+
# label :transport
|
30
|
+
# path "a/transport/path"
|
31
|
+
# ...
|
32
|
+
# }
|
33
|
+
#
|
34
|
+
# ...
|
35
|
+
# }
|
36
|
+
#
|
37
|
+
class CalculationSet
|
38
|
+
|
39
|
+
# Initialize a <i>CalculationSet</i> with a "DSL" block, i.e. a block to be
|
40
|
+
# evaluated in the context of the instantiated CalculationSet
|
41
|
+
#
|
42
|
+
def initialize(options={},&block)
|
43
|
+
@calculations=ActiveSupport::OrderedHash.new
|
44
|
+
@all_blocks=[]
|
45
|
+
@all_options={}
|
46
|
+
instance_eval(&block) if block
|
47
|
+
end
|
48
|
+
|
49
|
+
# Access the @calculations instance variable ordered hash. Keys are labels
|
50
|
+
# assocaited with each prototype calculation; values are the instantiated
|
51
|
+
# <i>PrototypeCalculation</i> objects
|
52
|
+
#
|
53
|
+
attr_accessor :calculations
|
54
|
+
|
55
|
+
# Shorthand method for returning the prototype calculation which is represented
|
56
|
+
# by a label matching <tt>sym</tt>
|
57
|
+
#
|
58
|
+
def [](sym)
|
59
|
+
@calculations[sym.to_sym]
|
60
|
+
end
|
61
|
+
|
62
|
+
# Instantiate a <i>PrototypeCalculation</i> within this calculation set,
|
63
|
+
# initializing with the supplied DSL block to be evaluated in the context
|
64
|
+
# of the newly created calculation
|
65
|
+
#
|
66
|
+
def calculation(options={},&block)
|
67
|
+
new_content=PrototypeCalculation.new(options.merge(@all_options),&block)
|
68
|
+
@all_blocks.each {|all_block| new_content.instance_eval(&all_block) }
|
69
|
+
new_content.name new_content.label.to_s.humanize unless new_content.name
|
70
|
+
@calculations[new_content.label]=new_content
|
71
|
+
end
|
72
|
+
|
73
|
+
# Append the supplied block to the DSL block of ALL calculations in this
|
74
|
+
# calculation set. This is useful for configuration which is required
|
75
|
+
# across all calculations (e.g. overriding human readable names or adding
|
76
|
+
# globally applicable metadatum)
|
77
|
+
#
|
78
|
+
def all_calculations(options={},&dsl_block)
|
79
|
+
@all_blocks.push dsl_block
|
80
|
+
@all_options.merge(options)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Instantiate several prototype calculations, by loading each possible usage
|
84
|
+
# for the category with path given in <tt>apath</tt>.
|
85
|
+
#
|
86
|
+
# Each instantiated calculation is customised on the basis of the supplied
|
87
|
+
# DSL block. The usage is given as a parameter to the DSL block
|
88
|
+
#
|
89
|
+
def calculations_all_usages(apath,options={},&dsl_block)
|
90
|
+
dummycalc=PrototypeCalculation.new{path apath}
|
91
|
+
dummycalc.amee_usages.each do |usage|
|
92
|
+
calculation(options){
|
93
|
+
path apath
|
94
|
+
instance_exec(usage,&dsl_block)
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,63 @@
|
|
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::DataAbstraction::Drill
|
5
|
+
|
6
|
+
module AMEE
|
7
|
+
module DataAbstraction
|
8
|
+
|
9
|
+
# Subclass of <tt>Input</tt> providing methods and attributes appropriate for
|
10
|
+
# representing AMEE drill down choices and selections specifically
|
11
|
+
#
|
12
|
+
class Drill < Input
|
13
|
+
|
14
|
+
public
|
15
|
+
|
16
|
+
# Returns <tt>true</tt> if the UI element of <tt>self</tt> is disabled.
|
17
|
+
# Otherwise, returns <tt>false</tt>.
|
18
|
+
#
|
19
|
+
# A drill is considered disabled if it either (1) explicitly set using the
|
20
|
+
# <tt>#disable!</tt> method; (2) has a <i>fixed</i> value; or (3) is not the
|
21
|
+
# next drill (because drill should be chosen in order).
|
22
|
+
#
|
23
|
+
def disabled?
|
24
|
+
super || (!set? && !next?)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Initialization of <i>Drill</i> objects follows that of the parent
|
28
|
+
# <i>Input</i> class. The <tt>interface</tt> attribute of <tt>self</tt> is
|
29
|
+
# set to <tt>:drop_down</tt> by default for <tt>Drill</tt> instances, but
|
30
|
+
# can be manually configured if required.
|
31
|
+
#
|
32
|
+
def initialize(options={},&block)
|
33
|
+
interface :drop_down
|
34
|
+
super
|
35
|
+
choice_validation_message
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
# Returns <tt>true</tt> if the value set for <tt>self</tt> is one of the
|
41
|
+
# available choices. Otherwise, returns <tt>false</tt>.
|
42
|
+
#
|
43
|
+
def valid?
|
44
|
+
super && (choices.include? value)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns the list of available choices for <tt>self</tt>.
|
48
|
+
def choices
|
49
|
+
c=parent.amee_drill(:before=>label).choices
|
50
|
+
c.length==1 ? [value] : c #Intention is to get autodrilled, drill will result in a UID
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns <tt>true</tt> if <tt>self</tt> is the "first unset" drill, i.e.
|
54
|
+
# the one which should be set next
|
55
|
+
#
|
56
|
+
def next?
|
57
|
+
unset? && parent.drills.before(label).all?(&:set?)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|