Module: SuperState::ClassMethods

Defined in:
lib/super_state.rb

Instance Method Summary collapse

Instance Method Details

#define_state_methods(method_name, state_names = nil) ⇒ Object



213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/super_state.rb', line 213

def define_state_methods(method_name, state_names=nil)
  state_names ||= method_name
  
  # Loan.completed # scope
  self.scope method_name, self.scope_by_super_state(state_names)
  
  # pretty much;
  #   def record.completed?
  #     record.status == "completed"
  #   end
  define_method("#{method_name}?") do
    StateArray.new(state_names).include?(self.current_super_state)
  end
end

#define_state_transition_method(method_name, state_hash, save_method, &transition_block) ⇒ Object



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
# File 'lib/super_state.rb', line 228

def define_state_transition_method(method_name, state_hash, save_method, &transition_block)
  
  # pretty much;
  #   def record.complete!
  #     if record.pending?
  #       record.status = "completed"
  #       record.save!
  #     else
  #       raise SuperState::BadState
  #     end
  #   end
  define_method(method_name) do |*args|
    if to_state = state_hash[self.current_super_state]

      state_before = self.current_super_state
      self.set_super_state(to_state)

      if transition_block
        params = args.shift || {}
        self.instance_exec(params, &transition_block)
      end

      unless rtn = self.send(save_method)
        self.set_super_state(state_before, false) #roll it back on failure
      end
      rtn
    else
      raise SuperState::BadState, "#{method_name} can only be called from states #{state_hash.keys.inspect}"
    end
  end
  
end

#in_state(state_name) ⇒ Object

a wrapper around state based scopes to avoid malicious arguments;

Loan.in_state(:disbursed) => Loan.disbursed
Loan.in_state("active")   => Loan.active
Loan.in_state("all")      => Loan.scoped
Loan.in_state("")         => Loan.scoped
Loan.in_state("something_evil") => Exception!


159
160
161
162
163
164
165
# File 'lib/super_state.rb', line 159

def in_state(state_name)
  if state_array = self.super_states(state_name)
    self.scope_by_super_state(state_array)
  else
    raise BadState, "you are trying to scope by something other than a super state (or super state group)"
  end
end

#scope_by_super_state(state_names) ⇒ Object



185
186
187
188
189
190
191
# File 'lib/super_state.rb', line 185

def scope_by_super_state(state_names)
  if state_names.is_a?(StateArray) && state_names.all_states?
    self.scoped
  else
    self.where(self.super_state_column => SuperState.canonicalise(state_names))
  end
end

#state_transition(transition_name, state_hash, &transition_block) ⇒ Object

state_transition :complete, :processing => :completed



200
201
202
203
204
205
# File 'lib/super_state.rb', line 200

def state_transition(transition_name, state_hash, &transition_block)
  state_hash = state_hash.stringify_keys
  
  define_state_transition_method(transition_name,       state_hash, :save,  &transition_block)
  define_state_transition_method("#{transition_name}!", state_hash, :save!, &transition_block)
end

#super_state(state_name, options = {}) ⇒ Object



144
145
146
147
148
149
150
# File 'lib/super_state.rb', line 144

def super_state(state_name, options={})
  if options[:initial] || self.initial_super_state.nil?
    self.initial_super_state = state_name
  end
  define_state_methods(state_name)
  self.__super_states << state_name
end

#super_state_columnObject

internal methods



209
210
211
# File 'lib/super_state.rb', line 209

def super_state_column
  :status
end

#super_state_group(group_name, group_states) ⇒ Object

super_state_group(:active, [:approved, :requested, :disbursed])



194
195
196
197
# File 'lib/super_state.rb', line 194

def super_state_group(group_name, group_states)
  define_state_methods(group_name, group_states)
  self.super_state_groups[group_name] = group_states
end

#super_states(state_name = nil) ⇒ Object

self.super_states => [“first”, “second”, “third”] self.super_states(“”) => [“first”, “second”, “third”] self.super_states(“all”) => [“first”, “second”, “third”]

self.super_states(“first”) => [“first”]

self.super_states(“final”) => [“second”, “third”]



175
176
177
178
179
180
181
182
183
# File 'lib/super_state.rb', line 175

def super_states(state_name=nil)
  if state_name.blank? || state_name == "all"
    self.__super_states
  elsif self.__super_states.include?(state_name)
    StateArray.new(state_name)
  elsif self.super_state_groups.include?(state_name)
    self.super_state_groups[state_name]
  end
end

#super_states_for_select(options = {}) ⇒ Object



131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/super_state.rb', line 131

def super_states_for_select(options={})
  rtn = []
  if options[:include_all]
    rtn << ["<All>", "all"]
  end
  if options[:include_groups]
    rtn += self.super_state_groups.keys.for_select
  end
  rtn += self.super_states.for_select
  
  rtn
end