Class: OperationType
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- OperationType
- Includes:
- CodeHelper, DataAssociator, FieldTyper, HasTiming, OperationTypeExport, OperationTypePlanner, OperationTypeRandom, OperationTypeWorkflow
- Defined in:
- app/models/operation_type.rb
Overview
Defines a type of lab procedure, with the input-types, output-types, and the instructions for converting inputs into outputs. Executable unit Operations can be instantiated from an OperationType, and specific inputs and outputs are then given.
Class Method Summary collapse
Instance Method Summary collapse
- #add_cost_model(content:, user:) ⇒ Object
- #add_input(name, sample_name, container_name, opts = {}) ⇒ Object
- #add_io(name, sample_name, container_name, role, opts) ⇒ Object
-
#add_new_allowable_field_type(ft, new_type) ⇒ Object
Update Methods for Field Types from Front End Start Here.
- #add_new_field_type(new_type) ⇒ Object
- #add_output(name, sample_name, container_name, opts = {}) ⇒ Object
- #add_parameter(name:, type:, choices:) ⇒ Object
- #add_precondition(content:, user:) ⇒ Object
- #add_protocol(content:, user:) ⇒ Object
- #add_test(content:, user:) ⇒ Object
-
#category ⇒ String
Gets category of OperationType.
- #cost_model ⇒ Object
- #documentation ⇒ Object
- #done ⇒ Object
- #error_out_obsolete_operations ⇒ Object
-
#input(name) ⇒ Object
Returns the input of this OperationType with the given name.
-
#inputs ⇒ Array<FieldType>
The input types of this OperationType.
-
#name ⇒ String
Gets name of OperationType.
-
#output(name) ⇒ FieldType
Returns the output of this OperationType with the given name.
-
#outputs ⇒ Array<FieldType>
The output types of this OperationType.
- #pending ⇒ Object
- #precondition ⇒ Object
- #protocol ⇒ Object
- #stats ⇒ Object
- #test ⇒ Object
- #update_allowable_field_type(old_aft, new_aft) ⇒ Object
- #update_field_type(old_type:, new_type:) ⇒ Object
- #update_field_types(fts) ⇒ Object
- #waiting ⇒ Object
Methods included from DataAssociator
#append_notes, #associate, #associations, #data_associations, #get, #get_association, #lazy_associate, #modify, #notes, #notes=, #upload
Class Method Details
.numbers(user = nil) ⇒ Object
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 |
# File 'app/models/operation_type.rb', line 323 def self.numbers(user = nil) q = if user.nil? " SELECT status, operation_type_id, COUNT(status) FROM operations GROUP BY operation_type_id, status " else " SELECT status, operation_type_id, COUNT(status) FROM operations WHERE user_id = #{user.id} GROUP BY operation_type_id, status " end r = ActiveRecord::Base.connection.execute(q).entries result = {} r.each do |status, ot_id, count| result[ot_id] ||= { planning: 0, waiting: 0, pending: 0, delayed: 0, deferred: 0, primed: 0, scheduled: 0, running: 0, error: 0, done: 0 } result[ot_id][status] = count result[ot_id][:waiting] = count if status == 'primed' end result end |
Instance Method Details
#add_cost_model(content:, user:) ⇒ Object
122 123 124 125 126 127 128 |
# File 'app/models/operation_type.rb', line 122 def add_cost_model(content:, user:) if cost_model cost_model.commit(content, user) else new_code('cost_model', content, user) end end |
#add_input(name, sample_name, container_name, opts = {}) ⇒ Object
45 46 47 |
# File 'app/models/operation_type.rb', line 45 def add_input(name, sample_name, container_name, opts = {}) add_field(name, sample_name, container_name, 'input', opts) end |
#add_io(name, sample_name, container_name, role, opts) ⇒ Object
41 42 43 |
# File 'app/models/operation_type.rb', line 41 def add_io(name, sample_name, container_name, role, opts) add_field(name, sample_name, container_name, role, opts) end |
#add_new_allowable_field_type(ft, new_type) ⇒ Object
Update Methods for Field Types from Front End Start Here
162 163 164 165 166 167 168 169 170 |
# File 'app/models/operation_type.rb', line 162 def add_new_allowable_field_type(ft, new_type) st = (SampleType.find_by(name: new_type[:sample_type][:name]) if new_type[:sample_type]) ot = (ObjectType.find_by(name: new_type[:object_type][:name]) if new_type[:object_type] && new_type[:object_type][:name] != '') ft.allowable_field_types.create( sample_type_id: st ? st.id : nil, object_type_id: ot ? ot.id : nil ) end |
#add_new_field_type(new_type) ⇒ Object
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'app/models/operation_type.rb', line 190 def add_new_field_type(new_type) sample_type_names = [] container_names = [] if new_type[:allowable_field_types] sample_type_names = new_type[:allowable_field_types].collect do |aft| aft[:sample_type] ? aft[:sample_type][:name] : nil end container_names = new_type[:allowable_field_types] .select { |aft| aft[:object_type] && aft[:object_type][:name] && aft[:object_type][:name] != '' } .collect do |aft| raise "Object type '#{aft[:object_type][:name]}' not defined by browser for #{ft[:name]}." unless ObjectType.find_by(name: aft[:object_type][:name]) aft[:object_type][:name] end else sample_type_names = new_type[:sample_types] if new_type[:sample_types] container_names = new_type[:object_types] if new_type[:object_types] end add_io( new_type[:name], sample_type_names, container_names, new_type[:role], array: new_type[:array], part: new_type[:part], routing: new_type[:routing], ftype: new_type[:ftype], choices: new_type[:choices] ) field_types.where(name: new_type[:name], role: new_type[:role])[0] end |
#add_output(name, sample_name, container_name, opts = {}) ⇒ Object
49 50 51 |
# File 'app/models/operation_type.rb', line 49 def add_output(name, sample_name, container_name, opts = {}) add_field(name, sample_name, container_name, 'output', opts) end |
#add_parameter(name:, type:, choices:) ⇒ Object
53 54 55 |
# File 'app/models/operation_type.rb', line 53 def add_parameter(name:, type:, choices:) add_field(name, nil, nil, 'input', ftype: type, choices: choices) end |
#add_precondition(content:, user:) ⇒ Object
134 135 136 137 138 139 140 |
# File 'app/models/operation_type.rb', line 134 def add_precondition(content:, user:) if precondition precondition.commit(content, user) else new_code('precondition', content, user) end end |
#add_protocol(content:, user:) ⇒ Object
104 105 106 107 108 109 110 |
# File 'app/models/operation_type.rb', line 104 def add_protocol(content:, user:) if protocol protocol.commit(content, user) else new_code('protocol', content, user) end end |
#add_test(content:, user:) ⇒ Object
150 151 152 153 154 155 156 |
# File 'app/models/operation_type.rb', line 150 def add_test(content:, user:) if test test.commit(content, user) else new_code('test', content, user) end end |
#category ⇒ String
Gets category of OperationType.
31 |
# File 'app/models/operation_type.rb', line 31 attr_accessible :category |
#cost_model ⇒ Object
118 119 120 |
# File 'app/models/operation_type.rb', line 118 def cost_model code('cost_model') end |
#documentation ⇒ Object
142 143 144 |
# File 'app/models/operation_type.rb', line 142 def documentation code('documentation') end |
#done ⇒ Object
96 97 98 |
# File 'app/models/operation_type.rb', line 96 def done operations.where(status: 'done') end |
#error_out_obsolete_operations ⇒ Object
290 291 292 293 294 295 296 297 298 299 |
# File 'app/models/operation_type.rb', line 290 def error_out_obsolete_operations Operation.where(operation_type_id: id, status: %w[pending scheduled]).each do |op| op.field_values.each do |fv| if !fv.field_type || !fv.allowable_field_type puts("ERRORING OUT OP #{op.id}") op.error(:obsolete, 'The operation type definition for this operation has changed too much since it was created.') end end end end |
#input(name) ⇒ Object
Returns the input of this OperationType with the given name.
68 69 70 |
# File 'app/models/operation_type.rb', line 68 def input(name) inputs.select { |field_type| field_type[:name] == name }.first end |
#inputs ⇒ Array<FieldType>
The input types of this OperationType.
61 62 63 |
# File 'app/models/operation_type.rb', line 61 def inputs field_types.select { |ft| ft.role == 'input' } end |
#name ⇒ String
Gets name of OperationType.
26 |
# File 'app/models/operation_type.rb', line 26 attr_accessible :name |
#output(name) ⇒ FieldType
Returns the output of this OperationType with the given name.
84 85 86 |
# File 'app/models/operation_type.rb', line 84 def output(name) outputs.select { |field_type| field_type[:name] == name }.first end |
#outputs ⇒ Array<FieldType>
The output types of this OperationType.
76 77 78 |
# File 'app/models/operation_type.rb', line 76 def outputs field_types.select { |ft| ft.role == 'output' } end |
#pending ⇒ Object
92 93 94 |
# File 'app/models/operation_type.rb', line 92 def pending operations.where(status: 'pending') end |
#precondition ⇒ Object
130 131 132 |
# File 'app/models/operation_type.rb', line 130 def precondition code('precondition') end |
#protocol ⇒ Object
100 101 102 |
# File 'app/models/operation_type.rb', line 100 def protocol code('protocol') end |
#stats ⇒ Object
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 |
# File 'app/models/operation_type.rb', line 301 def stats r = { 'done' => 0, 'error' => 0 } operations.each do |op| r[op.status] ||= 0 r[op.status] = r[op.status] + 1 end r['success'] = if r['done'] + r['error'] != 0 r['done'].to_f / (r['done'] + r['error']) else 0.0 end unless operations.empty? r['first_run'] = operations[0].updated_at r['last_run'] = operations.last.updated_at end r end |
#test ⇒ Object
146 147 148 |
# File 'app/models/operation_type.rb', line 146 def test code('test') end |
#update_allowable_field_type(old_aft, new_aft) ⇒ Object
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'app/models/operation_type.rb', line 172 def update_allowable_field_type(old_aft, new_aft) if new_aft[:sample_type] st = SampleType.find_by(name: new_aft[:sample_type][:name]) old_aft.sample_type_id = st.id if st else old_aft.sample_type_id = nil end if new_aft[:object_type] && new_aft[:object_type][:name] != '' ot = ObjectType.find_by(name: new_aft[:object_type][:name]) old_aft.object_type_id = ot.id if ot else old_aft.sample_type_id = nil end old_aft.save end |
#update_field_type(old_type:, new_type:) ⇒ Object
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
# File 'app/models/operation_type.rb', line 226 def update_field_type(old_type:, new_type:) keepers = [] old_type.name = new_type[:name] if old_type.sample? old_type.routing = new_type[:routing] old_type.array = new_type[:array] old_type.part = new_type[:part] old_type.preferred_operation_type_id = new_type[:preferred_operation_type_id] old_type.preferred_field_type_id = new_type[:preferred_field_type_id] puts "PREF(#{old_type.name}): #{new_type[:preferred_field_type_id]}" if new_type[:allowable_field_types] new_type[:allowable_field_types].each do |newaft| matching_types = old_type.allowable_field_types.select { |aft| aft.id == newaft[:id] } if matching_types.length == 1 oldaft = matching_types[0] keepers << oldaft update_allowable_field_type oldaft, newaft elsif matching_types.empty? keepers << add_new_allowable_field_type(old_type, newaft) else raise 'More than one allowable field type matched.' end end end else old_type.ftype = new_type[:ftype] old_type.choices = new_type[:choices] end old_type.save old_type.allowable_field_types.reject { |aft| keepers.include? aft }.each(&:destroy) unless keepers.empty? end |
#update_field_types(fts) ⇒ Object
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 |
# File 'app/models/operation_type.rb', line 264 def update_field_types(fts) keepers = [] if fts fts.each do |new_ft| matching_fts = field_types.select { |field_type| field_type.id == new_ft[:id] && field_type.role == new_ft[:role] } if matching_fts.length == 1 old_ft = matching_fts[0] keepers << old_ft update_field_type(old_type: old_ft, new_type: new_ft) elsif matching_fts.empty? keepers << add_new_field_type(new_ft) else raise "Multiple inputs (or outputs) named #{new_ft[:name]}" end end end field_types.reject { |ft| keepers.include? ft }.each do |ft| puts "DELETING FT #{ft.name}/#{ft.role}" ft.destroy end error_out_obsolete_operations end |
#waiting ⇒ Object
88 89 90 |
# File 'app/models/operation_type.rb', line 88 def waiting operations.where(status: 'waiting') end |