aasm 5.0.2 → 5.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +27 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.travis.yml +42 -11
- data/Appraisals +17 -2
- data/CHANGELOG.md +33 -0
- data/Dockerfile +1 -6
- data/README.md +118 -99
- data/aasm.gemspec +3 -0
- data/gemfiles/norails.gemfile +10 -0
- data/gemfiles/rails_5.0.gemfile +1 -1
- data/gemfiles/rails_5.1.gemfile +1 -1
- data/gemfiles/rails_5.2.gemfile +13 -0
- data/lib/aasm/aasm.rb +29 -27
- data/lib/aasm/base.rb +25 -7
- data/lib/aasm/core/event.rb +3 -3
- data/lib/aasm/instance_base.rb +15 -3
- data/lib/aasm/persistence/active_record_persistence.rb +10 -1
- data/lib/aasm/persistence/base.rb +1 -1
- data/lib/aasm/persistence/core_data_query_persistence.rb +2 -1
- data/lib/aasm/persistence/dynamoid_persistence.rb +1 -1
- data/lib/aasm/persistence/mongoid_persistence.rb +1 -1
- data/lib/aasm/persistence/no_brainer_persistence.rb +1 -1
- data/lib/aasm/persistence/orm.rb +23 -19
- data/lib/aasm/persistence/redis_persistence.rb +1 -1
- data/lib/aasm/rspec/transition_from.rb +5 -1
- data/lib/aasm/version.rb +1 -1
- data/spec/database.rb +8 -0
- data/spec/models/active_record/instance_level_skip_validation_example.rb +19 -0
- data/spec/models/active_record/person.rb +23 -0
- data/spec/models/callbacks/with_state_arg.rb +5 -1
- data/spec/models/callbacks/with_state_arg_multiple.rb +4 -1
- data/spec/models/simple_example.rb +6 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/unit/abstract_class_spec.rb +27 -0
- data/spec/unit/callback_multiple_spec.rb +4 -0
- data/spec/unit/callbacks_spec.rb +4 -0
- data/spec/unit/complex_example_spec.rb +0 -1
- data/spec/unit/event_spec.rb +13 -0
- data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +4 -4
- data/spec/unit/persistence/active_record_persistence_spec.rb +58 -4
- data/spec/unit/rspec_matcher_spec.rb +3 -0
- data/spec/unit/simple_example_spec.rb +15 -0
- metadata +54 -2
data/aasm.gemspec
CHANGED
@@ -17,12 +17,15 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.required_ruby_version = '>= 1.9.3'
|
18
18
|
|
19
19
|
s.add_dependency 'concurrent-ruby', '~> 1.0'
|
20
|
+
s.add_dependency 'after_commit_action', '~> 1.0'
|
20
21
|
|
21
22
|
s.add_development_dependency 'rake'
|
22
23
|
s.add_development_dependency 'sdoc'
|
23
24
|
s.add_development_dependency 'rspec', ">= 3"
|
24
25
|
s.add_development_dependency 'generator_spec'
|
25
26
|
s.add_development_dependency 'appraisal'
|
27
|
+
s.add_development_dependency "simplecov"
|
28
|
+
s.add_development_dependency "codecov", ">= 0.1.10"
|
26
29
|
|
27
30
|
# debugging
|
28
31
|
# s.add_development_dependency 'debugger'
|
data/gemfiles/rails_5.0.gemfile
CHANGED
data/gemfiles/rails_5.1.gemfile
CHANGED
@@ -0,0 +1,13 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "sqlite3", "~> 1.3.5", platforms: :ruby
|
6
|
+
gem "rails", "5.2"
|
7
|
+
gem "mongoid", "~>6.0"
|
8
|
+
gem "sequel"
|
9
|
+
gem "dynamoid", "~>2.2", platforms: :ruby
|
10
|
+
gem "aws-sdk", "~>2", platforms: :ruby
|
11
|
+
gem "redis-objects"
|
12
|
+
|
13
|
+
gemspec path: "../"
|
data/lib/aasm/aasm.rb
CHANGED
@@ -99,25 +99,10 @@ private
|
|
99
99
|
begin
|
100
100
|
old_state = aasm(state_machine_name).state_object_for_name(aasm(state_machine_name).current_state)
|
101
101
|
|
102
|
-
event.
|
103
|
-
:before_all_events,
|
104
|
-
self,
|
105
|
-
*process_args(event, aasm(state_machine_name).current_state, *args)
|
106
|
-
)
|
107
|
-
|
108
|
-
# new event before callback
|
109
|
-
event.fire_callbacks(
|
110
|
-
:before,
|
111
|
-
self,
|
112
|
-
*process_args(event, aasm(state_machine_name).current_state, *args)
|
113
|
-
)
|
102
|
+
fire_default_callbacks(event, *process_args(event, aasm(state_machine_name).current_state, *args))
|
114
103
|
|
115
104
|
if may_fire_to = event.may_fire?(self, *args)
|
116
|
-
old_state
|
117
|
-
*process_args(event, aasm(state_machine_name).current_state, *args))
|
118
|
-
old_state.fire_callbacks(:exit, self,
|
119
|
-
*process_args(event, aasm(state_machine_name).current_state, *args))
|
120
|
-
|
105
|
+
fire_exit_callbacks(old_state, *process_args(event, aasm(state_machine_name).current_state, *args))
|
121
106
|
if new_state_name = event.fire(self, {:may_fire => may_fire_to}, *args)
|
122
107
|
aasm_fired(state_machine_name, event, old_state, new_state_name, options, *args, &block)
|
123
108
|
else
|
@@ -137,25 +122,44 @@ private
|
|
137
122
|
end
|
138
123
|
end
|
139
124
|
|
125
|
+
def fire_default_callbacks(event, *processed_args)
|
126
|
+
event.fire_global_callbacks(
|
127
|
+
:before_all_events,
|
128
|
+
self,
|
129
|
+
*processed_args
|
130
|
+
)
|
131
|
+
|
132
|
+
# new event before callback
|
133
|
+
event.fire_callbacks(
|
134
|
+
:before,
|
135
|
+
self,
|
136
|
+
*processed_args
|
137
|
+
)
|
138
|
+
end
|
139
|
+
|
140
|
+
def fire_exit_callbacks(old_state, *processed_args)
|
141
|
+
old_state.fire_callbacks(:before_exit, self, *processed_args)
|
142
|
+
old_state.fire_callbacks(:exit, self, *processed_args)
|
143
|
+
end
|
144
|
+
|
140
145
|
def aasm_fired(state_machine_name, event, old_state, new_state_name, options, *args)
|
141
146
|
persist = options[:persist]
|
142
147
|
|
143
148
|
new_state = aasm(state_machine_name).state_object_for_name(new_state_name)
|
149
|
+
callback_args = process_args(event, aasm(state_machine_name).current_state, *args)
|
144
150
|
|
145
|
-
new_state.fire_callbacks(:before_enter, self,
|
146
|
-
*process_args(event, aasm(state_machine_name).current_state, *args))
|
151
|
+
new_state.fire_callbacks(:before_enter, self, *callback_args)
|
147
152
|
|
148
|
-
new_state.fire_callbacks(:enter, self,
|
149
|
-
*process_args(event, aasm(state_machine_name).current_state, *args)) # TODO: remove for AASM 4?
|
153
|
+
new_state.fire_callbacks(:enter, self, *callback_args) # TODO: remove for AASM 4?
|
150
154
|
|
151
155
|
persist_successful = true
|
152
156
|
if persist
|
153
157
|
persist_successful = aasm(state_machine_name).set_current_state_with_persistence(new_state_name)
|
154
158
|
if persist_successful
|
155
159
|
yield if block_given?
|
156
|
-
event.fire_callbacks(:before_success, self)
|
160
|
+
event.fire_callbacks(:before_success, self, *callback_args)
|
157
161
|
event.fire_transition_callbacks(self, *process_args(event, old_state.name, *args))
|
158
|
-
event.fire_callbacks(:success, self)
|
162
|
+
event.fire_callbacks(:success, self, *callback_args)
|
159
163
|
end
|
160
164
|
else
|
161
165
|
aasm(state_machine_name).current_state = new_state_name
|
@@ -168,10 +172,8 @@ private
|
|
168
172
|
end
|
169
173
|
|
170
174
|
if persist_successful
|
171
|
-
old_state.fire_callbacks(:after_exit, self,
|
172
|
-
|
173
|
-
new_state.fire_callbacks(:after_enter, self,
|
174
|
-
*process_args(event, aasm(state_machine_name).current_state, *args))
|
175
|
+
old_state.fire_callbacks(:after_exit, self, *callback_args)
|
176
|
+
new_state.fire_callbacks(:after_enter, self, *callback_args)
|
175
177
|
event.fire_callbacks(
|
176
178
|
:after,
|
177
179
|
self,
|
data/lib/aasm/base.rb
CHANGED
@@ -54,13 +54,14 @@ module AASM
|
|
54
54
|
# make sure to raise an error if no_direct_assignment is enabled
|
55
55
|
# and attribute is directly assigned though
|
56
56
|
aasm_name = @name
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
57
|
+
|
58
|
+
if @state_machine.config.no_direct_assignment
|
59
|
+
@klass.send(:define_method, "#{@state_machine.config.column}=") do |state_name|
|
60
|
+
if self.class.aasm(:"#{aasm_name}").state_machine.config.no_direct_assignment
|
61
|
+
raise AASM::NoDirectAssignmentError.new('direct assignment of AASM column has been disabled (see AASM configuration for this class)')
|
62
|
+
else
|
63
|
+
super(state_name)
|
64
|
+
end
|
64
65
|
end
|
65
66
|
end
|
66
67
|
end
|
@@ -134,6 +135,8 @@ module AASM
|
|
134
135
|
aasm_fire_event(aasm_name, event, {:persist => false}, *args, &block)
|
135
136
|
end
|
136
137
|
|
138
|
+
skip_instance_level_validation(event, name, aasm_name, klass)
|
139
|
+
|
137
140
|
# Create aliases for the event methods. Keep the old names to maintain backwards compatibility.
|
138
141
|
if namespace?
|
139
142
|
klass.send(:alias_method, "may_#{name}_#{namespace}?", "may_#{name}?")
|
@@ -249,5 +252,20 @@ module AASM
|
|
249
252
|
end
|
250
253
|
end
|
251
254
|
|
255
|
+
def skip_instance_level_validation(event, name, aasm_name, klass)
|
256
|
+
# Overrides the skip_validation config for an instance (If skip validation is set to false in original config) and
|
257
|
+
# restores it back to the original value after the event is fired.
|
258
|
+
safely_define_method klass, "#{name}_without_validation!", ->(*args, &block) do
|
259
|
+
original_config = AASM::StateMachineStore.fetch(self.class, true).machine(aasm_name).config.skip_validation_on_save
|
260
|
+
begin
|
261
|
+
AASM::StateMachineStore.fetch(self.class, true).machine(aasm_name).config.skip_validation_on_save = true unless original_config
|
262
|
+
aasm(aasm_name).current_event = :"#{name}!"
|
263
|
+
aasm_fire_event(aasm_name, event, {:persist => true}, *args, &block)
|
264
|
+
ensure
|
265
|
+
AASM::StateMachineStore.fetch(self.class, true).machine(aasm_name).config.skip_validation_on_save = original_config
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
252
270
|
end
|
253
271
|
end
|
data/lib/aasm/core/event.rb
CHANGED
@@ -131,13 +131,13 @@ module AASM::Core
|
|
131
131
|
|
132
132
|
if to_state == ::AASM::NO_VALUE
|
133
133
|
to_state = nil
|
134
|
-
elsif to_state.respond_to?(:to_sym) && transitions.map(&:to).flatten.include?(to_state.to_sym)
|
135
|
-
# nop, to_state is a valid to-state
|
136
|
-
else
|
134
|
+
elsif !(to_state.respond_to?(:to_sym) && transitions.map(&:to).flatten.include?(to_state.to_sym))
|
137
135
|
# to_state is an argument
|
138
136
|
args.unshift(to_state)
|
139
137
|
to_state = nil
|
140
138
|
end
|
139
|
+
|
140
|
+
# nop, to_state is a valid to-state
|
141
141
|
|
142
142
|
transitions.each do |transition|
|
143
143
|
next if to_state and !Array(transition.to).include?(to_state)
|
data/lib/aasm/instance_base.rb
CHANGED
@@ -78,6 +78,17 @@ module AASM
|
|
78
78
|
events
|
79
79
|
end
|
80
80
|
|
81
|
+
def permitted_transitions
|
82
|
+
events(permitted: true).flat_map do |event|
|
83
|
+
available_transitions = event.transitions_from_state(current_state)
|
84
|
+
allowed_transitions = available_transitions.select { |t| t.allowed?(@instance) }
|
85
|
+
|
86
|
+
allowed_transitions.map do |transition|
|
87
|
+
{ event: event.name, state: transition.to }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
81
92
|
def state_object_for_name(name)
|
82
93
|
obj = @instance.class.aasm(@name).states.find {|s| s.name == name}
|
83
94
|
raise AASM::UndefinedState, "State :#{name} doesn't exist" if obj.nil?
|
@@ -91,7 +102,7 @@ module AASM
|
|
91
102
|
when Proc
|
92
103
|
state.call(@instance)
|
93
104
|
else
|
94
|
-
raise NotImplementedError, "Unrecognized state-type given.
|
105
|
+
raise NotImplementedError, "Unrecognized state-type given. Expected Symbol, String, or Proc."
|
95
106
|
end
|
96
107
|
end
|
97
108
|
|
@@ -104,11 +115,12 @@ module AASM
|
|
104
115
|
end
|
105
116
|
|
106
117
|
def fire(event_name, *args, &block)
|
107
|
-
@instance.send(
|
118
|
+
@instance.send(event_name, *args, &block)
|
108
119
|
end
|
109
120
|
|
110
121
|
def fire!(event_name, *args, &block)
|
111
|
-
|
122
|
+
event_name = event_name.to_s.+("!").to_sym
|
123
|
+
@instance.send(event_name, *args, &block)
|
112
124
|
end
|
113
125
|
|
114
126
|
def set_current_state_with_persistence(state)
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'after_commit_action'
|
1
2
|
require 'aasm/persistence/orm'
|
2
3
|
module AASM
|
3
4
|
module Persistence
|
@@ -28,6 +29,7 @@ module AASM
|
|
28
29
|
# end
|
29
30
|
#
|
30
31
|
def self.included(base)
|
32
|
+
base.send(:include, ::AfterCommitAction) unless base.include?(::AfterCommitAction)
|
31
33
|
base.send(:include, AASM::Persistence::Base)
|
32
34
|
base.send(:include, AASM::Persistence::ORM)
|
33
35
|
base.send(:include, AASM::Persistence::ActiveRecordPersistence::InstanceMethods)
|
@@ -88,6 +90,12 @@ module AASM
|
|
88
90
|
end
|
89
91
|
end
|
90
92
|
|
93
|
+
def aasm_execute_after_commit
|
94
|
+
execute_after_commit do
|
95
|
+
yield
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
91
99
|
def aasm_enum(name=:default)
|
92
100
|
case AASM::StateMachineStore.fetch(self.class, true).machine(name).config.enum
|
93
101
|
when false then nil
|
@@ -141,7 +149,8 @@ module AASM
|
|
141
149
|
|
142
150
|
def aasm_column_is_blank?(state_machine_name)
|
143
151
|
attribute_name = self.class.aasm(state_machine_name).attribute_name
|
144
|
-
attribute_names.include?(attribute_name.to_s) &&
|
152
|
+
attribute_names.include?(attribute_name.to_s) &&
|
153
|
+
(send(attribute_name).respond_to?(:empty?) ? !!send(attribute_name).empty? : !send(attribute_name))
|
145
154
|
end
|
146
155
|
|
147
156
|
def aasm_validate_states
|
@@ -34,7 +34,7 @@ module AASM
|
|
34
34
|
# This allows for nil aasm states - be sure to add validation to your model
|
35
35
|
def aasm_read_state(name=:default)
|
36
36
|
state = send(self.class.aasm(name).attribute_name)
|
37
|
-
if state.
|
37
|
+
if !state || state.empty?
|
38
38
|
aasm_new_record? ? aasm(name).determine_state_name(self.class.aasm(name).initial_state) : nil
|
39
39
|
else
|
40
40
|
state.to_sym
|
@@ -77,7 +77,8 @@ module AASM
|
|
77
77
|
#
|
78
78
|
def aasm_ensure_initial_state
|
79
79
|
AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |state_machine_name|
|
80
|
-
send(
|
80
|
+
next if !send(self.class.aasm(state_machine_name).attribute_name) || send(self.class.aasm(state_machine_name).attribute_name).empty?
|
81
|
+
send("#{self.class.aasm(state_machine_name).attribute_name}=", aasm(state_machine_name).enter_initial_state.to_s)
|
81
82
|
end
|
82
83
|
end
|
83
84
|
end # InstanceMethods
|
@@ -83,7 +83,7 @@ module AASM
|
|
83
83
|
#
|
84
84
|
def aasm_ensure_initial_state
|
85
85
|
AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |state_machine_name|
|
86
|
-
aasm(state_machine_name).enter_initial_state if send(self.class.aasm(state_machine_name).attribute_name).
|
86
|
+
aasm(state_machine_name).enter_initial_state if !send(self.class.aasm(state_machine_name).attribute_name) || send(self.class.aasm(state_machine_name).attribute_name).empty?
|
87
87
|
end
|
88
88
|
end
|
89
89
|
end # InstanceMethods
|
@@ -106,7 +106,7 @@ module AASM
|
|
106
106
|
# mongoid has_many relationship does not load child object attributes when
|
107
107
|
# only ids are loaded, for example parent.child_ids will not load child object attributes.
|
108
108
|
# This feature is introduced in mongoid > 4.
|
109
|
-
if attribute_names.include?(attribute_name) && attributes[attribute_name].
|
109
|
+
if attribute_names.include?(attribute_name) && !attributes[attribute_name] || attributes[attribute_name].empty?
|
110
110
|
# attribute_missing? is defined in mongoid > 4
|
111
111
|
return if Mongoid::VERSION.to_f >= 4 && attribute_missing?(attribute_name)
|
112
112
|
send("#{self.class.aasm(state_machine_name).attribute_name}=", aasm(state_machine_name).enter_initial_state.to_s)
|
@@ -96,7 +96,7 @@ module AASM
|
|
96
96
|
def aasm_ensure_initial_state
|
97
97
|
AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |name|
|
98
98
|
aasm_column = self.class.aasm(name).attribute_name
|
99
|
-
aasm(name).enter_initial_state if read_attribute(aasm_column).
|
99
|
+
aasm(name).enter_initial_state if !read_attribute(aasm_column) || read_attribute(aasm_column).empty?
|
100
100
|
end
|
101
101
|
end
|
102
102
|
end # InstanceMethods
|
data/lib/aasm/persistence/orm.rb
CHANGED
@@ -81,6 +81,10 @@ module AASM
|
|
81
81
|
true
|
82
82
|
end
|
83
83
|
|
84
|
+
def aasm_execute_after_commit
|
85
|
+
yield
|
86
|
+
end
|
87
|
+
|
84
88
|
def aasm_write_state_attribute(state, name=:default)
|
85
89
|
aasm_write_attribute(self.class.aasm(name).attribute_name, aasm_raw_attribute_value(state, name))
|
86
90
|
end
|
@@ -116,32 +120,32 @@ module AASM
|
|
116
120
|
|
117
121
|
# Returns true if event was fired successfully and transaction completed.
|
118
122
|
def aasm_fire_event(state_machine_name, name, options, *args, &block)
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
end
|
129
|
-
else
|
123
|
+
return super unless aasm_supports_transactions? && options[:persist]
|
124
|
+
|
125
|
+
event = self.class.aasm(state_machine_name).state_machine.events[name]
|
126
|
+
event.fire_callbacks(:before_transaction, self, *args)
|
127
|
+
event.fire_global_callbacks(:before_all_transactions, self, *args)
|
128
|
+
|
129
|
+
begin
|
130
|
+
success = if options[:persist] && use_transactions?(state_machine_name)
|
131
|
+
aasm_transaction(requires_new?(state_machine_name), requires_lock?(state_machine_name)) do
|
130
132
|
super
|
131
133
|
end
|
134
|
+
else
|
135
|
+
super
|
136
|
+
end
|
132
137
|
|
133
|
-
|
138
|
+
if success
|
139
|
+
aasm_execute_after_commit do
|
134
140
|
event.fire_callbacks(:after_commit, self, *args)
|
135
141
|
event.fire_global_callbacks(:after_all_commits, self, *args)
|
136
142
|
end
|
137
|
-
|
138
|
-
success
|
139
|
-
ensure
|
140
|
-
event.fire_callbacks(:after_transaction, self, *args)
|
141
|
-
event.fire_global_callbacks(:after_all_transactions, self, *args)
|
142
143
|
end
|
143
|
-
|
144
|
-
|
144
|
+
|
145
|
+
success
|
146
|
+
ensure
|
147
|
+
event.fire_callbacks(:after_transaction, self, *args)
|
148
|
+
event.fire_global_callbacks(:after_all_transactions, self, *args)
|
145
149
|
end
|
146
150
|
end
|
147
151
|
|
@@ -69,7 +69,7 @@ module AASM
|
|
69
69
|
def aasm_ensure_initial_state
|
70
70
|
AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |name|
|
71
71
|
aasm_column = self.class.aasm(name).attribute_name
|
72
|
-
aasm(name).enter_initial_state if send(aasm_column).value.
|
72
|
+
aasm(name).enter_initial_state if !send(aasm_column).value || send(aasm_column).value.empty?
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
@@ -2,7 +2,11 @@ RSpec::Matchers.define :transition_from do |from_state|
|
|
2
2
|
match do |obj|
|
3
3
|
@state_machine_name ||= :default
|
4
4
|
obj.aasm(@state_machine_name).current_state = from_state.to_sym
|
5
|
-
|
5
|
+
begin
|
6
|
+
obj.send(@event, *@args) && obj.aasm(@state_machine_name).current_state == @to_state.to_sym
|
7
|
+
rescue AASM::InvalidTransition
|
8
|
+
false
|
9
|
+
end
|
6
10
|
end
|
7
11
|
|
8
12
|
chain :on do |state_machine_name|
|
data/lib/aasm/version.rb
CHANGED
data/spec/database.rb
CHANGED
@@ -14,6 +14,9 @@ ActiveRecord::Migration.suppress_messages do
|
|
14
14
|
ActiveRecord::Migration.create_table "implemented_abstract_class_dsls", :force => true do |t|
|
15
15
|
t.string "status"
|
16
16
|
end
|
17
|
+
ActiveRecord::Migration.create_table "users", :force => true do |t|
|
18
|
+
t.string "status"
|
19
|
+
end
|
17
20
|
|
18
21
|
ActiveRecord::Migration.create_table "complex_active_record_examples", :force => true do |t|
|
19
22
|
t.string "left"
|
@@ -48,4 +51,9 @@ ActiveRecord::Migration.suppress_messages do
|
|
48
51
|
t.string "search"
|
49
52
|
t.string "sync"
|
50
53
|
end
|
54
|
+
|
55
|
+
ActiveRecord::Migration.create_table "instance_level_skip_validation_examples", :force => true do |t|
|
56
|
+
t.string "state"
|
57
|
+
t.string "some_string"
|
58
|
+
end
|
51
59
|
end
|