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 +9 -0
- data/Gemfile.lock +5 -11
- data/VERSION +1 -1
- data/acts-as-approvable.gemspec +0 -1
- data/features/reset_approval.feature +13 -0
- data/features/step_definitions/cucumber_steps.rb +21 -3
- data/gemfiles/mysql2.gemfile.lock +2 -8
- data/gemfiles/rails2.gemfile.lock +2 -8
- data/gemfiles/rails30.gemfile.lock +2 -8
- data/gemfiles/rails31.gemfile.lock +2 -8
- data/generators/acts_as_approvable/templates/approvals_controller.rb +2 -7
- data/generators/acts_as_approvable/templates/views/erb/index.html.erb +6 -6
- data/generators/acts_as_approvable/templates/views/haml/index.html.haml +1 -1
- data/lib/acts-as-approvable.rb +16 -0
- data/lib/acts_as_approvable/approval.rb +16 -4
- data/lib/acts_as_approvable/error.rb +9 -6
- data/lib/acts_as_approvable/model/create_instance_methods.rb +5 -0
- data/lib/acts_as_approvable/ownership.rb +34 -10
- data/lib/generators/acts_as_approvable/templates/approvals_controller.rb +2 -7
- data/lib/generators/erb/templates/index.html.erb +6 -6
- data/lib/generators/haml/templates/index.html.haml +1 -1
- data/spec/acts_as_approvable/approval_spec.rb +37 -3
- data/spec/acts_as_approvable/model/create_instance_methods_spec.rb +20 -0
- data/spec/acts_as_approvable/ownership/class_methods_spec.rb +33 -0
- data/spec/acts_as_approvable/ownership_spec.rb +4 -3
- data/spec/spec_helper.rb +1 -1
- data/spec/support/database.rb +4 -1
- metadata +33 -42
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.
|
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
|
-
|
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.
|
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.
|
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.
|
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.
|
1
|
+
0.6.9
|
data/acts-as-approvable.gemspec
CHANGED
@@ -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
|
-
|
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.
|
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/
|
2
|
+
remote: /Users/jlogsdon/Code/jlogsdon.github.com/acts_as_approvable
|
3
3
|
specs:
|
4
|
-
acts-as-approvable (0.6.
|
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/
|
2
|
+
remote: /Users/jlogsdon/Code/jlogsdon.github.com/acts_as_approvable
|
3
3
|
specs:
|
4
|
-
acts-as-approvable (0.6.
|
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/
|
2
|
+
remote: /Users/jlogsdon/Code/jlogsdon.github.com/acts_as_approvable
|
3
3
|
specs:
|
4
|
-
acts-as-approvable (0.6.
|
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/
|
2
|
+
remote: /Users/jlogsdon/Code/jlogsdon.github.com/acts_as_approvable
|
3
3
|
specs:
|
4
|
-
acts-as-approvable (0.6.
|
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
|
-
|
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
|
-
<%%=
|
6
|
-
<%%=
|
5
|
+
<%%= label_tag(:state) %>
|
6
|
+
<%%= select_tag(:state, options_for_select(Approval.options_for_state, @conditions[:state])) %>
|
7
7
|
<%% end %>
|
8
|
-
<% if owner? %> <%%=
|
9
|
-
<%%=
|
10
|
-
<% end %> <%%=
|
11
|
-
<%%=
|
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
|
-
=
|
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
|
data/lib/acts-as-approvable.rb
CHANGED
@@ -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
|
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
|
-
|
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
|
-
|
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
|
-
|
27
|
-
|
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
|
@@ -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
|
19
|
-
# @option options [Object] :owner
|
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
|
-
|
28
|
+
ActsAsApprovable.owner_source = options.delete(:source)
|
28
29
|
|
29
|
-
approval.
|
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
|
-
#
|
73
|
-
#
|
74
|
-
#
|
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
|
-
|
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
|
-
<%%=
|
6
|
-
<%%=
|
5
|
+
<%%= label_tag(:state) %>
|
6
|
+
<%%= select_tag(:state, options_for_select(Approval.options_for_state, @conditions[:state])) %>
|
7
7
|
<%% end %>
|
8
|
-
<% if owner? %> <%%=
|
9
|
-
<%%=
|
10
|
-
<% end %> <%%=
|
11
|
-
<%%=
|
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
|
-
=
|
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, :
|
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(:
|
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(:
|
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 '
|
33
|
-
|
34
|
-
|
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
data/spec/support/database.rb
CHANGED
@@ -24,7 +24,10 @@ module Support
|
|
24
24
|
end
|
25
25
|
|
26
26
|
if db_adapter.nil?
|
27
|
-
|
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.
|
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: &
|
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: *
|
26
|
+
version_requirements: *70273856448700
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: appraisal
|
29
|
-
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: *
|
37
|
+
version_requirements: *70273856524460
|
38
38
|
- !ruby/object:Gem::Dependency
|
39
39
|
name: redcarpet
|
40
|
-
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: *
|
48
|
+
version_requirements: *70273856571200
|
49
49
|
- !ruby/object:Gem::Dependency
|
50
50
|
name: shoulda
|
51
|
-
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: *
|
59
|
+
version_requirements: *70273856581720
|
60
60
|
- !ruby/object:Gem::Dependency
|
61
61
|
name: rspec
|
62
|
-
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: *
|
70
|
+
version_requirements: *70273856589600
|
71
71
|
- !ruby/object:Gem::Dependency
|
72
72
|
name: timecop
|
73
|
-
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: *
|
81
|
+
version_requirements: *70273856676420
|
82
82
|
- !ruby/object:Gem::Dependency
|
83
83
|
name: cucumber
|
84
|
-
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: *
|
92
|
+
version_requirements: *70273856899940
|
93
93
|
- !ruby/object:Gem::Dependency
|
94
94
|
name: rake
|
95
|
-
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: *
|
103
|
+
version_requirements: *70273865174320
|
104
104
|
- !ruby/object:Gem::Dependency
|
105
105
|
name: yard
|
106
|
-
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: *
|
114
|
+
version_requirements: *70273865539380
|
115
115
|
- !ruby/object:Gem::Dependency
|
116
116
|
name: pry
|
117
|
-
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: *
|
125
|
+
version_requirements: *70273865678380
|
126
126
|
- !ruby/object:Gem::Dependency
|
127
127
|
name: pry-syntax-hacks
|
128
|
-
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: *
|
136
|
+
version_requirements: *70273865753300
|
137
137
|
- !ruby/object:Gem::Dependency
|
138
138
|
name: simplecov
|
139
|
-
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: *
|
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: &
|
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: *
|
158
|
+
version_requirements: *70273866221340
|
170
159
|
- !ruby/object:Gem::Dependency
|
171
160
|
name: pry-nav
|
172
|
-
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: *
|
169
|
+
version_requirements: *70273866220740
|
181
170
|
- !ruby/object:Gem::Dependency
|
182
171
|
name: plymouth
|
183
|
-
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: *
|
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
|