Module: Statize

Includes:
TR::CondUtils, TeLogger::TeLogHelper
Defined in:
lib/statize.rb,
lib/statize/version.rb

Defined Under Namespace

Modules: ClassMethods Classes: DuplicatedKey, Error, InvalidEvent, InvalidState, InvalidStateForEvent, UserHalt

Constant Summary collapse

VERSION =
"0.1.0"

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(klass) ⇒ Object



190
191
192
# File 'lib/statize.rb', line 190

def self.included(klass)
  klass.extend(ClassMethods)
end

Instance Method Details

#activate_state_profile(prof) ⇒ Object



205
206
207
208
# File 'lib/statize.rb', line 205

def activate_state_profile(prof)
  prof = prof.to_sym if not prof.nil?
  set_active_state_profile(prof)
end

#all_statesObject



223
224
225
# File 'lib/statize.rb', line 223

def all_states
  self.class.profile_states_list(active_state_profile).map { |s| s.to_s }
end

#apply_state(st) ⇒ Object



227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
# File 'lib/statize.rb', line 227

def apply_state(st)
  
  case st
  when Symbol
    sst = st
  else
    sst = st.to_sym
  end

  if next_states.include?(sst.to_s)
    update_state(sst)
    true
  else
    false
  end
end

#apply_state!(st) ⇒ Object

Raises:



243
244
245
246
# File 'lib/statize.rb', line 243

def apply_state!(st)
  res = apply_state(st)
  raise InvalidState, "Given new state '#{st}' is not valid" if not res
end

#at_initial_state?Boolean

Returns:

  • (Boolean)


210
211
212
# File 'lib/statize.rb', line 210

def at_initial_state?
  current_state == self.class.initial_state(active_state_profile)
end

#current_stateObject



293
294
295
296
297
298
299
# File 'lib/statize.rb', line 293

def current_state
  if has_rattr?(self.class.state_attr_name(active_state_profile))
    self.send("#{self.class.state_attr_name(active_state_profile)}")
  else
    nil
  end
end

#current_state_meaningObject



305
306
307
308
309
310
311
312
313
314
# File 'lib/statize.rb', line 305

def current_state_meaning
  cst = current_state
  smt = self.class.state_meaning_table(active_state_profile)
  meaning = smt[cst.to_sym]
  if meaning.nil?
    :not_defined
  else
    meaning
  end
end

#init_state(prof = :default) ⇒ Object

instance methods



199
200
201
202
203
# File 'lib/statize.rb', line 199

def init_state(prof = :default)
  prof = prof.to_sym if not prof.nil?
  set_active_state_profile(prof)
  update_state(self.class.initial_state(prof))
end

#next_eventsObject



249
250
251
252
253
254
255
256
# File 'lib/statize.rb', line 249

def next_events
  se = self.class.state_events_table(active_state_profile)
  cst = current_state
  res = se[cst.to_sym]
  # res == nil will happened if it is at the end of the event chain
  res = [] if res.nil? 
  res
end

#next_statesObject



214
215
216
217
218
219
220
221
# File 'lib/statize.rb', line 214

def next_states
  st = current_state
  if not_empty?(st)
    self.class.states_table(active_state_profile)[st.to_sym].map { |e| e.to_s }
  else
    []
  end
end

#state_profilesObject



301
302
303
# File 'lib/statize.rb', line 301

def state_profiles
  self.class.state_profiles
end

#states_of_meaning(meaning) ⇒ Object



316
317
318
319
320
321
322
323
# File 'lib/statize.rb', line 316

def states_of_meaning(meaning)
  res = self.class.meaning_states_table(active_state_profile)[meaning]
  if not res.nil?
    res
  else
    []
  end
end

#trigger_event(evt, &block) ⇒ Object



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
283
284
285
286
287
288
289
290
291
# File 'lib/statize.rb', line 258

def trigger_event(evt, &block)
  evt = evt.to_sym if not evt.nil?
  cst = current_state
  if not_empty?(cst)
    cst = cst.to_sym
    tbl = self.class.event_states_table(active_state_profile)[evt]

    raise InvalidEvent, "Event '#{evt}' not registered under profile '#{active_state_profile}'" if tbl.nil?

    # current state not tie to from state of this event
    raise InvalidStateForEvent, "Current state '#{cst}' is not register to event '#{evt}'" if not tbl.keys.include?(cst)
    
    destSt = tbl[cst]
    raise InvalidStateForEvent, "New state transition from current state '#{cst}' due to event '#{evt}' is empty" if is_empty?(destSt)

    evtBlock = self.class.event_block_table(active_state_profile)[evt]
    update = true

    update = evtBlock.call(action: :before, profile: active_state_profile, event: evt, from_state: cst, to_state: destSt, target: self) if not evtBlock.nil?
    update = true if is_empty?(update) or not_bool?(update)

    if update
      apply_state(destSt)
      evtBlock.call(action: :after, profile: active_state_profile, event: evt, from_state: cst, to_state: destSt, target: self) if not evtBlock.nil?
      block.call(action: :after, profile: active_state_profile, event: evt, from_state: cst, to_state: destSt, target: self) if block
    else
      teLogger.error "Event '#{evt}' triggered but block returned false. Status not updated to '#{destSt}'"
      raise UserHalt,"Event '#{evt}' triggered but block returned false. Status not updated to '#{destSt}'"
    end

  else
    # current state is empty!
  end
end