omg-statelogic 1.0.2 → 1.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,2 +1,8 @@
1
- 0.1.2 - 2008-01-10
1
+ 1.1 - 2009-08-11
2
+ - adds finder methods in the form of find_all_#{state}(*args)
3
+ - adds named scope named after corresponding state
4
+ - no longer redefines existing methods with the same names, issues warnings instead
5
+ - forces state names to underscore notation when used as part of method/scope names
6
+
7
+ 0.1.2 - 2009-01-10
2
8
  - Support scoping arbitrary callbacks beyond ActiveRecord's
data/README.rdoc CHANGED
@@ -12,6 +12,13 @@ consistency over merely formal... whatever...
12
12
  - ???????
13
13
  - PROFIT!!!11
14
14
 
15
+ === Changes in v1.1
16
+ _Please review these carefully as they may be incompatible with your existing code._
17
+ - adds finder methods in the form of +find_all_#{state}(*args)+ (Order.find_all_ready) sugg. by ares
18
+ - adds named scope named after corresponding state (Order.paid) sugg. by ares
19
+ - no longer redefines existing methods with the same names, issues warnings instead
20
+ - forces state names to underscore notation when used as part of method names
21
+
15
22
  === Installation
16
23
  gem install omg-statelogic --source http://gems.github.com
17
24
 
@@ -32,7 +39,7 @@ Please report via Github issue tracking.
32
39
  initial_state 'unpaid' do
33
40
  transitions_to 'ready', 'suspended' # won't let you change to wrong states
34
41
  end
35
- state 'ready' do # you get +ready?+, +was_ready?+
42
+ state 'ready' do # you get +ready?+, +was_ready?+, +Order.ready+ named scope and +Order.find_all_ready+ finder
36
43
  transitions_to 'redeemed', 'suspended'
37
44
  validates_presence_of :txref # scoped validations
38
45
  before_save :prepare_for_plucking # scoped callbacks
@@ -1,6 +1,27 @@
1
- require 'statelogic/callbacks_ext'
1
+ require 'statelogic/callbacks_ext' unless ([ActiveRecord::VERSION::MAJOR, ActiveRecord::VERSION::MINOR] <=> [2, 3]) >= 0
2
2
 
3
3
  module Statelogic
4
+ module Util
5
+ def self.debug(msg = nil, &block)
6
+ ::ActiveRecord::Base.logger.debug(msg, &block) if ::ActiveRecord::Base.logger
7
+ end
8
+
9
+ def self.warn(msg = nil, &block)
10
+ ::ActiveRecord::Base.logger.warn(msg, &block) if ::ActiveRecord::Base.logger
11
+ end
12
+
13
+ def self.defmethod(cls, name, meta = false, &block)
14
+ c = meta ? cls.metaclass : cls
15
+ unless c.method_defined?(name)
16
+ c.send(:define_method, name, &block)
17
+ Util.debug { "Statelogic created #{meta ? 'class' : 'instance'} method #{name} on #{cls.name}." }
18
+ else
19
+ warn { "Statelogic won't override #{meta ? 'class' : 'instance'} method #{name} already defined on #{cls.name}." }
20
+ nil
21
+ end
22
+ end
23
+ end
24
+
4
25
  module ActiveRecord
5
26
  def self.included(other)
6
27
  other.extend(ClassMethods)
@@ -51,14 +72,25 @@ module Statelogic
51
72
  alias initial initial_state
52
73
 
53
74
  def state(name, options = {}, &block)
75
+ name = name.to_s
76
+ uname = name.underscore
54
77
  attr = @config[:attribute]
55
78
  attr_was = :"#{attr}_was"
56
- @class.class_eval do
57
- define_method("#{name}?") { send(attr) == name }
58
- define_method("was_#{name}?") { send(attr_was) == name }
79
+ find_all_by_attr = "find_all_by_#{attr}"
80
+
81
+ Util.defmethod(@class, "#{uname}?") { send(attr) == name }
82
+ Util.defmethod(@class, "was_#{uname}?") { send(attr_was) == name }
83
+
84
+ unless @class.respond_to?(name)
85
+ @class.send(:named_scope, uname, :conditions => {attr.to_sym => name })
86
+ Util.debug { "Statelogic has defined named scope #{uname} on #{@class.name}." }
87
+ else
88
+ Util.warn { "Statelogic won't override class method #{uname} already defined on #{@class.name}." }
59
89
  end
60
90
 
61
- StateScopeHelper.new(@class, name, @config).instance_eval(&block)
91
+ Util.defmethod(@class, "find_all_#{uname}", true) {|*args| send(find_all_by_attr, name, *args) }
92
+
93
+ StateScopeHelper.new(@class, name, @config).instance_eval(&block) if block_given?
62
94
 
63
95
  @config[:states] << name
64
96
  @config[:initial] << name if options[:initial]
@@ -73,7 +105,7 @@ module Statelogic
73
105
 
74
106
  ConfigHelper.new(self, options).instance_eval(&block)
75
107
 
76
- initial = [options[:initial], options[:states]].find {|x| !x.blank? }
108
+ initial = [options[:initial], options[:states]].find(&:present?)
77
109
  validates_inclusion_of attr, :in => initial, :on => :create if initial
78
110
 
79
111
  const = attr.to_s.pluralize.upcase
@@ -83,7 +115,5 @@ module Statelogic
83
115
  end
84
116
  end
85
117
 
86
- # :stopdoc:
87
- class ActiveRecord::Base
88
- include Statelogic::ActiveRecord
89
- end
118
+ ActiveRecord::Base.send :include, Statelogic::ActiveRecord
119
+
@@ -1,7 +1,7 @@
1
1
  class Test::Unit::TestCase
2
2
  def self.should_not_require_attributes(*attributes)
3
3
  get_options!(attributes)
4
- klass = model_class
4
+ klass = described_type
5
5
 
6
6
  attributes.each do |attribute|
7
7
  should "not require #{attribute} to be set" do
@@ -9,4 +9,5 @@ class Test::Unit::TestCase
9
9
  end
10
10
  end
11
11
  end
12
- end
12
+ end
13
+
@@ -1,39 +1,32 @@
1
1
  require 'test_helper'
2
2
 
3
- class Order < ActiveRecord::Base
4
- statelogic do
5
- initial_state 'unpaid' do
6
- transitions_to 'ready', 'suspended'
7
- end
8
- state 'ready' do
9
- transitions_to 'redeemed', 'suspended'
10
- validates_presence_of :txref
11
- end
12
- state 'redeemed' do
13
- transitions_to 'suspended'
14
- validates_presence_of :txref, :redeemed_at, :facility_id
15
- end
16
- state 'suspended' do
17
- transitions_to 'unpaid', 'ready', 'redeemed'
18
- validate do |order|
19
- order.errors.add(:txref, :invalid) if order.txref && order.txref !~ /\AREF/
20
- end
21
- end
22
- end
23
- end
3
+ #ActiveRecord::Base.logger = Logger.new(STDERR)
24
4
 
25
5
  class OrderTest < ActiveSupport::TestCase
26
6
  include ActiveRecord::TestFixtures
27
7
  self.fixture_path = 'test/fixtures'
28
8
 
29
9
  fixtures :orders
10
+
11
+ should_have_class_methods :unpaid, :ready, :redeemed, :suspended
12
+ should_have_class_methods :find_all_unpaid, :find_all_ready, :find_all_redeemed, :find_all_suspended
30
13
 
14
+ should_have_instance_methods :unpaid?, :ready?, :redeemed?, :suspended?
15
+ should_have_instance_methods :was_unpaid?, :was_ready?, :was_redeemed?, :was_suspended?
16
+
17
+ context 'Finders and scopes' do
18
+ should 'return adequate shit' do
19
+ for st in %w(unpaid ready redeemed suspended)
20
+ assert_same_elements Order.find_all_by_state(st), Order.send(st)
21
+ assert_same_elements Order.find_all_by_state(st), Order.send("find_all_#{st}")
22
+ end
23
+ end
24
+ end
25
+
31
26
  should_validate_presence_of :state, :message => default_error_message(:inclusion)
32
27
 
33
28
  context 'A fresh order' do
34
- setup do
35
- @order = Order.new
36
- end
29
+ subject { Order.new }
37
30
 
38
31
  should_allow_values_for :state, 'unpaid'
39
32
  should_not_allow_values_for :state, 'ready', 'redeemed', 'suspended', 'screwed_up',
@@ -42,9 +35,7 @@ class OrderTest < ActiveSupport::TestCase
42
35
  end
43
36
 
44
37
  context 'An unpaid order' do
45
- setup do
46
- @order = orders(:unpaid)
47
- end
38
+ subject { orders(:unpaid) }
48
39
 
49
40
  should_allow_values_for :state, 'unpaid', 'ready', 'suspended'
50
41
  should_not_allow_values_for :state, 'redeemed', 'screwed_up',
@@ -53,9 +44,7 @@ class OrderTest < ActiveSupport::TestCase
53
44
  end
54
45
 
55
46
  context 'A ready order' do
56
- setup do
57
- @order = orders(:ready)
58
- end
47
+ subject { orders(:ready) }
59
48
 
60
49
  should_allow_values_for :state, 'ready', 'redeemed', 'suspended'
61
50
  should_not_allow_values_for :state, 'unpaid', 'screwed_up',
@@ -65,9 +54,7 @@ class OrderTest < ActiveSupport::TestCase
65
54
  end
66
55
 
67
56
  context 'A redeemed order' do
68
- setup do
69
- @order = orders(:redeemed)
70
- end
57
+ subject { orders(:redeemed) }
71
58
 
72
59
  should_allow_values_for :state, 'redeemed', 'suspended'
73
60
  should_not_allow_values_for :state, 'unpaid', 'ready', 'screwed_up',
@@ -76,9 +63,7 @@ class OrderTest < ActiveSupport::TestCase
76
63
  end
77
64
 
78
65
  context 'A suspended order' do
79
- setup do
80
- @order = orders(:suspended)
81
- end
66
+ subject { orders(:suspended) }
82
67
 
83
68
  should_allow_values_for :state, 'suspended', 'redeemed', 'ready', 'unpaid'
84
69
  should_not_allow_values_for :state, 'screwed_up', :message => default_error_message(:inclusion)
@@ -87,3 +72,4 @@ class OrderTest < ActiveSupport::TestCase
87
72
  should_not_require_attributes :txref, :redeemed_at, :facility_id
88
73
  end
89
74
  end
75
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omg-statelogic
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: "1.1"
5
5
  platform: ruby
6
6
  authors:
7
7
  - Igor Gunko
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-06-23 00:00:00 -07:00
12
+ date: 2009-08-11 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -64,7 +64,8 @@ files:
64
64
  - rails/init.rb
65
65
  has_rdoc: true
66
66
  homepage: http://github.com/omg/statelogic
67
- post_install_message:
67
+ licenses:
68
+ post_install_message: v1.1 introduces changes that may (or may not) be incompatible for you. Please review them at http://github.com/omg/statelogic
68
69
  rdoc_options:
69
70
  - --line-numbers
70
71
  - --main
@@ -86,7 +87,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
86
87
  requirements: []
87
88
 
88
89
  rubyforge_project:
89
- rubygems_version: 1.2.0
90
+ rubygems_version: 1.3.5
90
91
  signing_key:
91
92
  specification_version: 2
92
93
  summary: Another state machine for ActiveRecord