state_machinable 2.0.0 → 3.0.0.pre.rc0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 14cbdf576bdb9760f0da81d5b53accb8c73a048e
4
- data.tar.gz: fca5149485432751a7ecd18c4f21ab1ccf633f69
3
+ metadata.gz: 41405511bd178326737846d59454cefb6727cf71
4
+ data.tar.gz: d5d40aadb0a86ec6a1120a1ddf398c1c2a1fbfa7
5
5
  SHA512:
6
- metadata.gz: 016b0c5f2b755cc4e89328b118e7b01152b6b83d5330bdb8474166a2c8e20587359bab329a2f7de23d17608f2a86006cf3d77af52947654642ced2afbc895bbc
7
- data.tar.gz: a0df1e3bac12a44e72d3d7d3b1bad100b66936d9013202b3f3a3defce63a10ee083467b09c6e717c4176b8ac00ad604570aa75a788efc678259b41638d2ff792
6
+ metadata.gz: a88628febd7d3ed64216b5fc864ebca770ca1576e728d09c95d038865ba8174c294a533f214c5b41afcae86059ddf5edc1ef611d295c9e0c41981773d047df87
7
+ data.tar.gz: 5fdba8bc745a51f3c12db9b05142c323a97dd2fb433d066d18a4180751d36c76a216bad4c0c5c666bc9e82bd4b22f32024685831407ca7f5d11fb6437bce4df3
data/README.md CHANGED
@@ -4,10 +4,11 @@ Adds state machine functionality to `statesman`
4
4
 
5
5
  ## Installation
6
6
 
7
- Add this line to your application's Gemfile:
7
+ Add these lines to your application's Gemfile:
8
8
 
9
9
  ```ruby
10
10
  gem 'state_machinable'
11
+ gem 'statesman'
11
12
  ```
12
13
 
13
14
  And then execute:
@@ -16,11 +17,129 @@ And then execute:
16
17
 
17
18
  Or install it yourself as:
18
19
 
20
+ $ gem install statesman
19
21
  $ gem install state_machinable
20
22
 
23
+ ## Setup
24
+
25
+ Generate the transitions for a model, e.g. `Order`
26
+
27
+ $ rails g migration CreateOrderTransitions
28
+
29
+ The migration will look very similar to if you had generated it with Statesman, but with a `current_state` added
30
+
31
+ `rails g statesman:active_record_transition Order OrderTransition`
32
+
33
+ ```ruby
34
+ class CreateOrderTransitions < ActiveRecord::Migration
35
+ def change
36
+ add_column :orders, :current_state, :string # <- ADD THIS LINE
37
+ create_table :order_transitions do |t|
38
+ t.string :to_state, null: false
39
+ t.text :metadata
40
+ t.integer :sort_key, null: false
41
+ t.integer :order_id, null: false
42
+ t.boolean :most_recent
43
+ t.timestamps null: false
44
+ end
45
+
46
+ add_index(:order_transitions, [:order_id, :sort_key], unique: true, name: "index_order_transitions_parent_sort")
47
+ add_index(:order_transitions, [:order_id, :most_recent], unique: true, name: "index_order_transitions_parent_most_recent")
48
+ end
49
+ end
50
+ ```
51
+
52
+ In your model, include this library and transitions:
53
+
54
+ ```ruby
55
+ class Order < ActiveRecord::Base
56
+ include StateMachinable::Model
57
+ has_many :order_transitions, :dependent => :destroy
58
+ ```
59
+
60
+ Then set up your state transitions:
61
+ ```ruby
62
+ # app/state_machines/order_state_machine.rb
63
+
64
+ class OrderStateMachine
65
+ include StateMachinable::Base
66
+
67
+ # define your states
68
+ state :open
69
+ state :processing
70
+ state :shipped
71
+ state :delivered
72
+ state :cancelled
73
+
74
+ # define transitions
75
+ transition :from => :initial, :to => :open
76
+ transition :from => :open, :to => [:processing, :cancelled]
77
+ transition :from => :processing, :to => [:shipped, :cancelled]
78
+ transition :from => :shipped, :to => [:delivered]
79
+
80
+ # define events that may occur
81
+ EVENTS = [
82
+ :event_processing,
83
+ :event_shipped,
84
+ :event_cancelled,
85
+ :event_delivered
86
+ ].freeze
87
+
88
+ # define a class for each state, with methods for event that may occur within that state
89
+ class Open
90
+ def self.event_processing(order)
91
+ order.transition_to!(:processing)
92
+ # TODO: send order confirmation email to customer
93
+ end
94
+ def self.event_cancelled(order)
95
+ order.transition_to!(:cancelled)
96
+ # ...
97
+ end
98
+ end
99
+
100
+ class Shipped
101
+ def self.event_delivered(order)
102
+ order.transition_to!(:delivered)
103
+ # ...
104
+ end
105
+ end
106
+ end
107
+
108
+ ```
109
+
110
+ There are also hooks for the state changes that could be used instead of duplicating logic in multiple events that transition to the same state
111
+
112
+ ```ruby
113
+ class Cancelled
114
+ def self.enter(order)
115
+ # TODO: send email to customer that order is cancelled
116
+ end
117
+ end
118
+
119
+ ```
120
+
21
121
  ## Usage
122
+ When you want to transition from one state to another, call an event:
123
+
124
+ ```ruby
125
+ order.state_machine.event_shipped
126
+ ```
22
127
 
23
- TODO
128
+ You may want to use a transaction around the event to ensure that both the current_state and transitions are committed, or to prevent invalid states
129
+
130
+ ```ruby
131
+ ActiveRecord::Base.transaction do
132
+ # without a transaction here then an invoice could be created without the order's state succeeding in transitioning to shipped
133
+ Order.create_invoice_for_order!(order)
134
+ order.state_machine.event_shipped
135
+ end
136
+ ```
137
+
138
+ You can check the model's state with `#current_state`
139
+
140
+ ```ruby
141
+ order.current_state
142
+ ```
24
143
 
25
144
  ## Development
26
145
 
@@ -38,7 +38,6 @@ module StateMachinable
38
38
  events = []
39
39
  end
40
40
 
41
- events.concat([:ev_before_save, :ev_after_save]).uniq
42
41
  clean_name = name.to_s.chomp('!').to_sym
43
42
 
44
43
  if events.include?(clean_name)
@@ -13,8 +13,6 @@ module StateMachinable
13
13
  end
14
14
 
15
15
  included do
16
- before_save :send_ev_before_save, :if => Proc.new { |obj| obj.changed? }
17
- after_save :send_ev_after_save, :if => Proc.new { |obj| !obj.id_changed? && obj.changed? }
18
16
  after_save :transition_to_initial_state, :if => Proc.new { |obj| obj.id_changed? }
19
17
  delegate :can_transition_to?, :transition_to!, :transition_to, :to => :state_machine
20
18
 
@@ -22,14 +20,6 @@ module StateMachinable
22
20
  @state_machine ||= self.class.state_machine_class.new(self, :transition_class => self.class.transition_class)
23
21
  end
24
22
 
25
- def send_ev_before_save
26
- self.state_machine.send('ev_before_save')
27
- end
28
-
29
- def send_ev_after_save
30
- self.state_machine.send('ev_after_save')
31
- end
32
-
33
23
  private def transition_to_initial_state
34
24
  initial_state = self.state_machine.class.successors['initial'].first
35
25
  if (!self.respond_to?(:skip_state_machine?) || !self.skip_state_machine?) && (self.current_state != initial_state)
@@ -1,3 +1,3 @@
1
1
  module StateMachinable
2
- VERSION = "2.0.0"
2
+ VERSION = "3.0.0-rc0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: state_machinable
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 3.0.0.pre.rc0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Santiago Herrera
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-07-18 00:00:00.000000000 Z
11
+ date: 2018-02-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -125,9 +125,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
125
125
  version: '0'
126
126
  required_rubygems_version: !ruby/object:Gem::Requirement
127
127
  requirements:
128
- - - ">="
128
+ - - ">"
129
129
  - !ruby/object:Gem::Version
130
- version: '0'
130
+ version: 1.3.1
131
131
  requirements: []
132
132
  rubyforge_project:
133
133
  rubygems_version: 2.6.8