sapience 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.simplecov +6 -2
- data/.travis.yml +8 -25
- data/CODE_OF_CONDUCT.md +1 -1
- data/Gemfile +5 -5
- data/README.md +146 -15
- data/Rakefile +2 -1
- data/config/default.yml +29 -0
- data/dev-entrypoint.sh +10 -0
- data/docker-compose.yml +42 -0
- data/lib/sapience/appender/datadog.rb +100 -0
- data/lib/sapience/appender/file.rb +11 -22
- data/lib/sapience/appender/sentry.rb +61 -55
- data/lib/sapience/appender/wrapper.rb +5 -4
- data/lib/sapience/base.rb +21 -13
- data/lib/sapience/config_loader.rb +66 -0
- data/lib/sapience/configuration/grape.rb +9 -0
- data/lib/sapience/configuration.rb +32 -22
- data/lib/sapience/core_ext/hash.rb +25 -0
- data/lib/sapience/core_ext/thread.rb +2 -2
- data/lib/sapience/extensions/action_cable/tagged_logger_proxy.rb +6 -0
- data/lib/sapience/extensions/action_controller/live.rb +6 -0
- data/lib/sapience/extensions/action_controller/log_subscriber.rb +127 -0
- data/lib/sapience/extensions/action_controller/log_subscriber_processing.rb +24 -0
- data/lib/sapience/extensions/action_dispatch/debug_exceptions.rb +11 -0
- data/lib/sapience/extensions/action_view/log_subscriber.rb +9 -0
- data/lib/sapience/extensions/action_view/streaming_template_renderer.rb +11 -0
- data/lib/sapience/extensions/active_job/logging.rb +14 -0
- data/lib/sapience/extensions/active_model_serializers/logging.rb +14 -0
- data/lib/sapience/extensions/active_record/log_subscriber.rb +35 -0
- data/lib/sapience/extensions/grape/middleware/logging.rb +91 -0
- data/lib/sapience/extensions/grape/timings.rb +25 -0
- data/lib/sapience/extensions/rails/rack/logger.rb +11 -0
- data/lib/sapience/extensions/rails/rack/logger_info_as_debug.rb +24 -0
- data/lib/sapience/formatters/color.rb +3 -3
- data/lib/sapience/formatters/default.rb +1 -1
- data/lib/sapience/grape.rb +25 -0
- data/lib/sapience/log.rb +8 -6
- data/lib/sapience/loggable.rb +19 -17
- data/lib/sapience/logger.rb +46 -126
- data/lib/sapience/rails.rb +65 -8
- data/lib/sapience/sapience.rb +74 -73
- data/lib/sapience/subscriber.rb +5 -1
- data/lib/sapience/version.rb +1 -1
- data/lib/sapience.rb +4 -1
- data/sapience.gemspec +7 -4
- data/test_app/Gemfile +5 -1
- data/test_app/Rakefile +5 -1
- data/test_app/app/controllers/posts_controller.rb +12 -11
- data/test_app/config/application.rb +0 -1
- data/test_app/spec/controllers/posts_controller_spec.rb +1 -1
- data/test_app/spec/fixtures/sapience.yml +14 -0
- data/test_app/spec/helpers/posts_helper_spec.rb +1 -1
- data/test_app/spec/integration/sapience_spec.rb +14 -0
- data/test_app/spec/models/post_spec.rb +1 -1
- data/test_app/spec/models/user_spec.rb +1 -1
- data/test_app/spec/rails_helper.rb +15 -0
- data/test_app/spec/requests/posts_spec.rb +1 -1
- data/test_app/spec/routing/posts_routing_spec.rb +8 -10
- data/test_app/spec/spec_helper.rb +0 -44
- metadata +76 -11
- data/lib/sapience/appender/statsd.rb +0 -68
data/lib/sapience/sapience.rb
CHANGED
@@ -12,7 +12,7 @@ require "socket"
|
|
12
12
|
# config.appenders = [
|
13
13
|
# { file: { io: STDOUT, formatter: :color } },
|
14
14
|
# { statsd: { url: 'udp://localhost:2222' } },
|
15
|
-
# { sentry: { dsn: '
|
15
|
+
# { sentry: { dsn: 'https://foobar:443' } },
|
16
16
|
# ]
|
17
17
|
# end
|
18
18
|
|
@@ -27,17 +27,46 @@ module Sapience
|
|
27
27
|
LEVELS = [:trace, :debug, :info, :warn, :error, :fatal]
|
28
28
|
|
29
29
|
def self.config
|
30
|
-
@@config ||=
|
30
|
+
@@config ||= begin
|
31
|
+
config = ConfigLoader.load_from_file
|
32
|
+
env = config[environment]
|
33
|
+
unless env
|
34
|
+
puts "Missing configuration for #{environment} environment. Sapience is going to use default configuration"
|
35
|
+
env = config.fetch("default")
|
36
|
+
end
|
37
|
+
Configuration.new(env)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.reset!
|
42
|
+
@@config = nil
|
43
|
+
@@logger = nil
|
44
|
+
@@metrix = nil
|
45
|
+
reset_appenders!
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.reset_appenders!
|
49
|
+
@@appenders = Concurrent::Array.new
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.environment
|
53
|
+
ENV.fetch("RAILS_ENV") do
|
54
|
+
ENV.fetch("RACK_ENV") do
|
55
|
+
::Rails.env if defined?(::Rails) && ::Rails.respond_to?(:env)
|
56
|
+
end
|
57
|
+
end
|
31
58
|
end
|
32
59
|
|
33
60
|
def self.configure
|
34
|
-
yield
|
61
|
+
yield config if block_given?
|
35
62
|
|
36
63
|
config.appenders.each do |appender|
|
37
64
|
appender.each do |name, options|
|
38
65
|
add_appender(name, options)
|
39
66
|
end
|
40
67
|
end
|
68
|
+
|
69
|
+
config
|
41
70
|
end
|
42
71
|
|
43
72
|
# Return a logger for the supplied class or class_name
|
@@ -123,24 +152,36 @@ module Sapience
|
|
123
152
|
# logger = Sapience['Example']
|
124
153
|
# logger.info "Hello World"
|
125
154
|
# logger.debug("Login time", user: 'Joe', duration: 100, ip_address: '127.0.0.1')
|
126
|
-
def self.add_appender(appender, options, _deprecated_level = nil, &
|
155
|
+
def self.add_appender(appender, options = {}, _deprecated_level = nil, &_block)
|
127
156
|
fail ArgumentError, "options should be a hash" unless options.is_a?(Hash)
|
157
|
+
options.deep_symbolize_keys!
|
128
158
|
appender_class = constantize_symbol(appender)
|
129
159
|
appender = appender_class.new(options)
|
130
160
|
@@appenders << appender
|
131
161
|
|
132
162
|
# Start appender thread if it is not already running
|
133
163
|
Sapience::Logger.start_appender_thread
|
134
|
-
Sapience
|
164
|
+
Sapience.logger = appender if appender.is_a?(Sapience::Appender::File)
|
165
|
+
Sapience.metrix = appender if appender.is_a?(Sapience::Appender::Datadog)
|
135
166
|
appender
|
136
167
|
end
|
137
168
|
|
169
|
+
|
138
170
|
# Remove an existing appender
|
139
171
|
# Currently only supports appender instances
|
172
|
+
# TODO: Make it possible to remove appenders by type
|
173
|
+
# Maybe create a concurrent collection that allows this by inheriting from concurrent array.
|
140
174
|
def self.remove_appender(appender)
|
141
175
|
@@appenders.delete(appender)
|
142
176
|
end
|
143
177
|
|
178
|
+
# Remove specific appenders or all existing
|
179
|
+
def self.remove_appenders(appenders = @@appenders)
|
180
|
+
appenders.each do |appender|
|
181
|
+
remove_appender(appender)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
144
185
|
# Returns [Sapience::Subscriber] a copy of the list of active
|
145
186
|
# appenders for debugging etc.
|
146
187
|
# Use Sapience.add_appender and Sapience.remove_appender
|
@@ -149,6 +190,22 @@ module Sapience
|
|
149
190
|
@@appenders.clone
|
150
191
|
end
|
151
192
|
|
193
|
+
def self.metrix=(metrix)
|
194
|
+
@@metrix = metrix
|
195
|
+
end
|
196
|
+
|
197
|
+
def self.metrix
|
198
|
+
@@metrix ||= Sapience.add_appender(:datadog)
|
199
|
+
end
|
200
|
+
|
201
|
+
def self.logger=(logger)
|
202
|
+
@@logger = Sapience::Logger.logger = logger
|
203
|
+
end
|
204
|
+
|
205
|
+
def self.logger
|
206
|
+
@@logger ||= Sapience::Logger.logger
|
207
|
+
end
|
208
|
+
|
152
209
|
# Wait until all queued log messages have been written and flush all active
|
153
210
|
# appenders
|
154
211
|
def self.flush
|
@@ -170,63 +227,6 @@ module Sapience
|
|
170
227
|
Sapience::Logger.start_appender_thread
|
171
228
|
end
|
172
229
|
|
173
|
-
# Add signal handlers for Sapience
|
174
|
-
#
|
175
|
-
# Two signal handlers will be registered by default:
|
176
|
-
#
|
177
|
-
# 1. Changing the log_level:
|
178
|
-
#
|
179
|
-
# The log level can be changed without restarting the process by sending the
|
180
|
-
# log_level_signal, which by default is 'USR2'
|
181
|
-
#
|
182
|
-
# When the log_level_signal is raised on this process, the global default log level
|
183
|
-
# rotates through the following log levels in the following order, starting
|
184
|
-
# from the current global default level:
|
185
|
-
# :warn, :info, :debug, :trace
|
186
|
-
#
|
187
|
-
# If the current level is :trace it wraps around back to :warn
|
188
|
-
#
|
189
|
-
# 2. Logging a Ruby thread dump
|
190
|
-
#
|
191
|
-
# When the signal is raised on this process, Sapience will write the list
|
192
|
-
# of threads to the log file, along with their back-traces when available
|
193
|
-
#
|
194
|
-
# It is recommended to name any threads you create in the application, by
|
195
|
-
# calling the following from within the thread itself:
|
196
|
-
# Thread.current.name = 'My Worker'
|
197
|
-
#
|
198
|
-
#
|
199
|
-
# Note:
|
200
|
-
# To only register one of the signal handlers, set the other to nil
|
201
|
-
# rubocop:disable AbcSize, CyclomaticComplexity, PerceivedComplexity
|
202
|
-
def self.add_signal_handler(log_level_signal = "USR2", thread_dump_signal = "TTIN", _gc_log_microseconds = 100_000)
|
203
|
-
Signal.trap(log_level_signal) do
|
204
|
-
index = (default_level == :trace) ? LEVELS.find_index(:error) : LEVELS.find_index(default_level)
|
205
|
-
new_level = LEVELS[index - 1]
|
206
|
-
self["Sapience"].warn "Changed global default log level to #{new_level.inspect}"
|
207
|
-
self.default_level = new_level
|
208
|
-
end if log_level_signal
|
209
|
-
|
210
|
-
Signal.trap(thread_dump_signal) do
|
211
|
-
logger = Sapience["Thread Dump"]
|
212
|
-
Thread.list.each do |thread|
|
213
|
-
next if thread == Thread.current
|
214
|
-
message = thread.name
|
215
|
-
if (backtrace = thread.backtrace)
|
216
|
-
message += "\n"
|
217
|
-
message << backtrace.join("\n")
|
218
|
-
end
|
219
|
-
tags = thread[:sapience_tags]
|
220
|
-
tags = tags.nil? ? [] : tags.clone
|
221
|
-
logger.tagged(tags) { logger.warn(message) }
|
222
|
-
end
|
223
|
-
end if thread_dump_signal
|
224
|
-
|
225
|
-
true
|
226
|
-
end
|
227
|
-
|
228
|
-
# rubocop:enable AbcSize, CyclomaticComplexity, PerceivedComplexity
|
229
|
-
|
230
230
|
# If the tag being supplied is definitely a string then this fast
|
231
231
|
# tag api can be used for short lived tags
|
232
232
|
def self.fast_tag(tag)
|
@@ -327,20 +327,21 @@ module Sapience
|
|
327
327
|
Thread.current[:sapience_silence] = current_index
|
328
328
|
end
|
329
329
|
|
330
|
-
|
331
|
-
|
332
|
-
@@appenders = Concurrent::Array.new
|
330
|
+
reset_appenders!
|
333
331
|
|
334
332
|
def self.constantize_symbol(symbol, namespace = "Sapience::Appender")
|
335
333
|
klass = "#{namespace}::#{camelize(symbol.to_s)}"
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
334
|
+
constantize(klass)
|
335
|
+
rescue NameError
|
336
|
+
raise(ArgumentError, "Could not convert symbol: #{symbol} to a class in: #{namespace}. Looking for: #{klass}")
|
337
|
+
end
|
338
|
+
|
339
|
+
def self.constantize(class_name)
|
340
|
+
return class_name unless class_name.is_a?(String)
|
341
|
+
if RUBY_VERSION.to_i >= 2
|
342
|
+
Object.const_get(class_name)
|
343
|
+
else
|
344
|
+
class_name.split("::").inject(Object) { |o, name| o.const_get(name) } # rubocop:disable SingleLineBlockParams
|
344
345
|
end
|
345
346
|
end
|
346
347
|
|
data/lib/sapience/subscriber.rb
CHANGED
@@ -96,10 +96,13 @@ module Sapience
|
|
96
96
|
# - Any object that responds to :call
|
97
97
|
# - If none of the above apply, then the supplied block is returned as the formatter.
|
98
98
|
# - Otherwise an instance of the default formatter is returned.
|
99
|
-
|
99
|
+
# rubocop:disable CyclomaticComplexity, AbcSize, PerceivedComplexity
|
100
|
+
def extract_formatter(formatter, &block)
|
100
101
|
case
|
101
102
|
when formatter.is_a?(Symbol)
|
102
103
|
Sapience.constantize_symbol(formatter, "Sapience::Formatters").new
|
104
|
+
when formatter.is_a?(String)
|
105
|
+
Sapience.constantize_symbol(formatter, "Sapience::Formatters").new
|
103
106
|
when formatter.is_a?(Hash) && formatter.size > 0
|
104
107
|
fmt, options = formatter.first
|
105
108
|
Sapience.constantize_symbol(fmt.to_sym, "Sapience::Formatters").new(options)
|
@@ -113,6 +116,7 @@ module Sapience
|
|
113
116
|
default_formatter
|
114
117
|
end
|
115
118
|
end
|
119
|
+
# rubocop:enable CyclomaticComplexity, AbcSize, PerceivedComplexity
|
116
120
|
|
117
121
|
SUBSCRIBER_OPTIONS = [:level, :formatter, :filter, :application, :host].freeze
|
118
122
|
|
data/lib/sapience/version.rb
CHANGED
data/lib/sapience.rb
CHANGED
@@ -11,8 +11,11 @@ require "sapience/formatters/default"
|
|
11
11
|
require "sapience/formatters/color"
|
12
12
|
require "sapience/formatters/json"
|
13
13
|
|
14
|
+
require "sapience/config_loader"
|
14
15
|
require "sapience/configuration"
|
16
|
+
require "sapience/configuration/grape"
|
15
17
|
require "sapience/ansi_colors"
|
18
|
+
require "sapience/core_ext/hash"
|
16
19
|
require "sapience/core_ext/thread"
|
17
20
|
require "sapience/base"
|
18
21
|
require "sapience/log"
|
@@ -23,7 +26,7 @@ require "sapience/subscriber"
|
|
23
26
|
require "sapience/appender/file"
|
24
27
|
require "sapience/appender/sentry"
|
25
28
|
require "sapience/appender/wrapper"
|
26
|
-
require "sapience/appender/
|
29
|
+
require "sapience/appender/datadog"
|
27
30
|
|
28
31
|
# @formatter:on
|
29
32
|
|
data/sapience.gemspec
CHANGED
@@ -9,9 +9,9 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Mikael Henriksson", "Alex Malkov"]
|
10
10
|
spec.email = ["mika@reevoo.com", "alex.malkov@reevoo.com"]
|
11
11
|
|
12
|
-
spec.summary = "
|
13
|
-
spec.description = "
|
14
|
-
spec.homepage = "https://
|
12
|
+
spec.summary = "Hasslefree autoconfiguration for logging, metrics and exception collection."
|
13
|
+
spec.description = "Hasslefree autoconfiguration for logging, metrics and exception collection."
|
14
|
+
spec.homepage = "https://github.com/reevoo/sapience"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
17
17
|
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
|
28
28
|
spec.require_paths = ["lib"]
|
29
29
|
|
30
|
-
spec.add_dependency "concurrent-ruby"
|
30
|
+
spec.add_dependency "concurrent-ruby", "~> 1.0"
|
31
31
|
spec.add_development_dependency "bundler", "~> 1.12"
|
32
32
|
spec.add_development_dependency "rake", "~> 10.0"
|
33
33
|
spec.add_development_dependency "rspec", "~> 3.0"
|
@@ -36,4 +36,7 @@ Gem::Specification.new do |spec|
|
|
36
36
|
spec.add_development_dependency "simplecov"
|
37
37
|
spec.add_development_dependency "simplecov-json"
|
38
38
|
spec.add_development_dependency "rspec-its"
|
39
|
+
spec.add_development_dependency "codeclimate-test-reporter"
|
40
|
+
spec.add_development_dependency "coveralls"
|
41
|
+
spec.add_development_dependency "gem-release"
|
39
42
|
end
|
data/test_app/Gemfile
CHANGED
@@ -14,7 +14,7 @@ gem "puma", "~> 3.0"
|
|
14
14
|
|
15
15
|
# Use Capistrano for deployment
|
16
16
|
# gem 'capistrano-rails', group: :development
|
17
|
-
gem "sapience", path: "../"
|
17
|
+
gem "sapience", path: "../", require: "sapience/rails"
|
18
18
|
gem "sentry-raven"
|
19
19
|
gem "statsd-ruby"
|
20
20
|
|
@@ -32,5 +32,9 @@ group :development do
|
|
32
32
|
gem "listen", "~> 3.0.5"
|
33
33
|
end
|
34
34
|
|
35
|
+
group :test do
|
36
|
+
gem "rspec-its"
|
37
|
+
end
|
38
|
+
|
35
39
|
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
|
36
40
|
gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby]
|
data/test_app/Rakefile
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
2
2
|
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
3
|
-
|
4
3
|
require_relative "config/application"
|
5
4
|
|
6
5
|
Rails.application.load_tasks
|
6
|
+
|
7
|
+
require "rspec/core/rake_task"
|
8
|
+
RSpec::Core::RakeTask.new(:spec)
|
9
|
+
|
10
|
+
task default: [:spec]
|
@@ -24,7 +24,7 @@ class PostsController < ApplicationController
|
|
24
24
|
@post = Post.new(post_params)
|
25
25
|
|
26
26
|
if @post.save
|
27
|
-
redirect_to @post, notice:
|
27
|
+
redirect_to @post, notice: "Post was successfully created."
|
28
28
|
else
|
29
29
|
render :new
|
30
30
|
end
|
@@ -33,7 +33,7 @@ class PostsController < ApplicationController
|
|
33
33
|
# PATCH/PUT /posts/1
|
34
34
|
def update
|
35
35
|
if @post.update(post_params)
|
36
|
-
redirect_to @post, notice:
|
36
|
+
redirect_to @post, notice: "Post was successfully updated."
|
37
37
|
else
|
38
38
|
render :edit
|
39
39
|
end
|
@@ -42,17 +42,18 @@ class PostsController < ApplicationController
|
|
42
42
|
# DELETE /posts/1
|
43
43
|
def destroy
|
44
44
|
@post.destroy
|
45
|
-
redirect_to posts_url, notice:
|
45
|
+
redirect_to posts_url, notice: "Post was successfully destroyed."
|
46
46
|
end
|
47
47
|
|
48
48
|
private
|
49
|
-
# Use callbacks to share common setup or constraints between actions.
|
50
|
-
def set_post
|
51
|
-
@post = Post.find(params[:id])
|
52
|
-
end
|
53
49
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
50
|
+
# Use callbacks to share common setup or constraints between actions.
|
51
|
+
def set_post
|
52
|
+
@post = Post.find(params[:id])
|
53
|
+
end
|
54
|
+
|
55
|
+
# Only allow a trusted parameter "white list" through.
|
56
|
+
def post_params
|
57
|
+
params.require(:post).permit(:title, :body, :author_id)
|
58
|
+
end
|
58
59
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "rails_helper"
|
2
|
+
require "fileutils"
|
3
|
+
|
4
|
+
describe Sapience, "rails integration", :integration do
|
5
|
+
context "with a sapience.yml present in config/" do
|
6
|
+
describe ".config" do
|
7
|
+
subject(:config) { Sapience.config }
|
8
|
+
its(:default_level) { is_expected.to eq(:fatal) }
|
9
|
+
its(:default_level_index) { is_expected.to eq(5) }
|
10
|
+
its(:backtrace_level) { is_expected.to eq(:fatal) }
|
11
|
+
its(:backtrace_level_index) { is_expected.to eq(5) }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -5,6 +5,7 @@ require File.expand_path("../../config/environment", __FILE__)
|
|
5
5
|
abort("The Rails environment is running in production mode!") if Rails.env.production?
|
6
6
|
require "spec_helper"
|
7
7
|
require "rspec/rails"
|
8
|
+
require "rspec/its"
|
8
9
|
|
9
10
|
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
|
10
11
|
|
@@ -20,4 +21,18 @@ RSpec.configure do |config|
|
|
20
21
|
|
21
22
|
config.infer_spec_type_from_file_location!
|
22
23
|
config.filter_rails_from_backtrace!
|
24
|
+
config.before(:each) do
|
25
|
+
Sapience.reset!
|
26
|
+
end
|
27
|
+
|
28
|
+
config.before(:suite) do
|
29
|
+
FileUtils.cp(
|
30
|
+
Rails.root.join("spec/fixtures/sapience.yml"),
|
31
|
+
Rails.root.join("config/sapience.yml"),
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
config.after(:suite) do
|
36
|
+
FileUtils.rm(Rails.root.join("config/sapience.yml"))
|
37
|
+
end
|
23
38
|
end
|
@@ -2,38 +2,36 @@ require "rails_helper"
|
|
2
2
|
|
3
3
|
RSpec.describe PostsController, type: :routing do
|
4
4
|
describe "routing" do
|
5
|
-
|
6
5
|
it "routes to #index" do
|
7
|
-
expect(:
|
6
|
+
expect(get: "/posts").to route_to("posts#index")
|
8
7
|
end
|
9
8
|
|
10
9
|
it "routes to #new" do
|
11
|
-
expect(:
|
10
|
+
expect(get: "/posts/new").to route_to("posts#new")
|
12
11
|
end
|
13
12
|
|
14
13
|
it "routes to #show" do
|
15
|
-
expect(:
|
14
|
+
expect(get: "/posts/1").to route_to("posts#show", id: "1")
|
16
15
|
end
|
17
16
|
|
18
17
|
it "routes to #edit" do
|
19
|
-
expect(:
|
18
|
+
expect(get: "/posts/1/edit").to route_to("posts#edit", id: "1")
|
20
19
|
end
|
21
20
|
|
22
21
|
it "routes to #create" do
|
23
|
-
expect(:
|
22
|
+
expect(post: "/posts").to route_to("posts#create")
|
24
23
|
end
|
25
24
|
|
26
25
|
it "routes to #update via PUT" do
|
27
|
-
expect(:
|
26
|
+
expect(put: "/posts/1").to route_to("posts#update", id: "1")
|
28
27
|
end
|
29
28
|
|
30
29
|
it "routes to #update via PATCH" do
|
31
|
-
expect(:
|
30
|
+
expect(patch: "/posts/1").to route_to("posts#update", id: "1")
|
32
31
|
end
|
33
32
|
|
34
33
|
it "routes to #destroy" do
|
35
|
-
expect(:
|
34
|
+
expect(delete: "/posts/1").to route_to("posts#destroy", id: "1")
|
36
35
|
end
|
37
|
-
|
38
36
|
end
|
39
37
|
end
|
@@ -7,54 +7,10 @@ RSpec.configure do |config|
|
|
7
7
|
mocks.verify_partial_doubles = true
|
8
8
|
end
|
9
9
|
|
10
|
-
# This option will default to `:apply_to_host_groups` in RSpec 4 (and will
|
11
|
-
# have no way to turn it off -- the option exists only for backwards
|
12
|
-
# compatibility in RSpec 3). It causes shared context metadata to be
|
13
|
-
# inherited by the metadata hash of host groups and examples, rather than
|
14
|
-
# triggering implicit auto-inclusion in groups with matching metadata.
|
15
10
|
config.shared_context_metadata_behavior = :apply_to_host_groups
|
16
|
-
|
17
|
-
# This allows you to limit a spec run to individual examples or groups
|
18
|
-
# you care about by tagging them with `:focus` metadata. When nothing
|
19
|
-
# is tagged with `:focus`, all examples get run. RSpec also provides
|
20
|
-
# aliases for `it`, `describe`, and `context` that include `:focus`
|
21
|
-
# metadata: `fit`, `fdescribe` and `fcontext`, respectively.
|
22
11
|
config.filter_run_when_matching :focus
|
23
|
-
|
24
|
-
# Allows RSpec to persist some state between runs in order to support
|
25
|
-
# the `--only-failures` and `--next-failure` CLI options. We recommend
|
26
|
-
# you configure your source control system to ignore this file.
|
27
12
|
config.example_status_persistence_file_path = "spec/examples.txt"
|
28
|
-
|
29
|
-
# Limits the available syntax to the non-monkey patched syntax that is
|
30
|
-
# recommended. For more details, see:
|
31
|
-
# - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
|
32
|
-
# - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
33
|
-
# - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
|
34
|
-
config.disable_monkey_patching!
|
35
|
-
|
36
|
-
# Many RSpec users commonly either run the entire suite or an individual
|
37
|
-
# file, and it's useful to allow more verbose output when running an
|
38
|
-
# individual spec file.
|
39
|
-
# Use the documentation formatter for detailed output,
|
40
|
-
# unless a formatter has already been configured
|
41
|
-
# (e.g. via a command-line flag).
|
42
13
|
config.default_formatter = "doc" if config.files_to_run.one?
|
43
|
-
|
44
|
-
# Print the 10 slowest examples and example groups at the
|
45
|
-
# end of the spec run, to help surface which specs are running
|
46
|
-
# particularly slow.
|
47
|
-
# config.profile_examples = 10
|
48
|
-
|
49
|
-
# Run specs in random order to surface order dependencies. If you find an
|
50
|
-
# order dependency and want to debug it, you can fix the order by providing
|
51
|
-
# the seed, which is printed after each run.
|
52
|
-
# --seed 1234
|
53
14
|
config.order = :random
|
54
|
-
|
55
|
-
# Seed global randomization in this process using the `--seed` CLI option.
|
56
|
-
# Setting this allows you to use `--seed` to deterministically reproduce
|
57
|
-
# test failures related to randomization by passing the same `--seed` value
|
58
|
-
# as the one that triggered the failure.
|
59
15
|
Kernel.srand config.seed
|
60
16
|
end
|