lib/timber/frameworks/rails.rb in timber-2.0.15 vs lib/timber/frameworks/rails.rb in timber-2.0.16

- old
+ new

@@ -1,28 +1,68 @@ module Timber module Frameworks # Module for Rails specific code, such as the Railtie and any methods that assist # with Rails setup. module Rails + # Because of the crazy way Rails sorts it's initializers, it is + # impossible for Timber to be inserted after Devise's omnitauth + # middlewares. + # See: https://github.com/plataformatec/devise/blob/master/lib/devise/rails.rb#L22 + # As such, we take a brute force approach here, ensuring we are inserted last + # no matter what. This ensures that we come after authentication so that we can + # properly set the user context. + # + # @private + module MiddlewareStackProxyFix + def self.included(klass) + klass.class_eval do + attr_accessor :timber_operations + + alias old_merge_into merge_into + + # This method does not exist for older versions of rails + begin + alias old_plus + + rescue NameError + end + + def +(*args) + result = old_plus(*args) + result.timber_operations = timber_operations + result + end + + def merge_into(*args) + if timber_operations + @operations -= timber_operations + @operations += timber_operations + end + old_merge_into(*args) + end + end + end + end + + ::Rails::Configuration::MiddlewareStackProxy.send(:include, MiddlewareStackProxyFix) + # Installs Timber into your Rails app automatically. class Railtie < ::Rails::Railtie config.timber = Config.instance # Initialize Timber immediately after the logger in case anything uses the logger # during the initialization process. - initializer(:timber, group: :all, after: :initialize_logger) do + initializer(:timber, after: :initialize_logger) do logger = Rails.ensure_timber_logger(::Rails.logger) Rails.set_logger(logger) Integrations.integrate! - end - # Ensures that we insert the middlewares last. We need to insert these last - # because initializers, such as Omniauth, insert middleware. If we are not - # after these initializers we will not capture user context, for example. - initializer(:timber_middlewares, after: :engines_blank_point) do - Rails.configure_middlewares(config.app_middleware) + timber_operations = Integrations::Rack.middlewares.collect do |middleware_class| + [:use, [middleware_class], nil] + end + + config.app_middleware.timber_operations = timber_operations end end # This builds a new Timber::Logger from an existing logger. This allows us to transparentl # switch users onto the Timber::Logger since we support a more useful logging API. @@ -57,20 +97,9 @@ ::ActionController::Base.logger = logger if defined?(::ActionController::Base) && ::ActionController::Base.respond_to?(:logger=) ::ActionMailer::Base.logger = logger if defined?(::ActionMailer::Base) && ::ActionMailer::Base.respond_to?(:logger=) ::ActionView::Base.logger = logger if defined?(::ActionView::Base) && ::ActionView::Base.respond_to?(:logger=) ::ActiveRecord::Base.logger = logger if defined?(::ActiveRecord::Base) && ::ActiveRecord::Base.respond_to?(:logger=) ::Rails.logger = logger - end - - def self.configure_middlewares(middleware) - var_name = :"@_timber_middlewares_inserted" - return true if middleware.instance_variable_defined?(var_name) && middleware.instance_variable_get(var_name) == true - - # Rails uses a proxy :/, so we need to do this instance variable hack - middleware.instance_variable_set(var_name, true) - Integrations::Rack.middlewares.each do |middleware_class| - middleware.use middleware_class - end end end end end \ No newline at end of file