timber 1.1.14 → 2.0.0
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.
- checksums.yaml +4 -4
- data/.gitignore +4 -2
- data/.travis.yml +47 -0
- data/Gemfile +1 -28
- data/README.md +83 -298
- data/bin/timber +13 -0
- data/gemfiles/rails-3.0.gemfile +5 -0
- data/gemfiles/rails-3.1.gemfile +5 -0
- data/gemfiles/rails-3.2.gemfile +5 -0
- data/gemfiles/rails-4.0.gemfile +9 -0
- data/gemfiles/rails-4.1.gemfile +9 -0
- data/gemfiles/rails-4.2.gemfile +9 -0
- data/gemfiles/rails-5.0.gemfile +9 -0
- data/gemfiles/rails-edge.gemfile +7 -0
- data/lib/timber.rb +7 -7
- data/lib/timber/cli.rb +72 -0
- data/lib/timber/cli/api.rb +104 -0
- data/lib/timber/cli/application.rb +28 -0
- data/lib/timber/cli/install.rb +186 -0
- data/lib/timber/cli/io_helper.rb +58 -0
- data/lib/timber/cli/messages.rb +170 -0
- data/lib/timber/config.rb +47 -6
- data/lib/timber/contexts/http.rb +2 -2
- data/lib/timber/current_context.rb +1 -1
- data/lib/timber/event.rb +8 -0
- data/lib/timber/events.rb +2 -0
- data/lib/timber/events/controller_call.rb +12 -3
- data/lib/timber/events/exception.rb +4 -3
- data/lib/timber/events/http_client_request.rb +61 -0
- data/lib/timber/events/http_client_response.rb +47 -0
- data/lib/timber/events/http_server_request.rb +15 -23
- data/lib/timber/events/http_server_response.rb +9 -9
- data/lib/timber/events/sql_query.rb +2 -2
- data/lib/timber/events/template_render.rb +2 -2
- data/lib/timber/frameworks/rails.rb +31 -6
- data/lib/timber/integrations.rb +22 -0
- data/lib/timber/integrations/action_controller/log_subscriber.rb +25 -0
- data/lib/timber/integrations/action_controller/log_subscriber/timber_log_subscriber.rb +40 -0
- data/lib/timber/integrations/action_dispatch/debug_exceptions.rb +51 -0
- data/lib/timber/integrations/action_view/log_subscriber.rb +25 -0
- data/lib/timber/integrations/action_view/log_subscriber/timber_log_subscriber.rb +73 -0
- data/lib/timber/integrations/active_record/log_subscriber.rb +25 -0
- data/lib/timber/integrations/active_record/log_subscriber/timber_log_subscriber.rb +39 -0
- data/lib/timber/integrations/active_support/tagged_logging.rb +71 -0
- data/lib/timber/integrations/rack.rb +16 -0
- data/lib/timber/integrations/rack/exception_event.rb +28 -0
- data/lib/timber/integrations/rack/http_context.rb +25 -0
- data/lib/timber/integrations/rack/http_events.rb +46 -0
- data/lib/timber/integrations/rack/user_context.rb +59 -0
- data/lib/timber/integrations/rails/rack_logger.rb +49 -0
- data/lib/timber/integrator.rb +24 -0
- data/lib/timber/log_devices/http.rb +14 -21
- data/lib/timber/log_entry.rb +1 -1
- data/lib/timber/logger.rb +38 -12
- data/lib/timber/overrides.rb +9 -0
- data/lib/timber/overrides/lograge.rb +14 -0
- data/lib/timber/overrides/rails_server.rb +10 -0
- data/lib/timber/util.rb +2 -0
- data/lib/timber/util/active_support_log_subscriber.rb +13 -9
- data/lib/timber/util/http_event.rb +54 -0
- data/lib/timber/util/request.rb +44 -0
- data/lib/timber/version.rb +1 -1
- data/spec/README.md +5 -9
- data/spec/spec_helper.rb +1 -4
- data/spec/support/action_controller.rb +7 -3
- data/spec/support/active_record.rb +23 -19
- data/spec/support/rails.rb +56 -32
- data/spec/support/timber.rb +2 -3
- data/spec/support/webmock.rb +1 -0
- data/spec/timber/integrations/action_controller/log_subscriber_spec.rb +55 -0
- data/spec/timber/integrations/action_dispatch/debug_exceptions_spec.rb +53 -0
- data/spec/timber/integrations/action_view/log_subscriber_spec.rb +115 -0
- data/spec/timber/integrations/active_record/log_subscriber_spec.rb +46 -0
- data/spec/timber/integrations/rack/http_context_spec.rb +60 -0
- data/spec/timber/integrations/rails/rack_logger_spec.rb +58 -0
- data/spec/timber/logger_spec.rb +45 -9
- data/timber.gemspec +29 -3
- metadata +143 -46
- data/Appraisals +0 -41
- data/circle.yml +0 -33
- data/lib/timber/overrides/logger_add.rb +0 -38
- data/lib/timber/probe.rb +0 -23
- data/lib/timber/probes.rb +0 -23
- data/lib/timber/probes/action_controller_log_subscriber.rb +0 -20
- data/lib/timber/probes/action_controller_log_subscriber/log_subscriber.rb +0 -64
- data/lib/timber/probes/action_controller_user_context.rb +0 -52
- data/lib/timber/probes/action_dispatch_debug_exceptions.rb +0 -80
- data/lib/timber/probes/action_view_log_subscriber.rb +0 -20
- data/lib/timber/probes/action_view_log_subscriber/log_subscriber.rb +0 -69
- data/lib/timber/probes/active_record_log_subscriber.rb +0 -20
- data/lib/timber/probes/active_record_log_subscriber/log_subscriber.rb +0 -31
- data/lib/timber/probes/active_support_tagged_logging.rb +0 -63
- data/lib/timber/probes/rails_rack_logger.rb +0 -77
- data/lib/timber/rack_middlewares.rb +0 -12
- data/lib/timber/rack_middlewares/http_context.rb +0 -30
- data/spec/support/action_view.rb +0 -4
- data/spec/support/coveralls.rb +0 -2
- data/spec/support/simplecov.rb +0 -9
- data/spec/timber/overrides/logger_add_spec.rb +0 -26
- data/spec/timber/probes/action_controller_log_subscriber_spec.rb +0 -65
- data/spec/timber/probes/action_controller_user_context_spec.rb +0 -53
- data/spec/timber/probes/action_dispatch_debug_exceptions_spec.rb +0 -48
- data/spec/timber/probes/action_view_log_subscriber_spec.rb +0 -107
- data/spec/timber/probes/active_record_log_subscriber_spec.rb +0 -47
- data/spec/timber/probes/rails_rack_logger_spec.rb +0 -46
- data/spec/timber/rack_middlewares/http_context_spec.rb +0 -47
data/lib/timber/log_entry.rb
CHANGED
|
@@ -3,7 +3,7 @@ module Timber
|
|
|
3
3
|
# `Logger` and the log device that you set it up with.
|
|
4
4
|
class LogEntry #:nodoc:
|
|
5
5
|
DT_PRECISION = 6.freeze
|
|
6
|
-
SCHEMA = "https://raw.githubusercontent.com/timberio/log-event-json-schema/1.2.
|
|
6
|
+
SCHEMA = "https://raw.githubusercontent.com/timberio/log-event-json-schema/1.2.20/schema.json".freeze
|
|
7
7
|
|
|
8
8
|
attr_reader :context_snapshot, :event, :level, :message, :progname, :tags, :time, :time_ms
|
|
9
9
|
|
data/lib/timber/logger.rb
CHANGED
|
@@ -16,7 +16,7 @@ module Timber
|
|
|
16
16
|
# @example Using a Hash
|
|
17
17
|
# # The :message key is required, the other additional key is your event type and data
|
|
18
18
|
# # :type is the namespace used in timber for the :data
|
|
19
|
-
# logger.info
|
|
19
|
+
# logger.info "Payment rejected", payment_rejected: {customer_id: customer_id, amount: 100}
|
|
20
20
|
#
|
|
21
21
|
# @example Using a Struct (a simple, more structured way, to define events)
|
|
22
22
|
# PaymentRejectedEvent = Struct.new(:customer_id, :amount, :reason) do
|
|
@@ -69,7 +69,7 @@ module Timber
|
|
|
69
69
|
"INFO" => :info,
|
|
70
70
|
"WARN" => :warn,
|
|
71
71
|
"ERROR" => :error,
|
|
72
|
-
"FATAL" => :
|
|
72
|
+
"FATAL" => :fatal,
|
|
73
73
|
"UNKNOWN" => :unknown
|
|
74
74
|
}
|
|
75
75
|
|
|
@@ -81,9 +81,12 @@ module Timber
|
|
|
81
81
|
tags = extract_active_support_tagged_logging_tags
|
|
82
82
|
time_ms = nil
|
|
83
83
|
if msg.is_a?(Hash)
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
if msg.key?(:tag) || msg.key?(:tags)
|
|
85
|
+
tags = tags.clone
|
|
86
|
+
tags << msg.delete(:tag) if msg.key?(:tag)
|
|
87
|
+
tags += msg.delete(:tags) if msg.key?(:tags)
|
|
88
|
+
tags.uniq!
|
|
89
|
+
end
|
|
87
90
|
time_ms = msg.delete(:time_ms) if msg.key?(:time_ms)
|
|
88
91
|
|
|
89
92
|
msg = msg[:message] if msg.length == 1
|
|
@@ -106,6 +109,16 @@ module Timber
|
|
|
106
109
|
end
|
|
107
110
|
end
|
|
108
111
|
|
|
112
|
+
# For use in development and test environments where you do not want metadata
|
|
113
|
+
# included in the log lines.
|
|
114
|
+
class SimpleFormatter < Formatter
|
|
115
|
+
|
|
116
|
+
# This method is invoked when a log event occurs
|
|
117
|
+
def call(severity, timestamp, progname, msg)
|
|
118
|
+
"#{String === msg ? msg : msg.inspect}\n"
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
109
122
|
# Structures your log messages into Timber's hybrid format, which makes
|
|
110
123
|
# it easy to read while also appending the appropriate metadata.
|
|
111
124
|
#
|
|
@@ -153,6 +166,11 @@ module Timber
|
|
|
153
166
|
end
|
|
154
167
|
end
|
|
155
168
|
|
|
169
|
+
class << self
|
|
170
|
+
def new_from_config
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
156
174
|
# Creates a new Timber::Logger instances. Accepts the same arguments as `::Logger.new`.
|
|
157
175
|
# The only difference is that it default the formatter to {HybridFormatter}. Using
|
|
158
176
|
# a different formatter is easy. For example, if you prefer your logs in JSON.
|
|
@@ -175,26 +193,34 @@ module Timber
|
|
|
175
193
|
end
|
|
176
194
|
|
|
177
195
|
self.level = environment_level
|
|
196
|
+
|
|
197
|
+
@initialized = true
|
|
178
198
|
end
|
|
179
199
|
|
|
180
200
|
def formatter=(value)
|
|
181
|
-
if @dev.is_a?(Timber::LogDevices::HTTP)
|
|
201
|
+
if @initialized && @logdev && @logdev.dev.is_a?(Timber::LogDevices::HTTP) && !value.is_a?(PassThroughFormatter)
|
|
182
202
|
raise ArgumentError.new("The formatter cannot be changed when using the " +
|
|
183
203
|
"Timber::LogDevices::HTTP log device. The PassThroughFormatter must be used for proper " +
|
|
184
204
|
"delivery.")
|
|
185
205
|
end
|
|
186
206
|
|
|
187
|
-
|
|
188
|
-
# silently discard this value since rails calls this during initialization :/
|
|
189
|
-
nil
|
|
190
|
-
else
|
|
191
|
-
super
|
|
192
|
-
end
|
|
207
|
+
super
|
|
193
208
|
end
|
|
194
209
|
|
|
195
210
|
# Backwards compatibility with older ActiveSupport::Logger versions
|
|
196
211
|
Logger::Severity.constants.each do |severity|
|
|
197
212
|
class_eval(<<-EOT, __FILE__, __LINE__ + 1)
|
|
213
|
+
def #{severity.downcase}(*args, &block)
|
|
214
|
+
progname = args.first
|
|
215
|
+
options = args.last
|
|
216
|
+
|
|
217
|
+
if args.length == 2 and options.is_a?(Hash) && options != {}
|
|
218
|
+
progname = options.merge(message: progname)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
add(#{severity}, nil, progname, &block)
|
|
222
|
+
end
|
|
223
|
+
|
|
198
224
|
def #{severity.downcase}? # def debug?
|
|
199
225
|
Logger::#{severity} >= level # DEBUG >= level
|
|
200
226
|
end # end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Timber and lograge are not compatible installed together. Using lograge
|
|
2
|
+
# with the Timber.io *service* is perfectly fine, but not with the Timber *gem*.
|
|
3
|
+
begin
|
|
4
|
+
require "lograge"
|
|
5
|
+
|
|
6
|
+
module Lograge
|
|
7
|
+
module_function
|
|
8
|
+
|
|
9
|
+
def setup(app)
|
|
10
|
+
return true
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
rescue Exception
|
|
14
|
+
end
|
data/lib/timber/util.rb
CHANGED
|
@@ -5,7 +5,7 @@ module Timber
|
|
|
5
5
|
extend self
|
|
6
6
|
|
|
7
7
|
def find(component, type)
|
|
8
|
-
ActiveSupport::LogSubscriber.log_subscribers.find do |subscriber|
|
|
8
|
+
::ActiveSupport::LogSubscriber.log_subscribers.find do |subscriber|
|
|
9
9
|
subscriber.class == type
|
|
10
10
|
end
|
|
11
11
|
end
|
|
@@ -14,16 +14,20 @@ module Timber
|
|
|
14
14
|
!find(component, type).nil?
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
# I don't know why this has to be so complicated, but it is. This code was taken from
|
|
18
|
+
# lograge :/
|
|
19
|
+
def unsubscribe!(component, type)
|
|
18
20
|
subscriber = find(component, type)
|
|
19
21
|
|
|
20
|
-
if subscriber
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
if !subscriber
|
|
23
|
+
raise "We could not find a log subscriber for #{component.inspect} of type #{type.inspect}"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
events = subscriber.public_methods(false).reject { |method| method.to_s == 'call' }
|
|
27
|
+
events.each do |event|
|
|
28
|
+
::ActiveSupport::Notifications.notifier.listeners_for("#{event}.#{component}").each do |listener|
|
|
29
|
+
if listener.instance_variable_get('@delegate') == subscriber
|
|
30
|
+
::ActiveSupport::Notifications.unsubscribe listener
|
|
27
31
|
end
|
|
28
32
|
end
|
|
29
33
|
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module Timber
|
|
2
|
+
module Util
|
|
3
|
+
module HTTPEvent
|
|
4
|
+
BODY_LIMIT = 5_000.freeze
|
|
5
|
+
QUERY_STRING_LIMIT = 5_000.freeze
|
|
6
|
+
|
|
7
|
+
extend self
|
|
8
|
+
|
|
9
|
+
def full_path(path, query_string)
|
|
10
|
+
if query_string
|
|
11
|
+
"#{path}?#{query_string}"
|
|
12
|
+
else
|
|
13
|
+
path
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def normalize_body(content_type, body)
|
|
18
|
+
if Config.instance.capture_http_body_content_types.include?(content_type)
|
|
19
|
+
if body.respond_to?(:body)
|
|
20
|
+
body = body.body.to_s
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
body[0..(BODY_LIMIT - 1)]
|
|
24
|
+
else
|
|
25
|
+
# Drop the body if it is not a format we want to capture.
|
|
26
|
+
# This gives users more control to avoid loggin files, etc.
|
|
27
|
+
nil
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def normalize_headers(headers)
|
|
32
|
+
if headers.is_a?(::Hash)
|
|
33
|
+
headers.each_with_object({}) do |(k, v), h|
|
|
34
|
+
h[k.to_s.downcase] = v
|
|
35
|
+
end
|
|
36
|
+
else
|
|
37
|
+
headers
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def normalize_method(method)
|
|
42
|
+
method.is_a?(::String) ? method.upcase : method
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def normalize_query_string(query_string)
|
|
46
|
+
if !query_string.nil?
|
|
47
|
+
query_string = query_string.to_s
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
query_string[0..(QUERY_STRING_LIMIT - 1)]
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require "rack"
|
|
3
|
+
rescue LoadError
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
if defined?(::Rack::Request)
|
|
7
|
+
module Timber
|
|
8
|
+
module Util
|
|
9
|
+
class Request < ::Rack::Request
|
|
10
|
+
def body_content
|
|
11
|
+
content = body.read
|
|
12
|
+
body.rewind
|
|
13
|
+
content
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def headers
|
|
17
|
+
@headers ||= ::Hash[*@env.select {|k,v| k.start_with? 'HTTP_'}
|
|
18
|
+
.collect {|k,v| [k.sub(/^HTTP_/, ''), v]}
|
|
19
|
+
.collect {|k,v| [k.split('_').collect(&:capitalize).join('-'), v]}
|
|
20
|
+
.sort
|
|
21
|
+
.flatten]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def ip
|
|
25
|
+
@ip ||= if @env["action_dispatch.remote_ip"]
|
|
26
|
+
@env["action_dispatch.remote_ip"].to_s || super
|
|
27
|
+
else
|
|
28
|
+
super
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def referer
|
|
33
|
+
# Rails 3.X returns "/" for some reason
|
|
34
|
+
@referer ||= super == "/" ? nil : super
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def request_id
|
|
38
|
+
@request_id ||= @env["action_dispatch.request_id"] || @env["X-Request-ID"] ||
|
|
39
|
+
@env["X-Request-Id"]
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
data/lib/timber/version.rb
CHANGED
data/spec/README.md
CHANGED
|
@@ -1,23 +1,19 @@
|
|
|
1
1
|
# Testing
|
|
2
2
|
|
|
3
|
-
Testing Timber uses [`appraisal`](https://github.com/thoughtbot/appraisal). This allows us to
|
|
4
|
-
test across multiple versions and combinations of libraries.
|
|
5
|
-
|
|
6
3
|
To get started:
|
|
7
4
|
|
|
8
5
|
```shell
|
|
9
6
|
bundle install
|
|
10
|
-
bundle exec appraisal install
|
|
11
7
|
```
|
|
12
8
|
|
|
13
|
-
|
|
9
|
+
Be sure to install specific Gemfile dependencies:
|
|
14
10
|
|
|
15
|
-
```
|
|
16
|
-
|
|
11
|
+
```
|
|
12
|
+
BUNDLE_GEMFILE=gemfiles/rails-4.2.gemfile bundle install
|
|
17
13
|
```
|
|
18
14
|
|
|
19
|
-
You can run tests
|
|
15
|
+
You can run tests like this:
|
|
20
16
|
|
|
21
17
|
```shell
|
|
22
|
-
|
|
18
|
+
BUNDLE_GEMFILE=gemfiles/rails-4.2.gemfile bundle exec rspec
|
|
23
19
|
```
|
data/spec/spec_helper.rb
CHANGED
|
@@ -3,23 +3,20 @@ require 'rubygems'
|
|
|
3
3
|
require 'bundler/setup'
|
|
4
4
|
|
|
5
5
|
# Testing
|
|
6
|
-
require 'pry'
|
|
7
6
|
require 'rspec'
|
|
8
7
|
require 'rspec/its'
|
|
9
8
|
require 'rspec/mocks'
|
|
10
9
|
|
|
11
10
|
# Support files, order is relevant
|
|
12
|
-
require File.join(File.dirname(__FILE__), 'support', 'coveralls')
|
|
13
11
|
require File.join(File.dirname(__FILE__), 'support', 'socket_hostname')
|
|
14
|
-
require File.join(File.dirname(__FILE__), 'support', 'simplecov')
|
|
15
12
|
require File.join(File.dirname(__FILE__), 'support', 'timecop')
|
|
16
13
|
require File.join(File.dirname(__FILE__), 'support', 'webmock')
|
|
17
14
|
require File.join(File.dirname(__FILE__), 'support', 'timber')
|
|
18
15
|
|
|
16
|
+
# Load framework files after we've setup everything
|
|
19
17
|
if !ENV["RAILS_23"]
|
|
20
18
|
require File.join(File.dirname(__FILE__), 'support', 'rails')
|
|
21
19
|
require File.join(File.dirname(__FILE__), 'support', 'action_controller')
|
|
22
|
-
require File.join(File.dirname(__FILE__), 'support', 'action_view')
|
|
23
20
|
require File.join(File.dirname(__FILE__), 'support', 'active_record')
|
|
24
21
|
end
|
|
25
22
|
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
begin
|
|
2
|
+
require "action_controller"
|
|
3
|
+
rescue LoadError
|
|
4
|
+
end
|
|
2
5
|
|
|
3
|
-
ActionController::Base
|
|
4
|
-
ActionController::Base.
|
|
6
|
+
if defined?(::ActionController::Base)
|
|
7
|
+
::ActionController::Base.prepend_view_path("#{File.dirname(__FILE__)}/rails/templates")
|
|
8
|
+
end
|
|
@@ -1,28 +1,32 @@
|
|
|
1
|
-
|
|
1
|
+
begin
|
|
2
|
+
require 'active_record'
|
|
3
|
+
rescue LoadError
|
|
4
|
+
end
|
|
2
5
|
|
|
3
|
-
ActiveRecord::Base
|
|
4
|
-
ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
|
|
5
|
-
ActiveRecord::Schema.define do
|
|
6
|
-
|
|
6
|
+
if defined?(::ActiveRecord::Base)
|
|
7
|
+
ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
|
|
8
|
+
ActiveRecord::Schema.define do
|
|
9
|
+
self.verbose = false
|
|
7
10
|
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
create_table :organizations, :force => true do |t|
|
|
12
|
+
t.string :name
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
t.timestamps :null => false
|
|
15
|
+
end
|
|
13
16
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
create_table :users, :force => true do |t|
|
|
18
|
+
t.integer :age
|
|
19
|
+
t.string :email
|
|
20
|
+
t.string :first_name
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
t.timestamps :null => false
|
|
23
|
+
end
|
|
21
24
|
|
|
22
|
-
end
|
|
25
|
+
end
|
|
23
26
|
|
|
24
|
-
class Organization < ::ActiveRecord::Base
|
|
25
|
-
end
|
|
27
|
+
class Organization < ::ActiveRecord::Base
|
|
28
|
+
end
|
|
26
29
|
|
|
27
|
-
class User < ::ActiveRecord::Base
|
|
30
|
+
class User < ::ActiveRecord::Base
|
|
31
|
+
end
|
|
28
32
|
end
|
data/spec/support/rails.rb
CHANGED
|
@@ -1,37 +1,61 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
# responsible for setting up the logger
|
|
5
|
-
logger = ::Logger.new(STDOUT) # change to STDOUT to see rails logs
|
|
6
|
-
Rails.logger = logger
|
|
7
|
-
|
|
8
|
-
class RailsApp < Rails::Application
|
|
9
|
-
if ::Rails.version =~ /^3\./
|
|
10
|
-
config.secret_token = '1e05af2b349457936a41427e63450937'
|
|
11
|
-
else
|
|
12
|
-
config.secret_key_base = '1e05af2b349457936a41427e63450937'
|
|
13
|
-
end
|
|
14
|
-
config.active_support.deprecation = :stderr
|
|
15
|
-
config.eager_load = false
|
|
1
|
+
begin
|
|
2
|
+
require "rails"
|
|
3
|
+
rescue LoadError
|
|
16
4
|
end
|
|
17
5
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
env = env.merge(additional_env_options)
|
|
30
|
-
::Rack::MockRequest.new(application).get(path, env)
|
|
6
|
+
if defined?(::Rails)
|
|
7
|
+
# Defualt the rails logger to nothing, each test shoould be
|
|
8
|
+
# responsible for setting up the logger
|
|
9
|
+
logger = Timber::Logger.new(nil) # change to STDOUT to see rails logs
|
|
10
|
+
Rails.logger = logger
|
|
11
|
+
|
|
12
|
+
class RailsApp < Rails::Application
|
|
13
|
+
if ::Rails.version =~ /^3\./
|
|
14
|
+
config.secret_token = '1e05af2b349457936a41427e63450937'
|
|
15
|
+
else
|
|
16
|
+
config.secret_key_base = '1e05af2b349457936a41427e63450937'
|
|
31
17
|
end
|
|
18
|
+
|
|
19
|
+
# This ensures our tests fail, otherwise exceptions get swallowed by ActionDispatch::DebugExceptions
|
|
20
|
+
config.action_dispatch.show_exceptions = false
|
|
21
|
+
config.active_support.deprecation = :stderr
|
|
22
|
+
config.eager_load = false
|
|
32
23
|
end
|
|
33
|
-
end
|
|
34
24
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
25
|
+
RailsApp.initialize!
|
|
26
|
+
|
|
27
|
+
module Support
|
|
28
|
+
module Rails
|
|
29
|
+
def dispatch_rails_request(path, additional_env_options = {})
|
|
30
|
+
application = ::Rails.application
|
|
31
|
+
env = application.respond_to?(:env_config) ? application.env_config.clone : application.env_defaults.clone
|
|
32
|
+
env["rack.request.cookie_hash"] = {}.with_indifferent_access
|
|
33
|
+
env["REMOTE_ADDR"] = "123.456.789.10"
|
|
34
|
+
env["HTTP_X_REQUEST_ID"] = "unique-request-id-1234"
|
|
35
|
+
env["action_dispatch.request_id"] = env["HTTP_X_REQUEST_ID"]
|
|
36
|
+
env = env.merge(additional_env_options)
|
|
37
|
+
::Rack::MockRequest.new(application).get(path, env)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def with_rails_logger(logger)
|
|
41
|
+
old_logger = ::Rails.logger
|
|
42
|
+
|
|
43
|
+
# We have to set these again because rails set's these after initialization.
|
|
44
|
+
# Since we've already booted the rails app we need to update them all as we
|
|
45
|
+
# change the logger.
|
|
46
|
+
#
|
|
47
|
+
# You can see here that they use simple class attribute, hence the reason we need
|
|
48
|
+
# to update all of them: https://github.com/rails/rails/blob/700ec897f97c60016ad748236bf3a49ef15a20de/actionview/lib/action_view/base.rb#L157
|
|
49
|
+
Timber::Frameworks::Rails.set_logger(logger)
|
|
50
|
+
|
|
51
|
+
yield
|
|
52
|
+
|
|
53
|
+
::Rails.logger = old_logger
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
RSpec.configure do |config|
|
|
59
|
+
config.include Support::Rails
|
|
60
|
+
end
|
|
61
|
+
end
|