transitions 0.0.17 → 0.0.18

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ # 0.0.18 (2012-05-18)
2
+
3
+ * (troessner) Remove `define_state_query_method` from public API
4
+ * (troessner) Do not override existing methods when defining state query methods but warn the user.
5
+
1
6
  # 0.0.17 (2012-05-02):
2
7
 
3
8
  * (zmillman) Add write_state_without_persistence.
@@ -27,7 +27,7 @@ module Transitions
27
27
  def initialize(name, options = {})
28
28
  @name = name
29
29
  if machine = options.delete(:machine)
30
- machine.klass.define_state_query_method(name)
30
+ define_state_query_method(machine)
31
31
  end
32
32
  update(options)
33
33
  end
@@ -63,5 +63,30 @@ module Transitions
63
63
  @options = options
64
64
  self
65
65
  end
66
+
67
+ private
68
+ def define_state_query_method(machine)
69
+ method_name, state_name = "#{@name}?", @name # Instance vars are out of scope when calling define_method below, so we use local variables.
70
+ if method_already_defined_on_recipient?(machine, method_name)
71
+ override_warning method_name
72
+ else
73
+ machine.klass.send :define_method, method_name do
74
+ current_state.to_s == state_name.to_s
75
+ end
76
+ end
77
+ end
78
+
79
+ def method_already_defined_on_recipient?(machine, method_name)
80
+ machine.klass.new.respond_to?(method_name)
81
+ end
82
+
83
+ def override_warning(method_name)
84
+ warning = "Transitions: Can not define method #{method_name} because it is already defined, please rename either the existing method or the state."
85
+ if Rails && Rails.logger
86
+ Rails.logger.warn warning
87
+ else
88
+ puts warning
89
+ end
90
+ end
66
91
  end
67
92
  end
@@ -1,3 +1,3 @@
1
1
  module Transitions
2
- VERSION = "0.0.17"
2
+ VERSION = "0.0.18"
3
3
  end
data/lib/transitions.rb CHANGED
@@ -32,7 +32,7 @@ module Transitions
32
32
 
33
33
  module ClassMethods
34
34
  def inherited(klass)
35
- super
35
+ super # Make sure we call other callbacks possibly defined upstream the ancestor chain.
36
36
  klass.state_machines = state_machines
37
37
  end
38
38
 
@@ -40,6 +40,7 @@ module Transitions
40
40
  @state_machines ||= {}
41
41
  end
42
42
 
43
+ # The only reason we need this method is for the inherited callback.
43
44
  def state_machines=(value)
44
45
  @state_machines = value ? value.dup : nil
45
46
  end
@@ -57,18 +58,13 @@ module Transitions
57
58
  def available_states(name = :default)
58
59
  state_machines[name].states.map(&:name).sort_by {|x| x.to_s}
59
60
  end
60
-
61
- def define_state_query_method(state_name)
62
- name = "#{state_name}?"
63
- undef_method(name) if method_defined?(name)
64
- define_method(name) { current_state.to_s == %(#{state_name}) }
65
- end
66
61
  end
67
62
 
68
63
  def self.included(base)
69
64
  base.extend(ClassMethods)
70
65
  end
71
66
 
67
+ # TODO Do we need this method really? Also, it's not a beauty, refactor at least.
72
68
  def current_state(name = nil, new_state = nil, persist = false)
73
69
  sm = self.class.state_machine(name)
74
70
  ivar = sm.current_state_variable
data/test/db/create_db.rb CHANGED
@@ -5,6 +5,9 @@ class CreateDb < ActiveRecord::Migration
5
5
  t.string :state
6
6
  t.string :name
7
7
  end
8
+ create_table(:bunnies, :force => true) do |t|
9
+ t.string :state
10
+ end
8
11
 
9
12
  create_table(:orders, :force => true) do |t|
10
13
  t.string :state
data/test/helper.rb CHANGED
@@ -7,6 +7,7 @@ require "db/create_db"
7
7
 
8
8
  require "transitions"
9
9
  require "active_model/transitions"
10
+ require 'random_data'
10
11
 
11
12
  def create_database
12
13
  ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
@@ -1,6 +1,8 @@
1
1
  require "helper"
2
2
  require 'active_support/core_ext/module/aliasing'
3
3
 
4
+ # TODO Tests here are quite messy, clean up.
5
+
4
6
  ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
5
7
 
6
8
  class CreateTrafficLights < ActiveRecord::Migration
@@ -188,34 +190,49 @@ class TestNewActiveRecord < TestActiveRecord
188
190
 
189
191
  end
190
192
 
193
+ class CreateBunnies < ActiveRecord::Migration
194
+ def self.up
195
+ create_table(:bunnies) do |t|
196
+ t.string :state
197
+ end
198
+ end
199
+ end
200
+
201
+ CreateBunnies.migrate(:up)
202
+
203
+ class Bunny < ActiveRecord::Base
204
+ include ActiveModel::Transitions
205
+
206
+ state_machine :auto_scopes => true do
207
+ state :hobbling
208
+ end
209
+ end
210
+
191
211
  class TestScopes < Test::Unit::TestCase
192
- test "scope returns correct object" do
193
- @light = TrafficLight.create!
194
- assert_respond_to TrafficLight, :off
195
- assert_equal TrafficLight.off.first, @light
196
- assert TrafficLight.red.empty?
212
+ def setup
213
+ create_database
214
+ @bunny = Bunny.create!
197
215
  end
198
216
 
199
217
  test "scopes exist" do
200
- assert_respond_to TrafficLight, :off
201
- assert_respond_to TrafficLight, :red
202
- assert_respond_to TrafficLight, :green
203
- assert_respond_to TrafficLight, :yellow
218
+ assert_respond_to Bunny, :hobbling
219
+ end
220
+
221
+ test "scope returns correct object" do
222
+ assert_equal Bunny.hobbling.first, @bunny
204
223
  end
205
224
 
206
225
  test 'scopes are only generated if we explicitly say so' do
207
226
  assert_not_respond_to LightBulb, :off
208
- assert_not_respond_to LightBulb, :on
209
227
  end
210
228
 
211
229
  test 'scope generation raises an exception if we try to overwrite an existing method' do
212
230
  assert_raise(Transitions::InvalidMethodOverride) {
213
- class Light < ActiveRecord::Base
231
+ class TrafficLight < ActiveRecord::Base
214
232
  include ActiveModel::Transitions
215
233
 
216
234
  state_machine :auto_scopes => true do
217
235
  state :new
218
- state :broken
219
236
  end
220
237
  end
221
238
  }
data/test/test_state.rb CHANGED
@@ -1,50 +1,50 @@
1
1
  require "helper"
2
2
 
3
- class StateTestSubject
4
- include Transitions
5
-
6
- state_machine do
7
- end
8
- end
9
-
10
3
  class TestState < Test::Unit::TestCase
11
4
  def setup
5
+ @state_test_subject = Class.new do
6
+ include Transitions
7
+ state_machine do
8
+ end
9
+ end
12
10
  @state_name = :astate
13
- @machine = StateTestSubject.state_machine
14
- @options = { :crazy_custom_key => "key", :machine => @machine }
11
+ @machine = @state_test_subject.state_machine
12
+ @options = { :machine => @machine, :custom_key => :my_key }
13
+ @state = Transitions::State.new(@state_name, @options)
15
14
  end
16
15
 
17
- def new_state(options={})
18
- Transitions::State.new(@state_name, @options.merge(options))
16
+ def new_state_name
17
+ Random.alphanumeric(16)
19
18
  end
20
19
 
21
20
  test "sets the name" do
22
- assert_equal :astate, new_state.name
21
+ assert_equal :astate, @state.name
23
22
  end
24
23
 
25
24
  test "sets the display_name from name" do
26
- assert_equal "Astate", new_state.display_name
25
+ assert_equal "Astate", @state.display_name
27
26
  end
28
27
 
29
28
  test "sets the display_name from options" do
30
- assert_equal "A State", new_state(:display => "A State").display_name
29
+ assert_equal "A State", Transitions::State.new(new_state_name, @options.merge(:display => "A State")).display_name
31
30
  end
32
31
 
33
32
  test "sets the options and expose them as options" do
34
33
  @options.delete(:machine)
35
- assert_equal @options, new_state.options
34
+ state = Transitions::State.new new_state_name, @options
35
+ assert_equal @options, state.options
36
36
  end
37
37
 
38
38
  test "equals a symbol of the same name" do
39
- assert_equal new_state, :astate
39
+ assert_equal @state, :astate
40
40
  end
41
41
 
42
42
  test "equals a State of the same name" do
43
- assert_equal new_state, new_state
43
+ assert_equal @state, @state
44
44
  end
45
45
 
46
46
  test "should send a message to the record for an action if the action is present as a symbol" do
47
- state = new_state(:entering => :foo)
47
+ state = Transitions::State.new new_state_name, @options.merge(:entering => :foo)
48
48
 
49
49
  record = stub
50
50
  record.expects(:foo)
@@ -53,7 +53,7 @@ class TestState < Test::Unit::TestCase
53
53
  end
54
54
 
55
55
  test "should send a message to the record for an action if the action is present as a string" do
56
- state = new_state(:entering => "foo")
56
+ state = Transitions::State.new new_state_name, @options.merge(:entering => "foo")
57
57
 
58
58
  record = stub
59
59
  record.expects(:foo)
@@ -62,7 +62,7 @@ class TestState < Test::Unit::TestCase
62
62
  end
63
63
 
64
64
  test "should call a proc, passing in the record for an action if the action is present" do
65
- state = new_state(:entering => Proc.new {|r| r.foobar})
65
+ state = Transitions::State.new new_state_name, @options.merge(:entering => Proc.new {|r| r.foobar})
66
66
 
67
67
  record = stub
68
68
  record.expects(:foobar)
@@ -70,3 +70,32 @@ class TestState < Test::Unit::TestCase
70
70
  state.call_action(:entering, record)
71
71
  end
72
72
  end
73
+
74
+ class StateOverrideMethodTestSubject
75
+ include Transitions
76
+
77
+ state_machine do
78
+ end
79
+
80
+ def a_state_name?; :foo; end
81
+ end
82
+
83
+
84
+ class TestStateQueryOverrideMethod < Test::Unit::TestCase
85
+ def setup
86
+ @state_name = 'a_state_name'
87
+ @machine = StateOverrideMethodTestSubject.state_machine
88
+ @options = { :machine => @machine }
89
+ end
90
+
91
+ test "warn on creation when we try to overwrite an existing method" do
92
+ # TODO
93
+ end
94
+
95
+ test "should not override an already existing method" do
96
+ Transitions::State.new :dummy, @options
97
+ expected_result = :foo
98
+ actual_result = StateOverrideMethodTestSubject.new.a_state_name?
99
+ assert_equal expected_result, actual_result
100
+ end
101
+ end
data/transitions.gemspec CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |s|
18
18
  s.add_development_dependency "test-unit", "~> 2.2"
19
19
  s.add_development_dependency "mocha"
20
20
  s.add_development_dependency "rake"
21
+ s.add_development_dependency "random_data"
21
22
  s.add_development_dependency "sqlite3"
22
23
  s.add_development_dependency "activerecord", "~> 3"
23
24
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: transitions
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.17
4
+ version: 0.0.18
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-05-02 00:00:00.000000000Z
13
+ date: 2012-05-18 00:00:00.000000000Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
17
- requirement: &80694140 !ruby/object:Gem::Requirement
17
+ requirement: &76418870 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ~>
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: '1'
23
23
  type: :development
24
24
  prerelease: false
25
- version_requirements: *80694140
25
+ version_requirements: *76418870
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: test-unit
28
- requirement: &80692960 !ruby/object:Gem::Requirement
28
+ requirement: &76418470 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ~>
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: '2.2'
34
34
  type: :development
35
35
  prerelease: false
36
- version_requirements: *80692960
36
+ version_requirements: *76418470
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: mocha
39
- requirement: &80692570 !ruby/object:Gem::Requirement
39
+ requirement: &76418120 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,10 +44,10 @@ dependencies:
44
44
  version: '0'
45
45
  type: :development
46
46
  prerelease: false
47
- version_requirements: *80692570
47
+ version_requirements: *76418120
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: rake
50
- requirement: &80682540 !ruby/object:Gem::Requirement
50
+ requirement: &76417650 !ruby/object:Gem::Requirement
51
51
  none: false
52
52
  requirements:
53
53
  - - ! '>='
@@ -55,10 +55,21 @@ dependencies:
55
55
  version: '0'
56
56
  type: :development
57
57
  prerelease: false
58
- version_requirements: *80682540
58
+ version_requirements: *76417650
59
+ - !ruby/object:Gem::Dependency
60
+ name: random_data
61
+ requirement: &76417170 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: *76417170
59
70
  - !ruby/object:Gem::Dependency
60
71
  name: sqlite3
61
- requirement: &80681530 !ruby/object:Gem::Requirement
72
+ requirement: &76416820 !ruby/object:Gem::Requirement
62
73
  none: false
63
74
  requirements:
64
75
  - - ! '>='
@@ -66,10 +77,10 @@ dependencies:
66
77
  version: '0'
67
78
  type: :development
68
79
  prerelease: false
69
- version_requirements: *80681530
80
+ version_requirements: *76416820
70
81
  - !ruby/object:Gem::Dependency
71
82
  name: activerecord
72
- requirement: &80680830 !ruby/object:Gem::Requirement
83
+ requirement: &76416030 !ruby/object:Gem::Requirement
73
84
  none: false
74
85
  requirements:
75
86
  - - ~>
@@ -77,7 +88,7 @@ dependencies:
77
88
  version: '3'
78
89
  type: :development
79
90
  prerelease: false
80
- version_requirements: *80680830
91
+ version_requirements: *76416030
81
92
  description: Lightweight state machine extracted from ActiveModel
82
93
  email: timo.roessner@googlemail.com
83
94
  executables: []
@@ -129,7 +140,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
129
140
  version: '0'
130
141
  segments:
131
142
  - 0
132
- hash: -1021171215
143
+ hash: -1015670387
133
144
  required_rubygems_version: !ruby/object:Gem::Requirement
134
145
  none: false
135
146
  requirements: