honeybadger 1.3.1 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Appraisals +20 -0
- data/Gemfile +1 -13
- data/Gemfile.lock +39 -64
- data/MIT-LICENSE +5 -0
- data/README.md +102 -3
- data/Rakefile +9 -134
- data/features/metal.feature +6 -4
- data/features/rack.feature +3 -4
- data/features/rails.feature +106 -99
- data/features/rake.feature +0 -2
- data/features/sinatra.feature +1 -3
- data/features/step_definitions/metal_steps.rb +2 -1
- data/features/step_definitions/rack_steps.rb +2 -2
- data/features/step_definitions/rails_steps.rb +238 -0
- data/features/step_definitions/rake_steps.rb +1 -1
- data/features/support/env.rb +7 -7
- data/features/support/rails.rb +41 -58
- data/gemfiles/rails2.3.gemfile +9 -0
- data/gemfiles/rails2.3.gemfile.lock +102 -0
- data/gemfiles/rails3.0.gemfile +8 -0
- data/gemfiles/rails3.0.gemfile.lock +146 -0
- data/gemfiles/rails3.1.gemfile +8 -0
- data/gemfiles/rails3.1.gemfile.lock +161 -0
- data/gemfiles/rails3.2.gemfile +8 -0
- data/gemfiles/rails3.2.gemfile.lock +160 -0
- data/honeybadger.gemspec +30 -24
- data/lib/honeybadger.rb +117 -113
- data/lib/honeybadger/backtrace.rb +9 -3
- data/lib/honeybadger/configuration.rb +22 -0
- data/lib/honeybadger/notice.rb +9 -0
- data/lib/honeybadger/rack.rb +5 -4
- data/lib/honeybadger/rails3_tasks.rb +20 -23
- data/lib/honeybadger/sender.rb +10 -4
- data/lib/honeybadger/shared_tasks.rb +12 -1
- data/lib/honeybadger/tasks.rb +6 -1
- data/test/test_helper.rb +71 -71
- data/test/unit/backtrace_test.rb +26 -23
- data/test/unit/capistrano_test.rb +1 -1
- data/test/unit/configuration_test.rb +19 -3
- data/test/unit/honeybadger_tasks_test.rb +1 -1
- data/test/unit/logger_test.rb +1 -1
- data/test/unit/notice_test.rb +71 -16
- data/test/unit/notifier_test.rb +25 -5
- data/test/unit/rack_test.rb +21 -1
- data/test/unit/rails/action_controller_catcher_test.rb +1 -1
- data/test/unit/rails_test.rb +1 -1
- data/test/unit/sender_test.rb +1 -1
- metadata +69 -45
- data/SUPPORTED_RAILS_VERSIONS +0 -37
- data/TESTING.md +0 -33
- data/features/step_definitions/file_steps.rb +0 -10
- data/features/step_definitions/rails_application_steps.rb +0 -394
- data/features/support/terminal.rb +0 -107
@@ -1,6 +1,6 @@
|
|
1
1
|
When /I run rake with (.+)/ do |command|
|
2
2
|
@rake_command = "rake #{command.gsub(' ','_')}"
|
3
|
-
@rake_result = `cd features/support/rake &&
|
3
|
+
@rake_result = `cd features/support/rake && #{@rake_command} 2>&1`
|
4
4
|
end
|
5
5
|
|
6
6
|
Then /Honeybadger should (|not) ?catch the exception/ do |condition|
|
data/features/support/env.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
|
-
require 'active_support'
|
2
1
|
require 'rspec'
|
2
|
+
require 'aruba/cucumber'
|
3
3
|
|
4
4
|
PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..')).freeze
|
5
5
|
TEMP_DIR = File.join(PROJECT_ROOT, 'tmp').freeze
|
6
6
|
LOCAL_RAILS_ROOT = File.join(TEMP_DIR, 'rails_root').freeze
|
7
|
-
BUILT_GEM_ROOT = File.join(TEMP_DIR, 'built_gems').freeze
|
8
|
-
LOCAL_GEM_ROOT = File.join(TEMP_DIR, 'local_gems').freeze
|
9
7
|
RACK_FILE = File.join(TEMP_DIR, 'rack_app.rb').freeze
|
10
8
|
|
11
9
|
Before do
|
12
|
-
FileUtils.mkdir_p(TEMP_DIR)
|
13
|
-
FileUtils.rm_rf(BUILT_GEM_ROOT)
|
14
10
|
FileUtils.rm_rf(LOCAL_RAILS_ROOT)
|
15
|
-
|
16
|
-
|
11
|
+
end
|
12
|
+
|
13
|
+
Before do
|
14
|
+
@dirs = ["tmp"]
|
15
|
+
@aruba_timeout_seconds = 45
|
16
|
+
@aruba_io_wait_seconds = 5
|
17
17
|
end
|
data/features/support/rails.rb
CHANGED
@@ -1,8 +1,4 @@
|
|
1
1
|
module RailsHelpers
|
2
|
-
def rails_root_exists?
|
3
|
-
File.exists?(environment_path)
|
4
|
-
end
|
5
|
-
|
6
2
|
def application_controller_filename
|
7
3
|
controller_filename = File.join(rails_root, 'app', 'controllers', "application_controller.rb")
|
8
4
|
end
|
@@ -20,24 +16,7 @@ module RailsHelpers
|
|
20
16
|
end
|
21
17
|
|
22
18
|
def rails_version
|
23
|
-
@rails_version ||=
|
24
|
-
if ENV["RAILS_VERSION"]
|
25
|
-
ENV["RAILS_VERSION"]
|
26
|
-
elsif bundler_manages_gems?
|
27
|
-
rails_version = open(gemfile_path).read.match(/gem.*rails["'].*["'](.+)["']/)[1]
|
28
|
-
else
|
29
|
-
environment_file = File.join(rails_root, 'config', 'environment.rb')
|
30
|
-
rails_version = `grep RAILS_GEM_VERSION #{environment_file}`.match(/[\d.]+/)[0]
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def bundler_manages_gems?
|
36
|
-
File.exists?(gemfile_path)
|
37
|
-
end
|
38
|
-
|
39
|
-
def gemfile_path
|
40
|
-
gemfile = File.join(rails_root, 'Gemfile')
|
19
|
+
@rails_version ||= `bundle exec rails -v`[/\d.+/]
|
41
20
|
end
|
42
21
|
|
43
22
|
def rails_manages_gems?
|
@@ -52,10 +31,6 @@ module RailsHelpers
|
|
52
31
|
rails3? || rails_version =~ /^2\./
|
53
32
|
end
|
54
33
|
|
55
|
-
def version_string
|
56
|
-
ENV['RAILS_VERSION'] || `tail -n 1 SUPPORTED_RAILS_VERSIONS` # use latest version if ENV["RAILS_VERSION"] is undefined
|
57
|
-
end
|
58
|
-
|
59
34
|
def environment_path
|
60
35
|
File.join(rails_root, 'config', 'environment.rb')
|
61
36
|
end
|
@@ -64,12 +39,12 @@ module RailsHelpers
|
|
64
39
|
File.join(rails_root, 'Rakefile')
|
65
40
|
end
|
66
41
|
|
67
|
-
def
|
68
|
-
File.
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
42
|
+
def rails_initializer_file
|
43
|
+
File.join(rails_root, 'config', 'initializers', 'honeybadger.rb')
|
44
|
+
end
|
45
|
+
|
46
|
+
def rails_non_initializer_honeybadger_config_file
|
47
|
+
File.join(rails_root, 'config', 'honeybadger.rb')
|
73
48
|
end
|
74
49
|
|
75
50
|
def config_gem(gem_name, version = nil)
|
@@ -85,34 +60,17 @@ module RailsHelpers
|
|
85
60
|
end
|
86
61
|
end
|
87
62
|
|
88
|
-
def
|
89
|
-
insert = <<-END
|
90
|
-
if Gem::VERSION >= "1.3.6"
|
91
|
-
module Rails
|
92
|
-
class GemDependency
|
93
|
-
def requirement
|
94
|
-
r = super
|
95
|
-
(r == Gem::Requirement.default) ? nil : r
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
END
|
63
|
+
def disable_activerecord
|
101
64
|
run = "Rails::Initializer.run do |config|"
|
65
|
+
insert = " config.frameworks -= [ :active_record ]"
|
102
66
|
content = File.read(environment_path)
|
103
|
-
if content.sub!(run, "#{
|
67
|
+
if content.sub!(run, "#{run}\n#{insert}")
|
104
68
|
File.open(environment_path, 'wb') { |file| file.write(content) }
|
105
69
|
else
|
106
70
|
raise "Couldn't find #{run.inspect} in #{environment_path}"
|
107
71
|
end
|
108
72
|
end
|
109
73
|
|
110
|
-
def require_thread
|
111
|
-
content = File.read(rakefile_path)
|
112
|
-
content = "require 'thread'\n#{content}"
|
113
|
-
File.open(rakefile_path, 'wb') { |file| file.write(content) }
|
114
|
-
end
|
115
|
-
|
116
74
|
def perform_request(uri, environment = 'production')
|
117
75
|
if rails3?
|
118
76
|
request_script = <<-SCRIPT
|
@@ -132,8 +90,7 @@ module RailsHelpers
|
|
132
90
|
end
|
133
91
|
SCRIPT
|
134
92
|
File.open(File.join(rails_root, 'request.rb'), 'w') { |file| file.write(request_script) }
|
135
|
-
|
136
|
-
@terminal.run("ruby -rthread ./script/rails runner -e #{environment} request.rb")
|
93
|
+
step %(I run `ruby -rthread ./script/rails runner -e #{environment} request.rb`)
|
137
94
|
elsif rails_uses_rack?
|
138
95
|
request_script = <<-SCRIPT
|
139
96
|
require File.expand_path('../config/environment', __FILE__)
|
@@ -153,8 +110,7 @@ module RailsHelpers
|
|
153
110
|
puts response
|
154
111
|
SCRIPT
|
155
112
|
File.open(File.join(rails_root, 'request.rb'), 'w') { |file| file.write(request_script) }
|
156
|
-
|
157
|
-
@terminal.run("ruby -rthread ./script/runner -e #{environment} request.rb")
|
113
|
+
step %(I run `ruby -rthread ./script/runner -e #{environment} request.rb`)
|
158
114
|
else
|
159
115
|
uri = URI.parse(uri)
|
160
116
|
request_script = <<-SCRIPT
|
@@ -182,8 +138,7 @@ module RailsHelpers
|
|
182
138
|
Dispatcher.dispatch(cgi)
|
183
139
|
SCRIPT
|
184
140
|
File.open(File.join(rails_root, 'request.rb'), 'w') { |file| file.write(request_script) }
|
185
|
-
|
186
|
-
@terminal.run("ruby -rthread ./script/runner -e #{environment} request.rb")
|
141
|
+
step %(I run `ruby -rthread ./script/runner -e #{environment} request.rb`)
|
187
142
|
end
|
188
143
|
end
|
189
144
|
|
@@ -196,6 +151,34 @@ module RailsHelpers
|
|
196
151
|
|
197
152
|
File.open(File.join(rails_root,"config","initializers", 'monkeypatchin.rb'), 'w') { |file| file.write(monkeypatchin) }
|
198
153
|
end
|
154
|
+
|
155
|
+
def config_gem_dependencies
|
156
|
+
insert = <<-END
|
157
|
+
if Gem::VERSION >= "1.3.6"
|
158
|
+
module Rails
|
159
|
+
class GemDependency
|
160
|
+
def requirement
|
161
|
+
r = super
|
162
|
+
(r == Gem::Requirement.default) ? nil : r
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
END
|
168
|
+
run = "Rails::Initializer.run do |config|"
|
169
|
+
content = File.read(environment_path)
|
170
|
+
if content.sub!(run, "#{insert}\n#{run}")
|
171
|
+
File.open(environment_path, 'wb') { |file| file.write(content) }
|
172
|
+
else
|
173
|
+
raise "Couldn't find #{run.inspect} in #{environment_path}"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def require_thread
|
178
|
+
content = File.read(rakefile_path)
|
179
|
+
content = "require 'thread'\n#{content}"
|
180
|
+
File.open(rakefile_path, 'wb') { |file| file.write(content) }
|
181
|
+
end
|
199
182
|
end
|
200
183
|
|
201
184
|
World(RailsHelpers)
|
@@ -0,0 +1,102 @@
|
|
1
|
+
PATH
|
2
|
+
remote: /Users/josh/code/honeybadger-ruby
|
3
|
+
specs:
|
4
|
+
honeybadger (1.3.1)
|
5
|
+
activesupport
|
6
|
+
json
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
actionmailer (2.3.14)
|
12
|
+
actionpack (= 2.3.14)
|
13
|
+
actionpack (2.3.14)
|
14
|
+
activesupport (= 2.3.14)
|
15
|
+
rack (~> 1.1.0)
|
16
|
+
activerecord (2.3.14)
|
17
|
+
activesupport (= 2.3.14)
|
18
|
+
activeresource (2.3.14)
|
19
|
+
activesupport (= 2.3.14)
|
20
|
+
activesupport (2.3.14)
|
21
|
+
appraisal (0.5.1)
|
22
|
+
bundler
|
23
|
+
rake
|
24
|
+
aruba (0.5.1)
|
25
|
+
childprocess (~> 0.3.6)
|
26
|
+
cucumber (>= 1.1.1)
|
27
|
+
rspec-expectations (>= 2.7.0)
|
28
|
+
bourne (1.1.2)
|
29
|
+
mocha (= 0.10.5)
|
30
|
+
builder (3.1.4)
|
31
|
+
capistrano (2.13.5)
|
32
|
+
highline
|
33
|
+
net-scp (>= 1.0.0)
|
34
|
+
net-sftp (>= 2.0.0)
|
35
|
+
net-ssh (>= 2.0.14)
|
36
|
+
net-ssh-gateway (>= 1.1.0)
|
37
|
+
childprocess (0.3.6)
|
38
|
+
ffi (~> 1.0, >= 1.0.6)
|
39
|
+
cucumber (1.2.1)
|
40
|
+
builder (>= 2.1.2)
|
41
|
+
diff-lcs (>= 1.1.3)
|
42
|
+
gherkin (~> 2.11.0)
|
43
|
+
json (>= 1.4.6)
|
44
|
+
diff-lcs (1.1.3)
|
45
|
+
fakeweb (1.3.0)
|
46
|
+
ffi (1.2.0)
|
47
|
+
gherkin (2.11.5)
|
48
|
+
json (>= 1.4.6)
|
49
|
+
highline (1.6.15)
|
50
|
+
json (1.7.5)
|
51
|
+
metaclass (0.0.1)
|
52
|
+
mocha (0.10.5)
|
53
|
+
metaclass (~> 0.0.1)
|
54
|
+
net-scp (1.0.4)
|
55
|
+
net-ssh (>= 1.99.1)
|
56
|
+
net-sftp (2.0.5)
|
57
|
+
net-ssh (>= 2.0.9)
|
58
|
+
net-ssh (2.6.2)
|
59
|
+
net-ssh-gateway (1.1.0)
|
60
|
+
net-ssh (>= 1.99.1)
|
61
|
+
rack (1.1.3)
|
62
|
+
rails (2.3.14)
|
63
|
+
actionmailer (= 2.3.14)
|
64
|
+
actionpack (= 2.3.14)
|
65
|
+
activerecord (= 2.3.14)
|
66
|
+
activeresource (= 2.3.14)
|
67
|
+
activesupport (= 2.3.14)
|
68
|
+
rake (>= 0.8.3)
|
69
|
+
rake (0.9.5)
|
70
|
+
rspec (2.12.0)
|
71
|
+
rspec-core (~> 2.12.0)
|
72
|
+
rspec-expectations (~> 2.12.0)
|
73
|
+
rspec-mocks (~> 2.12.0)
|
74
|
+
rspec-core (2.12.0)
|
75
|
+
rspec-expectations (2.12.0)
|
76
|
+
diff-lcs (~> 1.1.3)
|
77
|
+
rspec-mocks (2.12.0)
|
78
|
+
sham_rack (1.3.4)
|
79
|
+
rack
|
80
|
+
shoulda (2.11.3)
|
81
|
+
sinatra (1.2.8)
|
82
|
+
rack (~> 1.1)
|
83
|
+
tilt (>= 1.2.2, < 2.0)
|
84
|
+
tilt (1.3.3)
|
85
|
+
|
86
|
+
PLATFORMS
|
87
|
+
ruby
|
88
|
+
|
89
|
+
DEPENDENCIES
|
90
|
+
appraisal
|
91
|
+
aruba
|
92
|
+
bourne (>= 1.0)
|
93
|
+
capistrano
|
94
|
+
cucumber (~> 1.2.1)
|
95
|
+
fakeweb (~> 1.3.0)
|
96
|
+
honeybadger!
|
97
|
+
rails (= 2.3.14)
|
98
|
+
rake (= 0.9.5)
|
99
|
+
rspec (~> 2.12.0)
|
100
|
+
sham_rack (~> 1.3.0)
|
101
|
+
shoulda (~> 2.11.3)
|
102
|
+
sinatra
|
@@ -0,0 +1,146 @@
|
|
1
|
+
PATH
|
2
|
+
remote: /Users/josh/code/honeybadger-ruby
|
3
|
+
specs:
|
4
|
+
honeybadger (1.3.1)
|
5
|
+
activesupport
|
6
|
+
json
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
abstract (1.0.0)
|
12
|
+
actionmailer (3.0.17)
|
13
|
+
actionpack (= 3.0.17)
|
14
|
+
mail (~> 2.2.19)
|
15
|
+
actionpack (3.0.17)
|
16
|
+
activemodel (= 3.0.17)
|
17
|
+
activesupport (= 3.0.17)
|
18
|
+
builder (~> 2.1.2)
|
19
|
+
erubis (~> 2.6.6)
|
20
|
+
i18n (~> 0.5.0)
|
21
|
+
rack (~> 1.2.5)
|
22
|
+
rack-mount (~> 0.6.14)
|
23
|
+
rack-test (~> 0.5.7)
|
24
|
+
tzinfo (~> 0.3.23)
|
25
|
+
activemodel (3.0.17)
|
26
|
+
activesupport (= 3.0.17)
|
27
|
+
builder (~> 2.1.2)
|
28
|
+
i18n (~> 0.5.0)
|
29
|
+
activerecord (3.0.17)
|
30
|
+
activemodel (= 3.0.17)
|
31
|
+
activesupport (= 3.0.17)
|
32
|
+
arel (~> 2.0.10)
|
33
|
+
tzinfo (~> 0.3.23)
|
34
|
+
activeresource (3.0.17)
|
35
|
+
activemodel (= 3.0.17)
|
36
|
+
activesupport (= 3.0.17)
|
37
|
+
activesupport (3.0.17)
|
38
|
+
appraisal (0.5.1)
|
39
|
+
bundler
|
40
|
+
rake
|
41
|
+
arel (2.0.10)
|
42
|
+
aruba (0.5.1)
|
43
|
+
childprocess (~> 0.3.6)
|
44
|
+
cucumber (>= 1.1.1)
|
45
|
+
rspec-expectations (>= 2.7.0)
|
46
|
+
bourne (1.1.2)
|
47
|
+
mocha (= 0.10.5)
|
48
|
+
builder (2.1.2)
|
49
|
+
capistrano (2.13.5)
|
50
|
+
highline
|
51
|
+
net-scp (>= 1.0.0)
|
52
|
+
net-sftp (>= 2.0.0)
|
53
|
+
net-ssh (>= 2.0.14)
|
54
|
+
net-ssh-gateway (>= 1.1.0)
|
55
|
+
childprocess (0.3.6)
|
56
|
+
ffi (~> 1.0, >= 1.0.6)
|
57
|
+
cucumber (1.2.1)
|
58
|
+
builder (>= 2.1.2)
|
59
|
+
diff-lcs (>= 1.1.3)
|
60
|
+
gherkin (~> 2.11.0)
|
61
|
+
json (>= 1.4.6)
|
62
|
+
diff-lcs (1.1.3)
|
63
|
+
erubis (2.6.6)
|
64
|
+
abstract (>= 1.0.0)
|
65
|
+
fakeweb (1.3.0)
|
66
|
+
ffi (1.2.0)
|
67
|
+
gherkin (2.11.5)
|
68
|
+
json (>= 1.4.6)
|
69
|
+
highline (1.6.15)
|
70
|
+
i18n (0.5.0)
|
71
|
+
json (1.7.5)
|
72
|
+
mail (2.2.19)
|
73
|
+
activesupport (>= 2.3.6)
|
74
|
+
i18n (>= 0.4.0)
|
75
|
+
mime-types (~> 1.16)
|
76
|
+
treetop (~> 1.4.8)
|
77
|
+
metaclass (0.0.1)
|
78
|
+
mime-types (1.19)
|
79
|
+
mocha (0.10.5)
|
80
|
+
metaclass (~> 0.0.1)
|
81
|
+
net-scp (1.0.4)
|
82
|
+
net-ssh (>= 1.99.1)
|
83
|
+
net-sftp (2.0.5)
|
84
|
+
net-ssh (>= 2.0.9)
|
85
|
+
net-ssh (2.6.2)
|
86
|
+
net-ssh-gateway (1.1.0)
|
87
|
+
net-ssh (>= 1.99.1)
|
88
|
+
polyglot (0.3.3)
|
89
|
+
rack (1.2.5)
|
90
|
+
rack-mount (0.6.14)
|
91
|
+
rack (>= 1.0.0)
|
92
|
+
rack-test (0.5.7)
|
93
|
+
rack (>= 1.0)
|
94
|
+
rails (3.0.17)
|
95
|
+
actionmailer (= 3.0.17)
|
96
|
+
actionpack (= 3.0.17)
|
97
|
+
activerecord (= 3.0.17)
|
98
|
+
activeresource (= 3.0.17)
|
99
|
+
activesupport (= 3.0.17)
|
100
|
+
bundler (~> 1.0)
|
101
|
+
railties (= 3.0.17)
|
102
|
+
railties (3.0.17)
|
103
|
+
actionpack (= 3.0.17)
|
104
|
+
activesupport (= 3.0.17)
|
105
|
+
rake (>= 0.8.7)
|
106
|
+
rdoc (~> 3.4)
|
107
|
+
thor (~> 0.14.4)
|
108
|
+
rake (10.0.2)
|
109
|
+
rdoc (3.12)
|
110
|
+
json (~> 1.4)
|
111
|
+
rspec (2.12.0)
|
112
|
+
rspec-core (~> 2.12.0)
|
113
|
+
rspec-expectations (~> 2.12.0)
|
114
|
+
rspec-mocks (~> 2.12.0)
|
115
|
+
rspec-core (2.12.0)
|
116
|
+
rspec-expectations (2.12.0)
|
117
|
+
diff-lcs (~> 1.1.3)
|
118
|
+
rspec-mocks (2.12.0)
|
119
|
+
sham_rack (1.3.4)
|
120
|
+
rack
|
121
|
+
shoulda (2.11.3)
|
122
|
+
sinatra (1.0)
|
123
|
+
rack (>= 1.0)
|
124
|
+
thor (0.14.6)
|
125
|
+
treetop (1.4.12)
|
126
|
+
polyglot
|
127
|
+
polyglot (>= 0.3.1)
|
128
|
+
tzinfo (0.3.35)
|
129
|
+
|
130
|
+
PLATFORMS
|
131
|
+
ruby
|
132
|
+
|
133
|
+
DEPENDENCIES
|
134
|
+
appraisal
|
135
|
+
aruba
|
136
|
+
bourne (>= 1.0)
|
137
|
+
capistrano
|
138
|
+
cucumber (~> 1.2.1)
|
139
|
+
fakeweb (~> 1.3.0)
|
140
|
+
honeybadger!
|
141
|
+
rails (= 3.0.17)
|
142
|
+
rake
|
143
|
+
rspec (~> 2.12.0)
|
144
|
+
sham_rack (~> 1.3.0)
|
145
|
+
shoulda (~> 2.11.3)
|
146
|
+
sinatra
|