Class: Hobo::Model::Lifecycles::Lifecycle
- Inherits:
-
Object
- Object
- Hobo::Model::Lifecycles::Lifecycle
- Defined in:
- lib/hobo/model/lifecycles/lifecycle.rb
Class Attribute Summary collapse
-
.creators ⇒ Object
Returns the value of attribute creators.
-
.default_state ⇒ Object
Returns the value of attribute default_state.
-
.invariants ⇒ Object
Returns the value of attribute invariants.
-
.model ⇒ Object
Returns the value of attribute model.
-
.options ⇒ Object
Returns the value of attribute options.
-
.states ⇒ Object
Returns the value of attribute states.
-
.transitions ⇒ Object
Returns the value of attribute transitions.
Instance Attribute Summary collapse
-
#active_step ⇒ Object
Returns the value of attribute active_step.
-
#provided_key ⇒ Object
Returns the value of attribute provided_key.
-
#record ⇒ Object
readonly
— Instance Features — #.
Class Method Summary collapse
- .can_create?(name, user) ⇒ Boolean
- .create(name, user, attributes = nil) ⇒ Object
- .creator(name) ⇒ Object
- .def_creator(name, on_create, options) ⇒ Object
- .def_state(name, on_enter) ⇒ Object
- .def_transition(name, start_states, end_state, on_transition, options) ⇒ Object
- .init(model, options) ⇒ Object
- .key_timeout ⇒ Object
- .publishable_creators ⇒ Object
- .publishable_transitions ⇒ Object
- .reset ⇒ Object
- .state_field ⇒ Object
- .state_names ⇒ Object
- .step_names ⇒ Object
Instance Method Summary collapse
- #active_step_is?(name) ⇒ Boolean
- #available_transitions ⇒ Object
-
#available_transitions_for(user, name = nil) ⇒ Object
see also publishable_transitions_for.
- #become(state_name, validate = true) ⇒ Object
- #can_transition?(name, user) ⇒ Boolean
- #clear_key ⇒ Object
- #find_transition(name, user) ⇒ Object
- #generate_key ⇒ Object
-
#initialize(record) ⇒ Lifecycle
constructor
A new instance of Lifecycle.
- #invariants_satisfied? ⇒ Boolean
- #key ⇒ Object
- #key_expired? ⇒ Boolean
- #key_timeout ⇒ Object
- #key_timestamp_field ⇒ Object
- #method_missing(name, *args) ⇒ Object
- #publishable_transitions_for(user) ⇒ Object
- #state ⇒ Object
- #state_name ⇒ Object
- #transition(name, user, attributes) ⇒ Object
- #valid_key? ⇒ Boolean
Constructor Details
#initialize(record) ⇒ Lifecycle
Returns a new instance of Lifecycle.
105 106 107 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 105 def initialize(record) @record = record end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args) ⇒ Object
231 232 233 234 235 236 237 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 231 def method_missing(name, *args) if name.to_s =~ /^(.*)_in_progress\?$/ active_step_is?($1) else super end end |
Class Attribute Details
.creators ⇒ Object
Returns the value of attribute creators.
21 22 23 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 21 def creators @creators end |
.default_state ⇒ Object
Returns the value of attribute default_state.
21 22 23 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 21 def default_state @default_state end |
.invariants ⇒ Object
Returns the value of attribute invariants.
21 22 23 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 21 def invariants @invariants end |
.model ⇒ Object
Returns the value of attribute model.
21 22 23 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 21 def model @model end |
.options ⇒ Object
Returns the value of attribute options.
21 22 23 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 21 def end |
.states ⇒ Object
Returns the value of attribute states.
21 22 23 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 21 def states @states end |
.transitions ⇒ Object
Returns the value of attribute transitions.
21 22 23 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 21 def transitions @transitions end |
Instance Attribute Details
#active_step ⇒ Object
Returns the value of attribute active_step.
102 103 104 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 102 def active_step @active_step end |
#provided_key ⇒ Object
Returns the value of attribute provided_key.
102 103 104 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 102 def provided_key @provided_key end |
#record ⇒ Object (readonly)
— Instance Features — #
100 101 102 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 100 def record @record end |
Class Method Details
.can_create?(name, user) ⇒ Boolean
78 79 80 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 78 def self.can_create?(name, user) creators[name.to_sym].allowed?(user) end |
.create(name, user, attributes = nil) ⇒ Object
83 84 85 86 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 83 def self.create(name, user, attributes=nil) creator = creators[name.to_sym] or raise LifecycleError, "No creator #{name} available" creator.run!(user, attributes) end |
.creator(name) ⇒ Object
73 74 75 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 73 def self.creator(name) creators[name.to_sym] or raise ArgumentError, "No such creator in lifecycle: #{name}" end |
.def_creator(name, on_create, options) ⇒ Object
32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 32 def self.def_creator(name, on_create, ) class_eval %{ def self.#{name}(user, attributes=nil) create(:#{name}, user, attributes) end def self.can_#{name}?(user, attributes=nil) can_create?(:#{name}, user) end } Creator.new(self, name.to_s, on_create, ) end |
.def_state(name, on_enter) ⇒ Object
25 26 27 28 29 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 25 def self.def_state(name, on_enter) name = name.to_sym class_eval "def #{name}_state?; state_name == :#{name} end" states[name] = Lifecycles::State.new(name, on_enter) end |
.def_transition(name, start_states, end_state, on_transition, options) ⇒ Object
44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 44 def self.def_transition(name, start_states, end_state, on_transition, ) class_eval %{ def #{name}!(user, attributes=nil) transition(:#{name}, user, attributes) end def can_#{name}?(user, attributes=nil) can_transition?(:#{name}, user) end } Transition.new(self, name.to_s, start_states, end_state, on_transition, ) end |
.init(model, options) ⇒ Object
7 8 9 10 11 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 7 def self.init(model, ) @model = model = reset end |
.key_timeout ⇒ Object
93 94 95 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 93 def self.key_timeout [:key_timeout] end |
.publishable_creators ⇒ Object
60 61 62 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 60 def self.publishable_creators creators.values.where.publishable? end |
.publishable_transitions ⇒ Object
64 65 66 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 64 def self.publishable_transitions transitions.where.publishable? end |
.reset ⇒ Object
13 14 15 16 17 18 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 13 def self.reset @states = {} @creators = {} @transitions = [] @invariants = [] end |
.state_field ⇒ Object
89 90 91 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 89 def self.state_field [:state_field] end |
.state_names ⇒ Object
56 57 58 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 56 def self.state_names states.keys end |
.step_names ⇒ Object
68 69 70 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 68 def self.step_names (creators.keys | transitions.*.name).uniq end |
Instance Method Details
#active_step_is?(name) ⇒ Boolean
227 228 229 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 227 def active_step_is?(name) active_step && active_step.name == name.to_sym end |
#available_transitions ⇒ Object
137 138 139 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 137 def available_transitions state ? state.transitions_out : [] end |
#available_transitions_for(user, name = nil) ⇒ Object
see also publishable_transitions_for
142 143 144 145 146 147 148 149 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 142 def available_transitions_for(user, name=nil) name = name.to_sym if name matches = available_transitions matches = matches.select { |t| t.name == name } if name record.with_acting_user(user) do matches.select { |t| t.can_run?(record) } end end |
#become(state_name, validate = true) ⇒ Object
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 160 def become(state_name, validate=true) state_name = state_name.to_sym record.send :write_attribute, self.class.state_field, state_name.to_s if state_name == :destroy record.destroy true else s = self.class.states[state_name] raise ArgumentError, "No such state '#{state_name}' for #{record.class.name}" unless s if record.save(:validate => validate) s.activate! record self.active_step = nil # That's the end of this step true else false end end end |
#can_transition?(name, user) ⇒ Boolean
110 111 112 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 110 def can_transition?(name, user) available_transitions_for(user, name).any? end |
#clear_key ⇒ Object
218 219 220 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 218 def clear_key record.send :write_attribute, , nil end |
#find_transition(name, user) ⇒ Object
121 122 123 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 121 def find_transition(name, user) available_transitions_for(user, name).first end |
#generate_key ⇒ Object
190 191 192 193 194 195 196 197 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 190 def generate_key if Time.zone.nil? raise RuntimeError, "Cannot generate lifecycle key timestamp if the time-zone is not configured. Please add, e.g. config.time_zone = 'UTC' to environment.rb" end = Time.now.utc record.send :write_attribute, , key end |
#invariants_satisfied? ⇒ Boolean
222 223 224 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 222 def invariants_satisfied? self.class.invariants.all? { |i| record.instance_eval(&i) } end |
#key ⇒ Object
200 201 202 203 204 205 206 207 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 200 def key require 'digest/sha1' = record.read_attribute() if = .getutc Digest::SHA1.hexdigest("#{record.id}-#{state_name}-#{timestamp}-#{Rails.application.config.secret_token}") end end |
#key_expired? ⇒ Boolean
209 210 211 212 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 209 def key_expired? = record.read_attribute() .nil? || (.getutc + key_timeout < Time.now.utc) end |
#key_timeout ⇒ Object
186 187 188 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 186 def key_timeout record.class::Lifecycle.[:key_timeout] end |
#key_timestamp_field ⇒ Object
182 183 184 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 182 def record.class::Lifecycle.[:key_timestamp_field] end |
#publishable_transitions_for(user) ⇒ Object
151 152 153 154 155 156 157 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 151 def publishable_transitions_for(user) record.with_acting_user(user) do available_transitions_for(user).select do |t| t.publishable_by(user, t.available_to, record) end end end |
#state ⇒ Object
132 133 134 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 132 def state self.class.states[state_name] end |
#state_name ⇒ Object
126 127 128 129 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 126 def state_name name = record.read_attribute(self.class.state_field) name.to_sym if name end |
#transition(name, user, attributes) ⇒ Object
115 116 117 118 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 115 def transition(name, user, attributes) transition = find_transition(name, user) or raise LifecycleError, "No transition #{name} available" transition.run!(record, user, attributes) end |
#valid_key? ⇒ Boolean
214 215 216 |
# File 'lib/hobo/model/lifecycles/lifecycle.rb', line 214 def valid_key? provided_key && provided_key == key && !key_expired? end |