acts-as-approvable 0.6.8.1 → 0.6.9

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,12 @@
1
+ == 0.6.9
2
+
3
+ * Fix generator templates using `select` instead of `select_tag`
4
+ * `reset!` to push a create approval back to a valid pending state
5
+ * Refactor Ownership setup to use a source class instead of monkey-patching
6
+ to override owner retrieval methods. Fixes an issue with rails development
7
+ mode.
8
+ * General cleanup
9
+
1
10
  == 0.6.8.1
2
11
 
3
12
  * Bad gem push...
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- acts-as-approvable (0.6.7)
4
+ acts-as-approvable (0.6.8.1)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
@@ -15,17 +15,15 @@ GEM
15
15
  binding_of_caller (0.6.7)
16
16
  builder (3.0.0)
17
17
  coderay (1.0.5)
18
- coolline (0.1.0)
19
- cucumber (1.1.0)
18
+ cucumber (1.1.9)
20
19
  builder (>= 2.1.2)
21
20
  diff-lcs (>= 1.1.2)
22
- gherkin (~> 2.5.0)
21
+ gherkin (~> 2.9.0)
23
22
  json (>= 1.4.6)
24
23
  term-ansicolor (>= 1.0.6)
25
24
  diff-lcs (1.1.3)
26
- gherkin (2.5.1)
25
+ gherkin (2.9.0)
27
26
  json (>= 1.4.6)
28
- io-console (0.3)
29
27
  json (1.6.5)
30
28
  method_source (0.7.1)
31
29
  multi_json (1.1.0)
@@ -35,9 +33,6 @@ GEM
35
33
  coderay (~> 1.0.5)
36
34
  method_source (~> 0.7.1)
37
35
  slop (>= 2.4.4, < 3)
38
- pry-coolline (0.1.1)
39
- coolline (~> 0.1.0)
40
- io-console (~> 0.3.0)
41
36
  pry-exception_explorer (0.1.9)
42
37
  pry-stack_explorer (>= 0.3.9)
43
38
  pry-nav (0.1.0)
@@ -63,7 +58,7 @@ GEM
63
58
  simplecov-html (~> 0.5.3)
64
59
  simplecov-html (0.5.3)
65
60
  slop (2.4.4)
66
- term-ansicolor (1.0.6)
61
+ term-ansicolor (1.0.7)
67
62
  timecop (0.3.5)
68
63
  yard (0.7.5)
69
64
 
@@ -77,7 +72,6 @@ DEPENDENCIES
77
72
  cucumber (~> 1.1.0)
78
73
  plymouth
79
74
  pry (~> 0.9.8.1)
80
- pry-coolline
81
75
  pry-nav (~> 0.1.0)
82
76
  pry-stack_explorer
83
77
  pry-syntax-hacks
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.6.8.1
1
+ 0.6.9
@@ -31,7 +31,6 @@ Gem::Specification.new do |s|
31
31
 
32
32
  if RUBY_VERSION =~ /^1\.9/
33
33
  s.add_development_dependency %q<simplecov>
34
- s.add_development_dependency %q<pry-coolline>
35
34
  s.add_development_dependency %q<pry-stack_explorer>
36
35
  s.add_development_dependency %q<pry-nav>, '~> 0.1.0'
37
36
  s.add_development_dependency %q<plymouth>
@@ -0,0 +1,13 @@
1
+ Feature: Reset Approvals
2
+ In order to allow reseting record creation approval for future-approval.
3
+
4
+ Background:
5
+ Given a record created with create approval
6
+ And the record is stale
7
+
8
+ Scenario: a stale record is encountered
9
+ Then it should be stale
10
+
11
+ Scenario: a stale record is reset
12
+ When I reset the record
13
+ Then it should not be stale
@@ -10,7 +10,17 @@ Given /^a record created with (create|update|any) approval$/ do |type|
10
10
  end
11
11
  end
12
12
 
13
- When /^I (approve|reject) the (record|changes?)$/ do |state, type|
13
+ Given /^the record is (stale)$/ do |state|
14
+ case state
15
+ when 'stale'
16
+ @record.title = 'changed'
17
+ sleep(1) # Save will put updated_at in a stale place
18
+ end
19
+
20
+ @record.save_without_approval!
21
+ end
22
+
23
+ When /^I (approve|reject|reset) the (record|changes?)$/ do |state, type|
14
24
  begin
15
25
  method = "#{state}!".to_sym
16
26
 
@@ -44,9 +54,17 @@ When /^I update the record with:$/ do |table|
44
54
  @update = table.rows_hash
45
55
  end
46
56
 
47
- Then /^it should be (pending|approved|rejected)$/ do |state|
57
+ Then /^it should (not )?be (pending|approved|rejected|stale)$/ do |invert, state|
48
58
  method = "#{state}?".to_sym
49
- @record.send(method).should be_true
59
+ record = state == 'stale' ? @record.approval : @record
60
+
61
+ unless invert == 'not '
62
+ record.send(method).should be_true
63
+ else
64
+ record.send(method).should be_false
65
+ end
66
+
67
+ @record.reload
50
68
  end
51
69
 
52
70
  Then /^it should have (no )?pending changes$/ do |empty|
@@ -1,7 +1,7 @@
1
1
  PATH
2
- remote: /Users/jlogsdon/Code/acts_as_approvable/acts_as_approvable
2
+ remote: /Users/jlogsdon/Code/jlogsdon.github.com/acts_as_approvable
3
3
  specs:
4
- acts-as-approvable (0.6.7)
4
+ acts-as-approvable (0.6.8.1)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
@@ -15,7 +15,6 @@ GEM
15
15
  binding_of_caller (0.6.7)
16
16
  builder (3.0.0)
17
17
  coderay (1.0.5)
18
- coolline (0.1.0)
19
18
  cucumber (1.1.0)
20
19
  builder (>= 2.1.2)
21
20
  diff-lcs (>= 1.1.2)
@@ -25,7 +24,6 @@ GEM
25
24
  diff-lcs (1.1.3)
26
25
  gherkin (2.5.1)
27
26
  json (>= 1.4.6)
28
- io-console (0.3)
29
27
  json (1.6.5)
30
28
  method_source (0.7.1)
31
29
  multi_json (1.1.0)
@@ -36,9 +34,6 @@ GEM
36
34
  coderay (~> 1.0.5)
37
35
  method_source (~> 0.7.1)
38
36
  slop (>= 2.4.4, < 3)
39
- pry-coolline (0.1.1)
40
- coolline (~> 0.1.0)
41
- io-console (~> 0.3.0)
42
37
  pry-exception_explorer (0.1.9)
43
38
  pry-stack_explorer (>= 0.3.9)
44
39
  pry-nav (0.1.0)
@@ -79,7 +74,6 @@ DEPENDENCIES
79
74
  mysql2 (~> 0.2.18)
80
75
  plymouth
81
76
  pry (~> 0.9.8.1)
82
- pry-coolline
83
77
  pry-nav (~> 0.1.0)
84
78
  pry-stack_explorer
85
79
  pry-syntax-hacks
@@ -1,7 +1,7 @@
1
1
  PATH
2
- remote: /Users/jlogsdon/Code/acts_as_approvable/acts_as_approvable
2
+ remote: /Users/jlogsdon/Code/jlogsdon.github.com/acts_as_approvable
3
3
  specs:
4
- acts-as-approvable (0.6.7)
4
+ acts-as-approvable (0.6.8.1)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
@@ -15,7 +15,6 @@ GEM
15
15
  binding_of_caller (0.6.7)
16
16
  builder (3.0.0)
17
17
  coderay (1.0.5)
18
- coolline (0.1.0)
19
18
  cucumber (1.1.0)
20
19
  builder (>= 2.1.2)
21
20
  diff-lcs (>= 1.1.2)
@@ -25,7 +24,6 @@ GEM
25
24
  diff-lcs (1.1.3)
26
25
  gherkin (2.5.1)
27
26
  json (>= 1.4.6)
28
- io-console (0.3)
29
27
  json (1.6.5)
30
28
  method_source (0.7.1)
31
29
  multi_json (1.1.0)
@@ -35,9 +33,6 @@ GEM
35
33
  coderay (~> 1.0.5)
36
34
  method_source (~> 0.7.1)
37
35
  slop (>= 2.4.4, < 3)
38
- pry-coolline (0.1.1)
39
- coolline (~> 0.1.0)
40
- io-console (~> 0.3.0)
41
36
  pry-exception_explorer (0.1.9)
42
37
  pry-stack_explorer (>= 0.3.9)
43
38
  pry-nav (0.1.0)
@@ -78,7 +73,6 @@ DEPENDENCIES
78
73
  cucumber (~> 1.1.0)
79
74
  plymouth
80
75
  pry (~> 0.9.8.1)
81
- pry-coolline
82
76
  pry-nav (~> 0.1.0)
83
77
  pry-stack_explorer
84
78
  pry-syntax-hacks
@@ -1,7 +1,7 @@
1
1
  PATH
2
- remote: /Users/jlogsdon/Code/acts_as_approvable/acts_as_approvable
2
+ remote: /Users/jlogsdon/Code/jlogsdon.github.com/acts_as_approvable
3
3
  specs:
4
- acts-as-approvable (0.6.7)
4
+ acts-as-approvable (0.6.8.1)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
@@ -34,7 +34,6 @@ GEM
34
34
  binding_of_caller (0.6.7)
35
35
  builder (2.1.2)
36
36
  coderay (1.0.5)
37
- coolline (0.1.0)
38
37
  cucumber (1.1.0)
39
38
  builder (>= 2.1.2)
40
39
  diff-lcs (>= 1.1.2)
@@ -47,7 +46,6 @@ GEM
47
46
  gherkin (2.5.1)
48
47
  json (>= 1.4.6)
49
48
  i18n (0.5.0)
50
- io-console (0.3)
51
49
  json (1.6.5)
52
50
  method_source (0.7.1)
53
51
  multi_json (1.0.4)
@@ -57,9 +55,6 @@ GEM
57
55
  coderay (~> 1.0.5)
58
56
  method_source (~> 0.7.1)
59
57
  slop (>= 2.4.4, < 3)
60
- pry-coolline (0.1.1)
61
- coolline (~> 0.1.0)
62
- io-console (~> 0.3.0)
63
58
  pry-exception_explorer (0.1.9)
64
59
  pry-stack_explorer (>= 0.3.9)
65
60
  pry-nav (0.1.0)
@@ -115,7 +110,6 @@ DEPENDENCIES
115
110
  cucumber (~> 1.1.0)
116
111
  plymouth
117
112
  pry (~> 0.9.8.1)
118
- pry-coolline
119
113
  pry-nav (~> 0.1.0)
120
114
  pry-stack_explorer
121
115
  pry-syntax-hacks
@@ -1,7 +1,7 @@
1
1
  PATH
2
- remote: /Users/jlogsdon/Code/acts_as_approvable/acts_as_approvable
2
+ remote: /Users/jlogsdon/Code/jlogsdon.github.com/acts_as_approvable
3
3
  specs:
4
- acts-as-approvable (0.6.7)
4
+ acts-as-approvable (0.6.8.1)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
@@ -35,7 +35,6 @@ GEM
35
35
  binding_of_caller (0.6.7)
36
36
  builder (3.0.0)
37
37
  coderay (1.0.5)
38
- coolline (0.1.0)
39
38
  cucumber (1.1.0)
40
39
  builder (>= 2.1.2)
41
40
  diff-lcs (>= 1.1.2)
@@ -48,7 +47,6 @@ GEM
48
47
  json (>= 1.4.6)
49
48
  hike (1.2.1)
50
49
  i18n (0.6.0)
51
- io-console (0.3)
52
50
  json (1.6.5)
53
51
  method_source (0.7.1)
54
52
  multi_json (1.0.4)
@@ -58,9 +56,6 @@ GEM
58
56
  coderay (~> 1.0.5)
59
57
  method_source (~> 0.7.1)
60
58
  slop (>= 2.4.4, < 3)
61
- pry-coolline (0.1.1)
62
- coolline (~> 0.1.0)
63
- io-console (~> 0.3.0)
64
59
  pry-exception_explorer (0.1.9)
65
60
  pry-stack_explorer (>= 0.3.9)
66
61
  pry-nav (0.1.0)
@@ -126,7 +121,6 @@ DEPENDENCIES
126
121
  cucumber (~> 1.1.0)
127
122
  plymouth
128
123
  pry (~> 0.9.8.1)
129
- pry-coolline
130
124
  pry-nav (~> 0.1.0)
131
125
  pry-stack_explorer
132
126
  pry-syntax-hacks
@@ -67,13 +67,8 @@ class ApprovalsController < <%= options[:base] %>
67
67
  def setup_conditions
68
68
  @conditions ||= {}
69
69
 
70
- <% if owner? %> if params[:owner_id]
71
- @conditions[:owner_id] = params[:owner_id]
72
- @conditions[:owner_id] = nil if params[:owner_id] == 0
73
- end
74
- <% end %> if params[:item_type]
75
- @conditions[:item_type] = params[:item_type]
76
- end
70
+ <% if owner? %> @conditions[:owner_id] = params[:owner_id] if params[:owner_id].present?
71
+ <% end %> @conditions[:item_type] = params[:item_type] if params[:item_type].present?
77
72
  end
78
73
 
79
74
  # Check for the selected models partial, use the generic one if it doesn't exist
@@ -2,13 +2,13 @@
2
2
 
3
3
  <%% form_for(:approval, :url => approvals_path, :html => {:method => :get}) do |f| %>
4
4
  <%% unless @conditions[:state].is_a?(Array) # History page shouldn't allow selecting different states %>
5
- <%%= f.label(:state) %>
6
- <%%= f.select(:state, options_for_select(Approval.options_for_state, @conditions[:state])) %>
5
+ <%%= label_tag(:state) %>
6
+ <%%= select_tag(:state, options_for_select(Approval.options_for_state, @conditions[:state])) %>
7
7
  <%% end %>
8
- <% if owner? %> <%%= f.label(:owner_id) %>
9
- <%%= f.select(:owner_id, options_for_select(Approval.options_for_assigned_owners, @conditions[:owner_id]), :prompt => 'All Users') %>
10
- <% end %> <%%= f.label(:item_type) %>
11
- <%%= f.select(:item_type, options_for_select(Approval.options_for_type, @conditions[:item_type]), :prompt => 'All Types') %>
8
+ <% if owner? %> <%%= label_tag(:owner_id) %>
9
+ <%%= select_tag(:owner_id, options_for_select(Approval.options_for_assigned_owners, @conditions[:owner_id]), :prompt => 'All Users') %>
10
+ <% end %> <%%= label_tag(:item_type) %>
11
+ <%%= select_tag(:item_type, options_for_select(Approval.options_for_type, @conditions[:item_type]), :prompt => 'All Types') %>
12
12
  <%%= f.submit('Filter') %>
13
13
  <%% end %>
14
14
 
@@ -5,7 +5,7 @@
5
5
  = label_tag('state', 'State')
6
6
  = select_tag('state', options_for_select(Approval.options_for_state, @conditions[:state]))
7
7
  <% if owner? %> = label_tag('owner_id', 'Owner')
8
- = select('owner_id', options_for_select(Approval.options_for_assigned_owners(true), @conditions[:owner_id]))
8
+ = select_tag('owner_id', options_for_select(Approval.options_for_assigned_owners(true), @conditions[:owner_id]))
9
9
  <% end %> = label_tag('item_type', 'Type')
10
10
  = select_tag('item_type', options_for_select(Approval.options_for_type(true), @conditions[:item_type]))
11
11
  %button{:type => 'Submit'} Filter
@@ -52,6 +52,22 @@ module ActsAsApprovable
52
52
  @owner_class
53
53
  end
54
54
 
55
+ ##
56
+ # Set the class used for overriding Ownership retrieval
57
+ #
58
+ # @see Ownership
59
+ def self.owner_source=(source)
60
+ @owner_source = source
61
+ end
62
+
63
+ ##
64
+ # Get the class used for overriding Ownership retrieval
65
+ #
66
+ # @see Ownership
67
+ def self.owner_source
68
+ @owner_source
69
+ end
70
+
55
71
  ##
56
72
  # Set the engine used for rendering view files.
57
73
  def self.view_language=(lang)
@@ -106,7 +106,7 @@ class Approval < ActiveRecord::Base
106
106
  # Returns true if the affected item has been updated since this approval was
107
107
  # created.
108
108
  def stale?
109
- unlocked? and item.has_attribute?(:updated_at) and created_at < item.updated_at
109
+ unlocked? and item.has_attribute?(:updated_at) and updated_at < item.updated_at
110
110
  end
111
111
 
112
112
  ##
@@ -164,15 +164,27 @@ class Approval < ActiveRecord::Base
164
164
  raise ActsAsApprovable::Error::Locked if locked?
165
165
  return unless run_item_callback(:before_reject)
166
166
 
167
- if create?
168
- item.set_approval_state('rejected')
169
- end
167
+ item.set_approval_state('rejected') if create?
170
168
 
171
169
  item.save_without_approval!
172
170
  update_attributes!(:state => 'rejected', :reason => reason)
173
171
  run_item_callback(:after_reject)
174
172
  end
175
173
 
174
+ ##
175
+ # Force the approval back into a 'pending' state. Only valid for :create events.
176
+ #
177
+ # @raise [ActsAsApprovable::Error::InvalidTransition] raised if the event is not {#create? :create}.
178
+ def reset!
179
+ raise ActsAsApprovable::Error::InvalidTransition.new(state, 'pending', self) unless create?
180
+
181
+ item.set_approval_state('pending')
182
+ item.save_without_approval!
183
+
184
+ state_will_change! # Force an update to the record
185
+ update_attributes!(:state => 'rejected')
186
+ end
187
+
176
188
  private
177
189
  def run_item_callback(callback)
178
190
  item.send(callback, self) != false
@@ -4,8 +4,7 @@ module ActsAsApprovable
4
4
  # Raised when a locked approval is accepted or rejected.
5
5
  class Locked < ActsAsApprovable::Error
6
6
  def initialize(*args)
7
- args[0] = 'this approval is locked'
8
- super(*args)
7
+ super('this approval is locked')
9
8
  end
10
9
  end
11
10
 
@@ -13,8 +12,7 @@ module ActsAsApprovable
13
12
  # Raised when a stale approval is accepted.
14
13
  class Stale < ActsAsApprovable::Error
15
14
  def initialize(*args)
16
- args[0] = 'this approval is stale and should not be approved'
17
- super(*args)
15
+ super('this approval is stale and should not be approved')
18
16
  end
19
17
  end
20
18
 
@@ -23,8 +21,13 @@ module ActsAsApprovable
23
21
  # {ActsAsApprovable::Ownership::ClassMethods#available_owners}.
24
22
  class InvalidOwner < ActsAsApprovable::Error
25
23
  def initialize(*args)
26
- args[0] = 'this record cannot be assigned as an owner'
27
- super(*args)
24
+ super('this record cannot be assigned as an owner')
25
+ end
26
+ end
27
+
28
+ class InvalidTransition < ActsAsApprovable::Error
29
+ def initialize(from, to, approval)
30
+ super("you may not transition from #{from} to #{to} in a #{approval.event} approval")
28
31
  end
29
32
  end
30
33
  end
@@ -69,6 +69,11 @@ module ActsAsApprovable
69
69
  approval.reject!
70
70
  end
71
71
 
72
+ def reset!
73
+ return unless approvable_on?(:create) && approval.present?
74
+ approval.reset!
75
+ end
76
+
72
77
  private
73
78
  def approvable_create?
74
79
  approvals_enabled? and approvable_on?(:create)
@@ -15,8 +15,9 @@ module ActsAsApprovable
15
15
  # allowing you to override functionality on the fly.
16
16
  #
17
17
  # @param [Hash] options a hash of options for configuration
18
- # @option options [Object] :model the model being used for Approval records (defaults to `Approval`).
19
- # @option options [Object] :owner the model being used for owner records (defaults to `User`).
18
+ # @option options [Object] :model the model being used for Approval records (defaults to `Approval`).
19
+ # @option options [Object] :owner the model being used for owner records (defaults to `User`).
20
+ # @option options [Object] :source class used to override retrieval of owner records.
20
21
  def self.configure(options = {}, &block)
21
22
  approval = options.delete(:model) { Approval }
22
23
  owner = options.delete(:owner) { User }
@@ -24,9 +25,9 @@ module ActsAsApprovable
24
25
  approval.send(:include, self)
25
26
 
26
27
  ActsAsApprovable.owner_class = owner
27
- approval.send(:belongs_to, :owner, :class_name => owner.to_s, :foreign_key => :owner_id)
28
+ ActsAsApprovable.owner_source = options.delete(:source)
28
29
 
29
- approval.class_exec(&block) if block
30
+ approval.send(:belongs_to, :owner, :class_name => owner.to_s, :foreign_key => :owner_id)
30
31
  end
31
32
 
32
33
  def self.included(base)
@@ -69,11 +70,30 @@ module ActsAsApprovable
69
70
  end
70
71
 
71
72
  ##
72
- # A list of records that can be assigned to an approval. This should be
73
- # overridden in {ActsAsApprovable::Ownership.configure} to return only the
74
- # records you wish to manage approvals.
73
+ # Source class used to override Owner retrieval methods
74
+ #
75
+ # @see ActsAsApprovable::Ownership.configure
76
+ def owner_source
77
+ ActsAsApprovable.owner_source
78
+ end
79
+
80
+ ##
81
+ # Attempt to run a method on the configured #owner_source class. If it does
82
+ # not exist yield to the given block.
83
+ def with_owner_source(method, *args)
84
+ if owner_source && owner_source.singleton_class.method_defined?(method)
85
+ owner_source.send(method, *args)
86
+ else
87
+ yield
88
+ end
89
+ end
90
+
91
+ ##
92
+ # A list of records that can be assigned to an approval.
93
+ #
94
+ # This method can be overriden by the configured #owner_source.
75
95
  def available_owners
76
- owner_class.all
96
+ with_owner_source(:available_owners) { owner_class.all }
77
97
  end
78
98
 
79
99
  ##
@@ -89,8 +109,10 @@ module ActsAsApprovable
89
109
 
90
110
  ##
91
111
  # A list of owners that have assigned approvals.
112
+ #
113
+ # This method can be overriden by the configured #owner_source.
92
114
  def assigned_owners
93
- all(:select => 'DISTINCT(owner_id)', :conditions => 'owner_id IS NOT NULL', :include => :owner).map(&:owner)
115
+ with_owner_source(:assigned_owners) { all(:select => 'DISTINCT(owner_id)', :conditions => 'owner_id IS NOT NULL', :include => :owner).map(&:owner) }
94
116
  end
95
117
 
96
118
  ##
@@ -108,9 +130,11 @@ module ActsAsApprovable
108
130
  # Helper method that takes an owner record and returns an array for Rails'
109
131
  # `#options_for_select`.
110
132
  #
133
+ # This method can be overriden by the configured #owner_source.
134
+ #
111
135
  # @return [Array] a 2-index array with a display string and value.
112
136
  def option_for_owner(owner)
113
- [owner.to_str, owner.id]
137
+ with_owner_source(:option_for_owner, owner) { [owner.to_str, owner.id] }
114
138
  end
115
139
  end
116
140
  end
@@ -67,13 +67,8 @@ class ApprovalsController < <%= options[:base] %>
67
67
  def setup_conditions
68
68
  @conditions ||= {}
69
69
 
70
- <% if owner? %> if params[:owner_id]
71
- @conditions[:owner_id] = params[:owner_id]
72
- @conditions[:owner_id] = nil if params[:owner_id] == 0
73
- end
74
- <% end %> if params[:item_type]
75
- @conditions[:item_type] = params[:item_type]
76
- end
70
+ <% if owner? %> @conditions[:owner_id] = params[:owner_id] if params[:owner_id].present?
71
+ <% end %> @conditions[:item_type] = params[:item_type] if params[:item_type].present?
77
72
  end
78
73
 
79
74
  # Check for the selected models partial, use the generic one if it doesn't exist
@@ -2,13 +2,13 @@
2
2
 
3
3
  <%% form_for(:approval, :url => approvals_path, :html => {:method => :get}) do |f| %>
4
4
  <%% unless @conditions[:state].is_a?(Array) # History page shouldn't allow selecting different states %>
5
- <%%= f.label(:state) %>
6
- <%%= f.select(:state, options_for_select(Approval.options_for_state, @conditions[:state])) %>
5
+ <%%= label_tag(:state) %>
6
+ <%%= select_tag(:state, options_for_select(Approval.options_for_state, @conditions[:state])) %>
7
7
  <%% end %>
8
- <% if owner? %> <%%= f.label(:owner_id) %>
9
- <%%= f.select(:owner_id, options_for_select(Approval.options_for_assigned_owners, @conditions[:owner_id]), :prompt => 'All Users') %>
10
- <% end %> <%%= f.label(:item_type) %>
11
- <%%= f.select(:item_type, options_for_select(Approval.options_for_type, @conditions[:item_type]), :prompt => 'All Types') %>
8
+ <% if owner? %> <%%= label_tag(:owner_id) %>
9
+ <%%= select_tag(:owner_id, options_for_select(Approval.options_for_assigned_owners, @conditions[:owner_id]), :prompt => 'All Users') %>
10
+ <% end %> <%%= label_tag(:item_type) %>
11
+ <%%= select_tag(:item_type, options_for_select(Approval.options_for_type, @conditions[:item_type]), :prompt => 'All Types') %>
12
12
  <%%= f.submit('Filter') %>
13
13
  <%% end %>
14
14
 
@@ -5,7 +5,7 @@
5
5
  = label_tag('state', 'State')
6
6
  = select_tag('state', options_for_select(Approval.options_for_state, @conditions[:state]))
7
7
  <% if owner? %> = label_tag('owner_id', 'Owner')
8
- = select('owner_id', options_for_select(Approval.options_for_assigned_owners(true), @conditions[:owner_id]))
8
+ = select_tag('owner_id', options_for_select(Approval.options_for_assigned_owners(true), @conditions[:owner_id]))
9
9
  <% end %> = label_tag('item_type', 'Type')
10
10
  = select_tag('item_type', options_for_select(Approval.options_for_type(true), @conditions[:item_type]))
11
11
  %button{:type => 'Submit'} Filter
@@ -181,6 +181,12 @@ describe Approval do
181
181
 
182
182
  it { should be_update }
183
183
  it { should_not be_create }
184
+
185
+ describe '#reset!' do
186
+ it 'should raise an InvalidTransition error' do
187
+ expect { subject.reset! }.to raise_error(ActsAsApprovable::Error::InvalidTransition)
188
+ end
189
+ end
184
190
  end
185
191
 
186
192
  context 'when the event is :create' do
@@ -190,12 +196,24 @@ describe Approval do
190
196
 
191
197
  it { should_not be_update }
192
198
  it { should be_create }
199
+
200
+ describe '#reset!' do
201
+ it 'should not raise an InvalidTransition error' do
202
+ expect { subject.reset! }.not_to raise_error(ActsAsApprovable::Error::InvalidTransition)
203
+ end
204
+
205
+ it 'should save even if no values change' do
206
+ subject.stub(:item => DefaultApprovable.new)
207
+ subject.should_receive(:save!).and_return(true)
208
+ subject.reset!
209
+ end
210
+ end
193
211
  end
194
212
 
195
213
  context 'when the approval is unlocked' do
196
214
  before(:each) do
197
215
  @item = DefaultApprovable.without_approval { |m| m.create }
198
- subject.stub(:locked? => false, :created_at => Time.now, :item => @item)
216
+ subject.stub(:locked? => false, :updated_at => Time.now, :item => @item)
199
217
  @item.stub(:updated_at => Time.now)
200
218
  end
201
219
 
@@ -222,9 +240,25 @@ describe Approval do
222
240
  end
223
241
  end
224
242
 
243
+ describe '#reset!' do
244
+ before(:each) do
245
+ subject.stub(:event => 'create')
246
+ end
247
+
248
+ it 'saves the approval record' do
249
+ subject.should_receive(:save!).and_return(true)
250
+ subject.reset!
251
+ end
252
+
253
+ it 'changes the item state' do
254
+ @item.should_receive(:set_approval_state).with('pending')
255
+ subject.reset!
256
+ end
257
+ end
258
+
225
259
  context 'when the approval is newer than the last update' do
226
260
  before(:each) do
227
- subject.stub(:created_at => @item.updated_at + 60)
261
+ subject.stub(:updated_at => @item.updated_at + 60)
228
262
  end
229
263
 
230
264
  it { should_not be_stale }
@@ -233,7 +267,7 @@ describe Approval do
233
267
 
234
268
  context 'when the approval is older than the last update' do
235
269
  before(:each) do
236
- subject.stub(:created_at => @item.updated_at - 60)
270
+ subject.stub(:updated_at => @item.updated_at - 60)
237
271
  end
238
272
 
239
273
  it { should be_stale }
@@ -145,5 +145,25 @@ describe ActsAsApprovable::Model::CreateInstanceMethods do
145
145
  subject.reject!
146
146
  end
147
147
  end
148
+
149
+ describe '#reset!' do
150
+ it 'proxies to the approval record for approval' do
151
+ subject.should_receive(:approval)
152
+ subject.reset!
153
+ end
154
+
155
+ context 'when the approval is stale' do
156
+ before(:each) do
157
+ subject.approval.class.record_timestamps = false
158
+ subject.approval.update_attribute(:updated_at, subject.approval.updated_at - 1)
159
+ subject.approval.class.record_timestamps = true
160
+ end
161
+
162
+ it 'puts the approval back to fresh' do
163
+ subject.reset!
164
+ subject.approval.should be_fresh
165
+ end
166
+ end
167
+ end
148
168
  end
149
169
  end
@@ -19,11 +19,30 @@ describe ActsAsApprovable::Ownership::ClassMethods do
19
19
  end
20
20
  end
21
21
 
22
+ describe '.owner_source' do
23
+ it 'proxies to ActsAsApprovable' do
24
+ ActsAsApprovable.should_receive(:owner_source)
25
+ subject.owner_source
26
+ end
27
+ end
28
+
22
29
  describe '.available_owners' do
23
30
  it 'selects all records from #owner_class' do
24
31
  subject.available_owners.should include(@user1)
25
32
  subject.available_owners.should include(@user2)
26
33
  end
34
+
35
+ context 'when an owner source is configured' do
36
+ before(:each) do
37
+ class FakeSource; end
38
+ ActsAsApprovable.owner_source = FakeSource
39
+ end
40
+
41
+ it 'proxies to the configured source' do
42
+ FakeSource.should_receive(:available_owners)
43
+ subject.available_owners
44
+ end
45
+ end
27
46
  end
28
47
 
29
48
  describe '.options_for_available_owners' do
@@ -51,6 +70,20 @@ describe ActsAsApprovable::Ownership::ClassMethods do
51
70
  end
52
71
  end
53
72
 
73
+ context 'when an owner source is configured' do
74
+ before(:each) do
75
+ class FakeSource; end
76
+ ActsAsApprovable.owner_source = FakeSource
77
+ end
78
+
79
+ describe '.assigned_owners' do
80
+ it 'proxies to the configured source' do
81
+ FakeSource.should_receive(:assigned_owners)
82
+ subject.assigned_owners
83
+ end
84
+ end
85
+ end
86
+
54
87
  context 'when no users are assigned' do
55
88
  describe '.assigned_owners' do
56
89
  it 'should be empty' do
@@ -29,9 +29,10 @@ describe ActsAsApprovable::Ownership do
29
29
  subject.configure(:owner => FakeUser)
30
30
  end
31
31
 
32
- it 'applies the provided block' do
33
- Approval.should_receive(:class_exec)
34
- subject.configure {}
32
+ it 'uses the given :source' do
33
+ class FakeSource; end
34
+ ActsAsApprovable.should_receive(:owner_source=).with(FakeSource)
35
+ subject.configure(:source => FakeSource)
35
36
  end
36
37
  end
37
38
 
data/spec/spec_helper.rb CHANGED
@@ -19,7 +19,7 @@ require 'active_record'
19
19
  begin
20
20
  require 'plymouth'
21
21
  rescue LoadError
22
- end
22
+ end if ENV['PRYABLE']
23
23
 
24
24
  require File.expand_path('../lib/acts-as-approvable', File.dirname(__FILE__))
25
25
 
@@ -24,7 +24,10 @@ module Support
24
24
  end
25
25
 
26
26
  if db_adapter.nil?
27
- raise 'No DB Adapter selected. Pass the DB= option to pick one, or install Sqlite or Sqlite3.'
27
+ puts
28
+ puts
29
+ puts "You must run tests using one of the available appraisals. `bundle exec rake -T` to list, `bundle exec rake appraisal:rails31` to run against Rails 3.1 and SQLite."
30
+ exit
28
31
  end
29
32
 
30
33
  ActiveRecord::Base.establish_connection(config[db_adapter])
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts-as-approvable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.8.1
4
+ version: 0.6.9
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -15,7 +15,7 @@ date: 2012-02-14 00:00:00.000000000Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: activerecord
18
- requirement: &70189871219020 !ruby/object:Gem::Requirement
18
+ requirement: &70273856448700 !ruby/object:Gem::Requirement
19
19
  none: false
20
20
  requirements:
21
21
  - - ~>
@@ -23,10 +23,10 @@ dependencies:
23
23
  version: 2.3.14
24
24
  type: :development
25
25
  prerelease: false
26
- version_requirements: *70189871219020
26
+ version_requirements: *70273856448700
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: appraisal
29
- requirement: &70189871218380 !ruby/object:Gem::Requirement
29
+ requirement: &70273856524460 !ruby/object:Gem::Requirement
30
30
  none: false
31
31
  requirements:
32
32
  - - ~>
@@ -34,10 +34,10 @@ dependencies:
34
34
  version: 0.4.1
35
35
  type: :development
36
36
  prerelease: false
37
- version_requirements: *70189871218380
37
+ version_requirements: *70273856524460
38
38
  - !ruby/object:Gem::Dependency
39
39
  name: redcarpet
40
- requirement: &70189871217740 !ruby/object:Gem::Requirement
40
+ requirement: &70273856571200 !ruby/object:Gem::Requirement
41
41
  none: false
42
42
  requirements:
43
43
  - - ~>
@@ -45,10 +45,10 @@ dependencies:
45
45
  version: 2.1.0
46
46
  type: :development
47
47
  prerelease: false
48
- version_requirements: *70189871217740
48
+ version_requirements: *70273856571200
49
49
  - !ruby/object:Gem::Dependency
50
50
  name: shoulda
51
- requirement: &70189871217020 !ruby/object:Gem::Requirement
51
+ requirement: &70273856581720 !ruby/object:Gem::Requirement
52
52
  none: false
53
53
  requirements:
54
54
  - - ~>
@@ -56,10 +56,10 @@ dependencies:
56
56
  version: '2.0'
57
57
  type: :development
58
58
  prerelease: false
59
- version_requirements: *70189871217020
59
+ version_requirements: *70273856581720
60
60
  - !ruby/object:Gem::Dependency
61
61
  name: rspec
62
- requirement: &70189871152460 !ruby/object:Gem::Requirement
62
+ requirement: &70273856589600 !ruby/object:Gem::Requirement
63
63
  none: false
64
64
  requirements:
65
65
  - - ~>
@@ -67,10 +67,10 @@ dependencies:
67
67
  version: 2.8.0
68
68
  type: :development
69
69
  prerelease: false
70
- version_requirements: *70189871152460
70
+ version_requirements: *70273856589600
71
71
  - !ruby/object:Gem::Dependency
72
72
  name: timecop
73
- requirement: &70189871151700 !ruby/object:Gem::Requirement
73
+ requirement: &70273856676420 !ruby/object:Gem::Requirement
74
74
  none: false
75
75
  requirements:
76
76
  - - ~>
@@ -78,10 +78,10 @@ dependencies:
78
78
  version: 0.3.5
79
79
  type: :development
80
80
  prerelease: false
81
- version_requirements: *70189871151700
81
+ version_requirements: *70273856676420
82
82
  - !ruby/object:Gem::Dependency
83
83
  name: cucumber
84
- requirement: &70189871151120 !ruby/object:Gem::Requirement
84
+ requirement: &70273856899940 !ruby/object:Gem::Requirement
85
85
  none: false
86
86
  requirements:
87
87
  - - ~>
@@ -89,10 +89,10 @@ dependencies:
89
89
  version: 1.1.0
90
90
  type: :development
91
91
  prerelease: false
92
- version_requirements: *70189871151120
92
+ version_requirements: *70273856899940
93
93
  - !ruby/object:Gem::Dependency
94
94
  name: rake
95
- requirement: &70189871150360 !ruby/object:Gem::Requirement
95
+ requirement: &70273865174320 !ruby/object:Gem::Requirement
96
96
  none: false
97
97
  requirements:
98
98
  - - ~>
@@ -100,10 +100,10 @@ dependencies:
100
100
  version: 0.9.2
101
101
  type: :development
102
102
  prerelease: false
103
- version_requirements: *70189871150360
103
+ version_requirements: *70273865174320
104
104
  - !ruby/object:Gem::Dependency
105
105
  name: yard
106
- requirement: &70189871149940 !ruby/object:Gem::Requirement
106
+ requirement: &70273865539380 !ruby/object:Gem::Requirement
107
107
  none: false
108
108
  requirements:
109
109
  - - ! '>='
@@ -111,10 +111,10 @@ dependencies:
111
111
  version: '0'
112
112
  type: :development
113
113
  prerelease: false
114
- version_requirements: *70189871149940
114
+ version_requirements: *70273865539380
115
115
  - !ruby/object:Gem::Dependency
116
116
  name: pry
117
- requirement: &70189871149320 !ruby/object:Gem::Requirement
117
+ requirement: &70273865678380 !ruby/object:Gem::Requirement
118
118
  none: false
119
119
  requirements:
120
120
  - - ~>
@@ -122,10 +122,10 @@ dependencies:
122
122
  version: 0.9.8.1
123
123
  type: :development
124
124
  prerelease: false
125
- version_requirements: *70189871149320
125
+ version_requirements: *70273865678380
126
126
  - !ruby/object:Gem::Dependency
127
127
  name: pry-syntax-hacks
128
- requirement: &70189871148820 !ruby/object:Gem::Requirement
128
+ requirement: &70273865753300 !ruby/object:Gem::Requirement
129
129
  none: false
130
130
  requirements:
131
131
  - - ! '>='
@@ -133,10 +133,10 @@ dependencies:
133
133
  version: '0'
134
134
  type: :development
135
135
  prerelease: false
136
- version_requirements: *70189871148820
136
+ version_requirements: *70273865753300
137
137
  - !ruby/object:Gem::Dependency
138
138
  name: simplecov
139
- requirement: &70189871148180 !ruby/object:Gem::Requirement
139
+ requirement: &70273866035260 !ruby/object:Gem::Requirement
140
140
  none: false
141
141
  requirements:
142
142
  - - ! '>='
@@ -144,21 +144,10 @@ dependencies:
144
144
  version: '0'
145
145
  type: :development
146
146
  prerelease: false
147
- version_requirements: *70189871148180
148
- - !ruby/object:Gem::Dependency
149
- name: pry-coolline
150
- requirement: &70189871147640 !ruby/object:Gem::Requirement
151
- none: false
152
- requirements:
153
- - - ! '>='
154
- - !ruby/object:Gem::Version
155
- version: '0'
156
- type: :development
157
- prerelease: false
158
- version_requirements: *70189871147640
147
+ version_requirements: *70273866035260
159
148
  - !ruby/object:Gem::Dependency
160
149
  name: pry-stack_explorer
161
- requirement: &70189871147080 !ruby/object:Gem::Requirement
150
+ requirement: &70273866221340 !ruby/object:Gem::Requirement
162
151
  none: false
163
152
  requirements:
164
153
  - - ! '>='
@@ -166,10 +155,10 @@ dependencies:
166
155
  version: '0'
167
156
  type: :development
168
157
  prerelease: false
169
- version_requirements: *70189871147080
158
+ version_requirements: *70273866221340
170
159
  - !ruby/object:Gem::Dependency
171
160
  name: pry-nav
172
- requirement: &70189871146340 !ruby/object:Gem::Requirement
161
+ requirement: &70273866220740 !ruby/object:Gem::Requirement
173
162
  none: false
174
163
  requirements:
175
164
  - - ~>
@@ -177,10 +166,10 @@ dependencies:
177
166
  version: 0.1.0
178
167
  type: :development
179
168
  prerelease: false
180
- version_requirements: *70189871146340
169
+ version_requirements: *70273866220740
181
170
  - !ruby/object:Gem::Dependency
182
171
  name: plymouth
183
- requirement: &70189871145480 !ruby/object:Gem::Requirement
172
+ requirement: &70273866220160 !ruby/object:Gem::Requirement
184
173
  none: false
185
174
  requirements:
186
175
  - - ! '>='
@@ -188,7 +177,7 @@ dependencies:
188
177
  version: '0'
189
178
  type: :development
190
179
  prerelease: false
191
- version_requirements: *70189871145480
180
+ version_requirements: *70273866220160
192
181
  description: Generic approval queues for record creation and updates
193
182
  email: dwarf@girsbrain.org
194
183
  executables: []
@@ -208,6 +197,7 @@ files:
208
197
  - VERSION
209
198
  - acts-as-approvable.gemspec
210
199
  - features/create_approval.feature
200
+ - features/reset_approval.feature
211
201
  - features/step_definitions/cucumber_steps.rb
212
202
  - features/support/env.rb
213
203
  - features/support/large.txt
@@ -308,6 +298,7 @@ specification_version: 3
308
298
  summary: Generic approval queues for record creation and updates
309
299
  test_files:
310
300
  - features/create_approval.feature
301
+ - features/reset_approval.feature
311
302
  - features/step_definitions/cucumber_steps.rb
312
303
  - features/support/env.rb
313
304
  - features/support/large.txt