acts-as-approvable 0.6.8.1 → 0.6.9

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/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