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
- #cost_model? ⇒ Boolean
- #create_operation(status:, user_id:, x: -1,, y: -1,, parent_id: -1)) ⇒ 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
- #precondition? ⇒ Boolean
- #protocol ⇒ Object
- #protocol? ⇒ Boolean
- #stats ⇒ Object
- #test ⇒ Object
- #test? ⇒ Boolean
- #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
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 |
# File 'app/models/operation_type.rb', line 343 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
130 131 132 133 134 135 136 |
# File 'app/models/operation_type.rb', line 130 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
49 50 51 |
# File 'app/models/operation_type.rb', line 49 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
45 46 47 |
# File 'app/models/operation_type.rb', line 45 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
182 183 184 185 186 187 188 189 190 |
# File 'app/models/operation_type.rb', line 182 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
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'app/models/operation_type.rb', line 210 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
53 54 55 |
# File 'app/models/operation_type.rb', line 53 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
57 58 59 |
# File 'app/models/operation_type.rb', line 57 def add_parameter(name:, type:, choices:) add_field(name, nil, nil, 'input', ftype: type, choices: choices) end |
#add_precondition(content:, user:) ⇒ Object
146 147 148 149 150 151 152 |
# File 'app/models/operation_type.rb', line 146 def add_precondition(content:, user:) if precondition precondition.commit(content, user) else new_code('precondition', content, user) end end |
#add_protocol(content:, user:) ⇒ Object
108 109 110 111 112 113 114 |
# File 'app/models/operation_type.rb', line 108 def add_protocol(content:, user:) if protocol protocol.commit(content, user) else new_code('protocol', content, user) end end |
#add_test(content:, user:) ⇒ Object
166 167 168 169 170 171 172 |
# File 'app/models/operation_type.rb', line 166 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
126 127 128 |
# File 'app/models/operation_type.rb', line 126 def cost_model code('cost_model') end |
#cost_model? ⇒ Boolean
138 139 140 |
# File 'app/models/operation_type.rb', line 138 def cost_model? !cost_model.nil? && cost_model.defined_methods.include?('cost') end |
#create_operation(status:, user_id:, x: -1,, y: -1,, parent_id: -1)) ⇒ Object
41 42 43 |
# File 'app/models/operation_type.rb', line 41 def create_operation(status:, user_id:, x: -1, y: -1, parent_id: -1) operations.create(status: status, user_id: user_id, x: x, y: y, parent_id: parent_id) end |
#documentation ⇒ Object
158 159 160 |
# File 'app/models/operation_type.rb', line 158 def documentation code('documentation') end |
#done ⇒ Object
100 101 102 |
# File 'app/models/operation_type.rb', line 100 def done operations.where(status: 'done') end |
#error_out_obsolete_operations ⇒ Object
310 311 312 313 314 315 316 317 318 319 |
# File 'app/models/operation_type.rb', line 310 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.
72 73 74 |
# File 'app/models/operation_type.rb', line 72 def input(name) inputs.select { |field_type| field_type[:name] == name }.first end |
#inputs ⇒ Array<FieldType>
The input types of this OperationType.
65 66 67 |
# File 'app/models/operation_type.rb', line 65 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.
88 89 90 |
# File 'app/models/operation_type.rb', line 88 def output(name) outputs.select { |field_type| field_type[:name] == name }.first end |
#outputs ⇒ Array<FieldType>
The output types of this OperationType.
80 81 82 |
# File 'app/models/operation_type.rb', line 80 def outputs field_types.select { |ft| ft.role == 'output' } end |
#pending ⇒ Object
96 97 98 |
# File 'app/models/operation_type.rb', line 96 def pending operations.where(status: 'pending') end |
#precondition ⇒ Object
142 143 144 |
# File 'app/models/operation_type.rb', line 142 def precondition code('precondition') end |
#precondition? ⇒ Boolean
154 155 156 |
# File 'app/models/operation_type.rb', line 154 def precondition? !precondition.nil? && precondition.defined_methods.include?('precondition') end |
#protocol ⇒ Object
104 105 106 |
# File 'app/models/operation_type.rb', line 104 def protocol code('protocol') end |
#protocol? ⇒ Boolean
116 117 118 |
# File 'app/models/operation_type.rb', line 116 def protocol? !protocol.nil? && protocol.defined_classes.include?('Protocol') end |
#stats ⇒ Object
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 |
# File 'app/models/operation_type.rb', line 321 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
162 163 164 |
# File 'app/models/operation_type.rb', line 162 def test code('test') end |
#test? ⇒ Boolean
174 175 176 |
# File 'app/models/operation_type.rb', line 174 def test? !test.nil? && test.defined_classes.include?('ProtocolTest') end |
#update_allowable_field_type(old_aft, new_aft) ⇒ Object
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
# File 'app/models/operation_type.rb', line 192 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
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
# File 'app/models/operation_type.rb', line 246 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
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 |
# File 'app/models/operation_type.rb', line 284 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
92 93 94 |
# File 'app/models/operation_type.rb', line 92 def waiting operations.where(status: 'waiting') end |