simple_state_machine 0.4.3 → 0.5.0.beta
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.
- data/.rspec +3 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +34 -0
- data/Rakefile +17 -34
- data/autotest/discover.rb +1 -0
- data/lib/simple_state_machine/active_record.rb +11 -6
- data/lib/simple_state_machine/simple_state_machine.rb +77 -27
- data/lib/simple_state_machine/version.rb +3 -0
- data/lib/simple_state_machine.rb +1 -1
- data/simple_state_machine.gemspec +13 -54
- data/spec/active_record_spec.rb +53 -24
- data/spec/decorator_spec.rb +179 -28
- data/spec/examples_spec.rb +1 -0
- data/spec/mountable_spec.rb +24 -0
- data/spec/simple_state_machine_spec.rb +73 -93
- data/spec/spec_helper.rb +0 -6
- data/spec/state_machine_definition_spec.rb +89 -0
- data/spec/state_machine_spec.rb +26 -0
- metadata +87 -24
- data/VERSION +0 -1
- data/spec/spec.opts +0 -3
data/.rspec
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
simple_state_machine (1.5.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
ZenTest (4.4.2)
|
10
|
+
activerecord (2.3.10)
|
11
|
+
activesupport (= 2.3.10)
|
12
|
+
activesupport (2.3.10)
|
13
|
+
diff-lcs (1.1.2)
|
14
|
+
rake (0.8.7)
|
15
|
+
rspec (2.5.0)
|
16
|
+
rspec-core (~> 2.5.0)
|
17
|
+
rspec-expectations (~> 2.5.0)
|
18
|
+
rspec-mocks (~> 2.5.0)
|
19
|
+
rspec-core (2.5.1)
|
20
|
+
rspec-expectations (2.5.0)
|
21
|
+
diff-lcs (~> 1.1.2)
|
22
|
+
rspec-mocks (2.5.0)
|
23
|
+
sqlite3-ruby (1.3.1)
|
24
|
+
|
25
|
+
PLATFORMS
|
26
|
+
ruby
|
27
|
+
|
28
|
+
DEPENDENCIES
|
29
|
+
ZenTest
|
30
|
+
activerecord (~> 2.3.5)
|
31
|
+
rake
|
32
|
+
rspec
|
33
|
+
simple_state_machine!
|
34
|
+
sqlite3-ruby
|
data/Rakefile
CHANGED
@@ -1,38 +1,21 @@
|
|
1
|
-
require '
|
2
|
-
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
require 'spec/rake/spectask'
|
22
|
-
Spec::Rake::SpecTask.new(:spec) do |spec|
|
23
|
-
spec.libs << 'lib' << 'spec'
|
24
|
-
spec.spec_files = FileList['spec/**/*_spec.rb']
|
25
|
-
end
|
26
|
-
|
27
|
-
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
28
|
-
spec.libs << 'lib' << 'spec'
|
29
|
-
spec.pattern = 'spec/**/*_spec.rb'
|
30
|
-
spec.rcov = true
|
31
|
-
end
|
32
|
-
|
33
|
-
task :spec => :check_dependencies
|
34
|
-
|
35
|
-
task :default => :spec
|
4
|
+
#require 'spec/rake/spectask'
|
5
|
+
#Spec::Rake::SpecTask.new(:spec) do |spec|
|
6
|
+
# spec.libs << 'lib' << 'spec'
|
7
|
+
# spec.spec_files = FileList['spec/**/*_spec.rb']
|
8
|
+
#end
|
9
|
+
#
|
10
|
+
#Spec::Rake::SpecTask.new(:rcov) do |spec|
|
11
|
+
# spec.libs << 'lib' << 'spec'
|
12
|
+
# spec.pattern = 'spec/**/*_spec.rb'
|
13
|
+
# spec.rcov = true
|
14
|
+
#end
|
15
|
+
#
|
16
|
+
#task :spec => :check_dependencies
|
17
|
+
#
|
18
|
+
#task :default => :spec
|
36
19
|
|
37
20
|
require 'rake/rdoctask'
|
38
21
|
Rake::RDocTask.new do |rdoc|
|
@@ -0,0 +1 @@
|
|
1
|
+
Autotest.add_discovery { "rspec2" }
|
@@ -1,10 +1,8 @@
|
|
1
1
|
module SimpleStateMachine::ActiveRecord
|
2
2
|
|
3
|
-
include SimpleStateMachine::
|
4
|
-
|
5
|
-
|
6
|
-
Decorator.new subject
|
7
|
-
end
|
3
|
+
include SimpleStateMachine::Mountable
|
4
|
+
include SimpleStateMachine::Extendable
|
5
|
+
include SimpleStateMachine::Inheritable
|
8
6
|
|
9
7
|
class Decorator < SimpleStateMachine::Decorator
|
10
8
|
|
@@ -60,5 +58,12 @@ module SimpleStateMachine::ActiveRecord
|
|
60
58
|
def define_state_getter_method; end
|
61
59
|
|
62
60
|
end
|
63
|
-
|
61
|
+
|
62
|
+
def state_machine_definition
|
63
|
+
unless @state_machine_definition
|
64
|
+
@state_machine_definition = SimpleStateMachine::StateMachineDefinition.new
|
65
|
+
@state_machine_definition.lazy_decorator = lambda { Decorator.new(self) }
|
66
|
+
end
|
67
|
+
@state_machine_definition
|
68
|
+
end
|
64
69
|
end
|
@@ -1,50 +1,68 @@
|
|
1
1
|
module SimpleStateMachine
|
2
|
+
|
3
|
+
require 'cgi'
|
2
4
|
|
3
|
-
class
|
5
|
+
class IllegalStateTransitionError < ::RuntimeError
|
4
6
|
end
|
5
7
|
|
8
|
+
##
|
9
|
+
# Allows class to mount a state_machine
|
10
|
+
module Mountable
|
11
|
+
def state_machine_definition
|
12
|
+
unless @state_machine_definition
|
13
|
+
@state_machine_definition = StateMachineDefinition.new
|
14
|
+
@state_machine_definition.lazy_decorator = lambda { Decorator.new(self) }
|
15
|
+
end
|
16
|
+
@state_machine_definition
|
17
|
+
end
|
18
|
+
|
19
|
+
def state_machine_definition= state_machine_definition
|
20
|
+
@state_machine_definition = state_machine_definition
|
21
|
+
state_machine_definition.transitions.each do |transition|
|
22
|
+
state_machine_definition.decorator.decorate(transition)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
include Mountable
|
27
|
+
|
6
28
|
##
|
7
29
|
# Adds state machine methods to the extended class
|
8
|
-
module
|
30
|
+
module Extendable
|
9
31
|
|
10
32
|
# mark the method as an event and specify how the state should transition
|
11
33
|
def event event_name, state_transitions
|
12
34
|
state_transitions.each do |froms, to|
|
13
35
|
[froms].flatten.each do |from|
|
14
|
-
|
15
|
-
state_machine_decorator(self).decorate(transition)
|
36
|
+
state_machine_definition.add_transition(event_name, from, to)
|
16
37
|
end
|
17
38
|
end
|
18
39
|
end
|
19
40
|
|
20
|
-
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
def state_machine_definition= state_machine_definition
|
25
|
-
@state_machine_definition = state_machine_definition
|
26
|
-
state_machine_definition.transitions.each do |transition|
|
27
|
-
state_machine_decorator(self).decorate(transition)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def state_machine_decorator subject
|
32
|
-
Decorator.new subject
|
33
|
-
end
|
41
|
+
end
|
42
|
+
include Extendable
|
34
43
|
|
44
|
+
##
|
45
|
+
# Allows subclasses to inherit state machines
|
46
|
+
module Inheritable
|
35
47
|
def inherited(subclass)
|
36
48
|
subclass.state_machine_definition = state_machine_definition.clone
|
49
|
+
decorator = state_machine_definition.decorator
|
50
|
+
decorator.subject = subclass
|
51
|
+
subclass.state_machine_definition.decorator = decorator
|
37
52
|
super
|
38
53
|
end
|
39
54
|
end
|
40
|
-
|
41
|
-
include StateMachineMixin
|
55
|
+
include Inheritable
|
42
56
|
|
43
57
|
##
|
44
58
|
# Defines state machine transitions
|
45
59
|
class StateMachineDefinition
|
46
60
|
|
47
|
-
attr_writer :state_method
|
61
|
+
attr_writer :state_method, :decorator, :lazy_decorator
|
62
|
+
|
63
|
+
def decorator
|
64
|
+
@decorator ||= @lazy_decorator.call
|
65
|
+
end
|
48
66
|
|
49
67
|
def transitions
|
50
68
|
@transitions ||= []
|
@@ -53,12 +71,28 @@ module SimpleStateMachine
|
|
53
71
|
def add_transition event_name, from, to
|
54
72
|
transition = Transition.new(event_name, from, to)
|
55
73
|
transitions << transition
|
56
|
-
transition
|
74
|
+
decorator.decorate(transition)
|
57
75
|
end
|
58
76
|
|
59
77
|
def state_method
|
60
78
|
@state_method ||= :state
|
61
79
|
end
|
80
|
+
|
81
|
+
# Human readable format: old_state.event! => new_state
|
82
|
+
def to_s
|
83
|
+
transitions.map(&:to_s).join("\n")
|
84
|
+
end
|
85
|
+
|
86
|
+
# Graphiz dot format for rendering as a directional graph
|
87
|
+
def to_graphiz_dot
|
88
|
+
transitions.map { |t| t.to_graphiz_dot }.join(";")
|
89
|
+
end
|
90
|
+
|
91
|
+
# Generates a url that renders states and events as a directional graph.
|
92
|
+
# See http://code.google.com/apis/chart/docs/gallery/graphviz.html
|
93
|
+
def google_chart_url
|
94
|
+
"http://chart.googleapis.com/chart?cht=gv&chl=digraph{#{::CGI.escape to_graphiz_dot}}"
|
95
|
+
end
|
62
96
|
end
|
63
97
|
|
64
98
|
##
|
@@ -128,7 +162,7 @@ module SimpleStateMachine
|
|
128
162
|
|
129
163
|
# override with your own implementation, like setting errors in your model
|
130
164
|
def illegal_event_callback event_name
|
131
|
-
raise
|
165
|
+
raise IllegalStateTransitionError.new("You cannot '#{event_name}' when state is '#{@subject.send(state_method)}'")
|
132
166
|
end
|
133
167
|
|
134
168
|
end
|
@@ -153,6 +187,15 @@ module SimpleStateMachine
|
|
153
187
|
is_same_event?(event_name) && error.class == from
|
154
188
|
end
|
155
189
|
|
190
|
+
def to_s
|
191
|
+
"#{from}.#{event_name}! => #{to}"
|
192
|
+
end
|
193
|
+
|
194
|
+
def to_graphiz_dot
|
195
|
+
%("#{from}"->"#{to}"[label=#{event_name}])
|
196
|
+
end
|
197
|
+
|
198
|
+
|
156
199
|
private
|
157
200
|
|
158
201
|
def is_same_event?(event_name)
|
@@ -168,6 +211,7 @@ module SimpleStateMachine
|
|
168
211
|
# Decorates @subject with methods to access the state machine
|
169
212
|
class Decorator
|
170
213
|
|
214
|
+
attr_writer :subject
|
171
215
|
def initialize(subject)
|
172
216
|
@subject = subject
|
173
217
|
define_state_machine_method
|
@@ -191,7 +235,7 @@ module SimpleStateMachine
|
|
191
235
|
end
|
192
236
|
|
193
237
|
def define_state_helper_method state
|
194
|
-
unless
|
238
|
+
unless any_method_defined?("#{state.to_s}?")
|
195
239
|
@subject.send(:define_method, "#{state.to_s}?") do
|
196
240
|
self.send(self.class.state_machine_definition.state_method) == state.to_s
|
197
241
|
end
|
@@ -199,7 +243,7 @@ module SimpleStateMachine
|
|
199
243
|
end
|
200
244
|
|
201
245
|
def define_event_method event_name
|
202
|
-
unless
|
246
|
+
unless any_method_defined?("#{event_name}")
|
203
247
|
@subject.send(:define_method, "#{event_name}") {}
|
204
248
|
end
|
205
249
|
end
|
@@ -218,7 +262,7 @@ module SimpleStateMachine
|
|
218
262
|
end
|
219
263
|
|
220
264
|
def define_state_setter_method
|
221
|
-
unless
|
265
|
+
unless any_method_defined?("#{state_method}=")
|
222
266
|
@subject.send(:define_method, "#{state_method}=") do |new_state|
|
223
267
|
instance_variable_set(:"@#{self.class.state_machine_definition.state_method}", new_state)
|
224
268
|
end
|
@@ -226,10 +270,16 @@ module SimpleStateMachine
|
|
226
270
|
end
|
227
271
|
|
228
272
|
def define_state_getter_method
|
229
|
-
unless
|
273
|
+
unless any_method_defined?(state_method)
|
230
274
|
@subject.send(:attr_reader, state_method)
|
231
275
|
end
|
232
276
|
end
|
277
|
+
|
278
|
+
def any_method_defined?(method)
|
279
|
+
@subject.method_defined?(method) ||
|
280
|
+
@subject.protected_method_defined?(method) ||
|
281
|
+
@subject.private_method_defined?(method)
|
282
|
+
end
|
233
283
|
|
234
284
|
protected
|
235
285
|
|
data/lib/simple_state_machine.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
require 'simple_state_machine/simple_state_machine'
|
2
|
-
require 'simple_state_machine/active_record'
|
2
|
+
require 'simple_state_machine/active_record'
|
@@ -1,72 +1,31 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "simple_state_machine/version"
|
5
4
|
|
6
5
|
Gem::Specification.new do |s|
|
7
6
|
s.name = %q{simple_state_machine}
|
8
|
-
s.version
|
7
|
+
s.version = SimpleStateMachine::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
9
|
|
10
|
-
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
10
|
s.authors = ["Marek de Heus", "Petrik de Heus"]
|
12
|
-
s.date = %q{2010-09-14}
|
13
11
|
s.description = %q{A simple DSL to decorate existing methods with logic that guards state transitions.}
|
14
12
|
s.email = ["FIX@example.com"]
|
13
|
+
s.homepage = %q{http://github.com/mdh/ssm}
|
15
14
|
s.extra_rdoc_files = [
|
16
15
|
"LICENSE",
|
17
16
|
"README.rdoc"
|
18
17
|
]
|
19
|
-
s.files
|
20
|
-
|
21
|
-
"LICENSE",
|
22
|
-
"README.rdoc",
|
23
|
-
"Rakefile",
|
24
|
-
"VERSION",
|
25
|
-
"examples/conversation.rb",
|
26
|
-
"examples/lamp.rb",
|
27
|
-
"examples/relationship.rb",
|
28
|
-
"examples/traffic_light.rb",
|
29
|
-
"examples/user.rb",
|
30
|
-
"lib/simple_state_machine.rb",
|
31
|
-
"lib/simple_state_machine/active_record.rb",
|
32
|
-
"lib/simple_state_machine/simple_state_machine.rb",
|
33
|
-
"simple_state_machine.gemspec",
|
34
|
-
"spec/active_record_spec.rb",
|
35
|
-
"spec/decorator_spec.rb",
|
36
|
-
"spec/examples_spec.rb",
|
37
|
-
"spec/simple_state_machine_spec.rb",
|
38
|
-
"spec/spec.opts",
|
39
|
-
"spec/spec_helper.rb"
|
40
|
-
]
|
41
|
-
s.homepage = %q{http://github.com/mdh/ssm}
|
18
|
+
s.files = `git ls-files`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
42
20
|
s.rdoc_options = ["--charset=UTF-8"]
|
43
21
|
s.require_paths = ["lib"]
|
44
22
|
s.rubygems_version = %q{1.3.7}
|
45
23
|
s.summary = %q{A statemachine that focuses on events instead of states}
|
46
|
-
s.test_files
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
"examples/conversation.rb",
|
53
|
-
"examples/lamp.rb",
|
54
|
-
"examples/relationship.rb",
|
55
|
-
"examples/traffic_light.rb",
|
56
|
-
"examples/user.rb"
|
57
|
-
]
|
58
|
-
|
59
|
-
if s.respond_to? :specification_version then
|
60
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
61
|
-
s.specification_version = 3
|
62
|
-
|
63
|
-
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
64
|
-
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
65
|
-
else
|
66
|
-
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
67
|
-
end
|
68
|
-
else
|
69
|
-
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
70
|
-
end
|
24
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
25
|
+
s.add_development_dependency "rake"
|
26
|
+
s.add_development_dependency "ZenTest"
|
27
|
+
s.add_development_dependency "rspec"
|
28
|
+
s.add_development_dependency "activerecord", "~>2.3.5"
|
29
|
+
s.add_development_dependency "sqlite3-ruby"
|
71
30
|
end
|
72
31
|
|
data/spec/active_record_spec.rb
CHANGED
@@ -1,28 +1,29 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
2
|
|
3
|
-
require
|
4
|
-
|
3
|
+
require "rubygems"
|
4
|
+
require "bundler"
|
5
|
+
Bundler.require
|
6
|
+
#Bundler.setup(:test)#, :activerecord)
|
5
7
|
require 'active_record'
|
6
8
|
require 'examples/user'
|
7
9
|
|
8
|
-
ActiveRecord::Base.logger = Logger.new
|
9
|
-
ActiveRecord::Base.establish_connection(:adapter
|
10
|
+
ActiveRecord::Base.logger = Logger.new "test.log"
|
11
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3",
|
12
|
+
:database => ":memory:")
|
10
13
|
|
11
14
|
def setup_db
|
12
15
|
ActiveRecord::Schema.define(:version => 1) do
|
13
16
|
create_table :users do |t|
|
14
|
-
t.column :id,
|
15
|
-
t.column :name,
|
16
|
-
t.column :state,
|
17
|
-
t.column :activation_code,
|
18
|
-
t.column :created_at,
|
19
|
-
t.column :updated_at,
|
17
|
+
t.column :id, :integer
|
18
|
+
t.column :name, :string
|
19
|
+
t.column :state, :string
|
20
|
+
t.column :activation_code, :string
|
21
|
+
t.column :created_at, :datetime
|
22
|
+
t.column :updated_at, :datetime
|
20
23
|
end
|
21
|
-
end
|
22
|
-
ActiveRecord::Schema.define(:version => 1) do
|
23
24
|
create_table :tickets do |t|
|
24
|
-
t.column :id,
|
25
|
-
t.column :ssm_state,
|
25
|
+
t.column :id, :integer
|
26
|
+
t.column :ssm_state, :string
|
26
27
|
end
|
27
28
|
end
|
28
29
|
end
|
@@ -87,8 +88,10 @@ describe ActiveRecord do
|
|
87
88
|
|
88
89
|
it "raises an error if an invalid state_transition is called" do
|
89
90
|
user = User.create!(:name => 'name')
|
90
|
-
|
91
|
-
|
91
|
+
expect {
|
92
|
+
user.confirm_invitation_and_save 'abc'
|
93
|
+
}.to raise_error(SimpleStateMachine::IllegalStateTransitionError,
|
94
|
+
"You cannot 'confirm_invitation' when state is 'new'")
|
92
95
|
end
|
93
96
|
|
94
97
|
it "returns false and keeps state if record is invalid" do
|
@@ -130,16 +133,20 @@ describe ActiveRecord do
|
|
130
133
|
|
131
134
|
it "raises an error if an invalid state_transition is called" do
|
132
135
|
user = User.create!(:name => 'name')
|
133
|
-
|
134
|
-
|
136
|
+
expect {
|
137
|
+
user.confirm_invitation_and_save! 'abc'
|
138
|
+
}.to raise_error(SimpleStateMachine::IllegalStateTransitionError,
|
139
|
+
"You cannot 'confirm_invitation' when state is 'new'")
|
135
140
|
end
|
136
141
|
|
137
142
|
it "raises a RecordInvalid and keeps state if record is invalid" do
|
138
143
|
user = User.new
|
139
144
|
user.should be_new
|
140
145
|
user.should_not be_valid
|
141
|
-
|
142
|
-
|
146
|
+
expect {
|
147
|
+
user.invite_and_save!
|
148
|
+
}.to raise_error(ActiveRecord::RecordInvalid,
|
149
|
+
"Validation failed: Name can't be blank")
|
143
150
|
user.should be_new
|
144
151
|
end
|
145
152
|
|
@@ -147,13 +154,34 @@ describe ActiveRecord do
|
|
147
154
|
user = User.create!(:name => 'name')
|
148
155
|
user.invite_and_save!
|
149
156
|
user.should be_invited
|
150
|
-
|
151
|
-
|
157
|
+
expect {
|
158
|
+
user.confirm_invitation_and_save!('x')
|
159
|
+
}.to raise_error(ActiveRecord::RecordInvalid,
|
160
|
+
"Validation failed: Activation code is invalid")
|
152
161
|
user.should be_invited
|
153
162
|
end
|
154
163
|
|
155
164
|
end
|
156
165
|
|
166
|
+
describe "event" do
|
167
|
+
|
168
|
+
it "does not persist transitions" do
|
169
|
+
user = User.create!(:name => 'name')
|
170
|
+
user.invite.should == true
|
171
|
+
User.find(user.id).should_not be_invited
|
172
|
+
User.find(user.id).activation_code.should be_nil
|
173
|
+
end
|
174
|
+
|
175
|
+
it "returns false and keeps state if record is invalid" do
|
176
|
+
user = User.new
|
177
|
+
user.should be_new
|
178
|
+
user.should_not be_valid
|
179
|
+
user.invite.should == false
|
180
|
+
user.should be_new
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
|
157
185
|
describe "event!" do
|
158
186
|
|
159
187
|
it "persists transitions" do
|
@@ -167,8 +195,7 @@ describe ActiveRecord do
|
|
167
195
|
user = User.new
|
168
196
|
user.should be_new
|
169
197
|
user.should_not be_valid
|
170
|
-
|
171
|
-
l.should raise_error(ActiveRecord::RecordInvalid, "Validation failed: Name can't be blank")
|
198
|
+
expect { user.invite! }.to raise_error(ActiveRecord::RecordInvalid, "Validation failed: Name can't be blank")
|
172
199
|
user.should be_new
|
173
200
|
end
|
174
201
|
|
@@ -191,4 +218,6 @@ describe ActiveRecord do
|
|
191
218
|
end
|
192
219
|
|
193
220
|
end
|
221
|
+
|
194
222
|
end
|
223
|
+
|