Thank you to anyone who has already donated - your generous donations helped make three months of treatment possible.

My brother Nate continues to fight stage IV Hodgkin's lymphoma. He's just 31, with a wife and baby girl. They have no active income (since he's been unable to return to work), no insurance, and cannot afford the treatment he needs. Nate and his family need your help. Please consider a donation, every dollar helps. Thanks.



			
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index 55e1d48..2af6adc 100644
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -331,6 +331,14 @@ module ActionController #:nodoc:
     # Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers.
     cattr_accessor :logger

+    def self.logger
+      @@logger ||= ActiveSupport::NilLogger.new
+    end
+
+    def self.logger=(new_logger)
+      @@logger = new_logger.nil? ? ActiveSupport::NilLogger.new : new_logger
+    end
+
     # Controls the resource action separator
     @@resource_action_separator = "/"
     cattr_accessor :resource_action_separator
@@ -1067,7 +1075,7 @@ module ActionController #:nodoc:
         end

         response.redirected_to= options
-        logger.info("Redirected to #{options}") if logger && logger.info?
+        logger.info("Redirected to #{options}")

         case options
           when %r{^\w+://.*}
@@ -1125,7 +1133,7 @@ module ActionController #:nodoc:
     private
       def render_for_file(template_path, status = nil, use_full_path = nil, locals = {}) #:nodoc:
         add_variables_to_assigns
-        logger.info("Rendering #{template_path}" + (status ? " (#{status})" : '')) if logger
+        logger.info { "Rendering #{template_path}" << (status ? " (#{status})" : '') }
         render_for_text(@template.render(:file => template_path, :locals => locals), status)
       end

@@ -1171,7 +1179,7 @@ module ActionController #:nodoc:
       end

       def log_processing
-        if logger && logger.info?
+        if logger.info?
           logger.info "\n\nProcessing #{self.class.name}\##{action_name} (for #{request_origin}) [#{request.method.to_s.upcase}]"
           logger.info "  Session ID: #{@_session.session_id}" if @_session and @_session.respond_to?(:session_id)
           logger.info "  Parameters: #{respond_to?(:filter_parameters) ? filter_parameters(params).inspect : params.inspect}"
diff --git a/actionpack/lib/action_controller/benchmarking.rb b/actionpack/lib/action_controller/benchmarking.rb
index 98b0325..267b967 100644
--- a/actionpack/lib/action_controller/benchmarking.rb
+++ b/actionpack/lib/action_controller/benchmarking.rb
@@ -21,7 +21,7 @@ module ActionController #:nodoc:
       # easy to include benchmarking statements in production software that will remain inexpensive because the benchmark
       # will only be conducted if the log level is low enough.
       def benchmark(title, log_level = Logger::DEBUG, use_silence = true)
-        if logger && logger.level == log_level
+        if logger.level == log_level
           result = nil
           seconds = Benchmark.realtime { result = use_silence ? silence { yield } : yield }
           logger.add(log_level, "#{title} (#{'%.5f' % seconds})")
@@ -33,16 +33,16 @@ module ActionController #:nodoc:

       # Silences the logger for the duration of the block.
       def silence
-        old_logger_level, logger.level = logger.level, Logger::ERROR if logger
+        old_logger_level, logger.level = logger.level, Logger::ERROR
         yield
       ensure
-        logger.level = old_logger_level if logger
+        logger.level = old_logger_level
       end
     end

     protected
       def render_with_benchmark(options = nil, extra_options = {}, &block)
-        unless logger
+        unless logger.info?
           render_without_benchmark(options, extra_options, &block)
         else
           db_runtime = ActiveRecord::Base.connection.reset_runtime if Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected?
@@ -62,7 +62,7 @@ module ActionController #:nodoc:

     private
       def perform_action_with_benchmark
-        unless logger
+        unless logger.info?
           perform_action_without_benchmark
         else
           runtime = [ Benchmark::measure{ perform_action_without_benchmark }.real, 0.0001 ].max
diff --git a/actionpack/lib/action_controller/components.rb b/actionpack/lib/action_controller/components.rb
index 8275bd3..315089a 100644
--- a/actionpack/lib/action_controller/components.rb
+++ b/actionpack/lib/action_controller/components.rb
@@ -144,14 +144,10 @@ module ActionController #:nodoc:
         end

         def component_logging(options)
-          if logger
-            logger.info "Start rendering component (#{options.inspect}): "
-            result = yield
-            logger.info "\n\nEnd of component rendering"
-            result
-          else
-            yield
-          end
+          logger.info "Start rendering component (#{options.inspect}): "
+          result = yield
+          logger.info "\n\nEnd of component rendering"
+          result
         end

         def set_session_options_with_components(request)
diff --git a/actionpack/lib/action_controller/cookies.rb b/actionpack/lib/action_controller/cookies.rb
index 0428f2a..e97a113 100644
--- a/actionpack/lib/action_controller/cookies.rb
+++ b/actionpack/lib/action_controller/cookies.rb
@@ -99,7 +99,7 @@ module ActionController #:nodoc:
       def set_cookie(options) #:doc:
         options["path"] = "/" unless options["path"]
         cookie = CGI::Cookie.new(options)
-        @controller.logger.info "Cookie set: #{cookie}" unless @controller.logger.nil?
+        @controller.logger.info "Cookie set: #{cookie}"
         @controller.response.headers["cookie"] << cookie
       end
   end
diff --git a/actionpack/lib/action_controller/dispatcher.rb b/actionpack/lib/action_controller/dispatcher.rb
index bdae5f9..b15ffae 100644
--- a/actionpack/lib/action_controller/dispatcher.rb
+++ b/actionpack/lib/action_controller/dispatcher.rb
@@ -24,7 +24,7 @@ module ActionController
           to_prepare(:activerecord_instantiate_observers) { ActiveRecord::Base.instantiate_observers }
         end

-        after_dispatch :flush_logger if Base.logger && Base.logger.respond_to?(:flush)
+        after_dispatch :flush_logger if Base.logger.respond_to?(:flush)
       end

       # Backward-compatible class method takes CGI-specific args. Deprecated
diff --git a/actionpack/lib/action_controller/filters.rb b/actionpack/lib/action_controller/filters.rb
index 1d7236f..ee15d88 100644
--- a/actionpack/lib/action_controller/filters.rb
+++ b/actionpack/lib/action_controller/filters.rb
@@ -673,7 +673,7 @@ module ActionController #:nodoc:

         def halt_filter_chain(filter, reason)
           @before_filter_chain_aborted = true
-          logger.info "Filter chain halted as [#{filter.inspect}] #{reason}." if logger
+          logger.info "Filter chain halted as [#{filter.inspect}] #{reason}."
         end
     end
   end
diff --git a/actionpack/lib/action_controller/layout.rb b/actionpack/lib/action_controller/layout.rb
index 8b6febe..a3d064c 100644
--- a/actionpack/lib/action_controller/layout.rb
+++ b/actionpack/lib/action_controller/layout.rb
@@ -246,7 +246,7 @@ module ActionController #:nodoc:

         if (layout = pick_layout(template_with_options, options)) && apply_layout?(template_with_options, options)
           options = options.merge :layout => false if template_with_options
-          logger.info("Rendering template within #{layout}") if logger
+          logger.info("Rendering template within #{layout}")

           content_for_layout = render_with_no_layout(options, extra_options, &block)
           erase_render_results
diff --git a/actionpack/lib/action_controller/rescue.rb b/actionpack/lib/action_controller/rescue.rb
index a1a9d68..c82bdbd 100644
--- a/actionpack/lib/action_controller/rescue.rb
+++ b/actionpack/lib/action_controller/rescue.rb
@@ -115,7 +115,7 @@ module ActionController #:nodoc:
         if handler_for_rescue(exception)
           rescue_action_with_handler(exception)
         else
-          log_error(exception) if logger
+          log_error(exception) if logger.fatal?
           erase_results if performed?

           # Let the exception alter the response if it wants.
diff --git a/actionpack/lib/action_controller/streaming.rb b/actionpack/lib/action_controller/streaming.rb
index 333fb61..29c85d8 100644
--- a/actionpack/lib/action_controller/streaming.rb
+++ b/actionpack/lib/action_controller/streaming.rb
@@ -82,12 +82,12 @@ module ActionController #:nodoc:
         @performed_render = false

         if options[:x_sendfile]
-          logger.info "Sending #{X_SENDFILE_HEADER} header #{path}" if logger
+          logger.info "Sending #{X_SENDFILE_HEADER} header #{path}"
           head options[:status], X_SENDFILE_HEADER => path
         else
           if options[:stream]
             render :status => options[:status], :text => Proc.new { |response, output|
-              logger.info "Streaming file #{path}" unless logger.nil?
+              logger.info "Streaming file #{path}"
               len = options[:buffer_size] || 4096
               File.open(path, 'rb') do |file|
                 while buf = file.read(len)
@@ -96,7 +96,7 @@ module ActionController #:nodoc:
               end
             }
           else
-            logger.info "Sending file #{path}" unless logger.nil?
+            logger.info "Sending file #{path}"
             File.open(path, 'rb') { |file| render :status => options[:status], :text => file.read }
           end
         end
@@ -126,7 +126,7 @@ module ActionController #:nodoc:
       #
       # See +send_file+ for more information on HTTP Content-* headers and caching.
       def send_data(data, options = {}) #:doc:
-        logger.info "Sending data #{options[:filename]}" if logger
+        logger.info "Sending data #{options[:filename]}"
         send_file_headers! options.merge(:length => data.size)
         @performed_render = false
         render :status => options[:status], :text => data
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index c65048b..96aacdc 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -328,7 +328,7 @@ module ActionView #:nodoc:
       else
         template = Template.new(template_path, view_paths)

-        if self.class.warn_cache_misses && logger
+        if self.class.warn_cache_misses && logger.debug?
           logger.debug "[PERFORMANCE] Rendering a template that was " +
             "not found in view path. Templates outside the view path are " +
             "not cached and result in expensive disk operations. Move this " +
diff --git a/actionpack/lib/action_view/helpers/benchmark_helper.rb b/actionpack/lib/action_view/helpers/benchmark_helper.rb
index 743d1d4..30c26db 100644
--- a/actionpack/lib/action_view/helpers/benchmark_helper.rb
+++ b/actionpack/lib/action_view/helpers/benchmark_helper.rb
@@ -21,12 +21,8 @@ module ActionView
       # You may give an optional logger level as the second argument
       # (:debug, :info, :warn, :error); the default value is :info.
       def benchmark(message = "Benchmarking", level = :info)
-        if controller.logger
-          real = Benchmark.realtime { yield }
-          controller.logger.send(level, "#{message} (#{'%.5f' % real})")
-        else
-          yield
-        end
+        real = Benchmark.realtime { yield }
+        controller.logger.send(level, "#{message} (#{'%.5f' % real})")
       end
     end
   end
diff --git a/actionpack/test/controller/base_test.rb b/actionpack/test/controller/base_test.rb
index d49cc2a..0ad67bd 100644
--- a/actionpack/test/controller/base_test.rb
+++ b/actionpack/test/controller/base_test.rb
@@ -157,10 +157,13 @@ class PerformActionTest < Test::Unit::TestCase
   end

   def test_namespaced_action_should_log_module_name
+    original_logger = ActionController::Base.logger
     use_controller Submodule::ContainedNonEmptyController
-    @controller.logger = MockLogger.new
+    ActionController::Base.logger = MockLogger.new
     get :public_action
     assert_match /Processing\sSubmodule::ContainedNonEmptyController#public_action/, @controller.logger.logged[1]
+  ensure
+    ActionController::Base.logger = original_logger
   end
 end

diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb
index fab16a4..9cba62d 100644
--- a/activerecord/lib/active_record/attribute_methods.rb
+++ b/activerecord/lib/active_record/attribute_methods.rb
@@ -211,11 +211,9 @@ module ActiveRecord
             class_eval(method_definition, __FILE__, __LINE__)
           rescue SyntaxError => err
             generated_methods.delete(attr_name)
-            if logger
-              logger.warn "Exception occurred during reader method compilation."
-              logger.warn "Maybe #{attr_name} is not a valid Ruby identifier?"
-              logger.warn "#{err.message}"
-            end
+            logger.warn "Exception occurred during reader method compilation."
+            logger.warn "Maybe #{attr_name} is not a valid Ruby identifier?"
+            logger.warn "#{err.message}"
           end
         end
     end #  ClassMethods
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 5c30f80..2973a54 100644
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -392,6 +392,14 @@ module ActiveRecord #:nodoc:
     # on to any new database connections made and which can be retrieved on both a class and instance level by calling +logger+.
     cattr_accessor :logger, :instance_writer => false

+    def self.logger
+      @@logger ||= ActiveSupport::NilLogger.new
+    end
+
+    def self.logger=(new_logger)
+      @@logger = new_logger.nil? ? ActiveSupport::NilLogger.new : new_logger
+    end
+
     def self.inherited(child) #:nodoc:
       @@subclasses[self] ||= []
       @@subclasses[self] << child
@@ -1314,7 +1322,7 @@ module ActiveRecord #:nodoc:
       #
       # The logging of the multiple statements is turned off unless use_silence is set to false.
       def benchmark(title, log_level = Logger::DEBUG, use_silence = true)
-        if logger && logger.level <= log_level
+        if logger.level <= log_level
           result = nil
           seconds = Benchmark.realtime { result = use_silence ? silence { yield } : yield }
           logger.add(log_level, "#{title} (#{'%.5f' % seconds})")
@@ -1329,7 +1337,7 @@ module ActiveRecord #:nodoc:
         old_logger_level, logger.level = logger.level, Logger::ERROR if logger
         yield
       ensure
-        logger.level = old_logger_level if logger
+        logger.level = old_logger_level
       end

       # Overwrite the default class equality method to provide support for association proxies.
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb
index 2a8807f..154ce31 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb
@@ -39,7 +39,7 @@ module ActiveRecord

       # set concurrency support flag (not thread safe, like most of the methods in this file)
       def allow_concurrency=(threaded) #:nodoc:
-        logger.debug "allow_concurrency=#{threaded}" if logger
+        logger.debug "allow_concurrency=#{threaded}"
         return if @@allow_concurrency == threaded
         clear_all_cached_connections!
         @@allow_concurrency = threaded
@@ -48,7 +48,7 @@ module ActiveRecord
         [:active_connections, :scoped_methods].each do |method|
           sing.send(:alias_method, method, "#{method_prefix}_#{method}")
         end
-        log_connections if logger
+        log_connections
       end

       def active_connection_name #:nodoc:
@@ -299,11 +299,9 @@ module ActiveRecord

     # connection state logging
     def self.log_connections #:nodoc:
-      if logger
-        logger.info "Defined connections: #{@@defined_connections.inspect}"
-        logger.info "Active connections: #{active_connections.inspect}"
-        logger.info "Active connection name: #{@active_connection_name}"
-      end
+      logger.info "Defined connections: #{@@defined_connections.inspect}"
+      logger.info "Active connections: #{active_connections.inspect}"
+      logger.info "Active connection name: #{@active_connection_name}"
     end
   end
 end
diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb
index 622cfc3..81c5e08 100644
--- a/activerecord/lib/active_record/fixtures.rb
+++ b/activerecord/lib/active_record/fixtures.rb
@@ -859,9 +859,7 @@ module Test #:nodoc:

           # Let's warn in case this is a subdependency, otherwise
           # subdependency error messages are totally cryptic
-          if ActiveRecord::Base.logger
-            ActiveRecord::Base.logger.warn("Unable to load #{file_name}, underlying cause #{e.message} \n\n #{e.backtrace.join("\n")}")
-          end
+          ActiveRecord::Base.logger.warn("Unable to load #{file_name}, underlying cause #{e.message} \n\n #{e.backtrace.join("\n")}")
         end

         def require_fixture_classes(table_names = nil)
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index c811135..7b7a724 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -2010,4 +2010,18 @@ class BasicsTest < ActiveRecord::TestCase
   ensure
     ActiveRecord::Base.logger = original_logger
   end
+
+  def test_benchmark_with_nil_logger
+    original_logger = ActiveRecord::Base.logger
+    testing = nil
+    ActiveRecord::Base.logger = nil
+    assert_kind_of ActiveSupport::NilLogger, ActiveRecord::Base.logger
+    assert_nothing_raised do
+      ActiveRecord::Base.benchmark("Logging", Logger::DEBUG, true) { testing = "Works" }
+    end
+    assert_equal 'Works', testing
+  ensure
+    ActiveRecord::Base.logger = original_logger
+  end
+
 end
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb
index 7e34a87..7192bf3 100644
--- a/activesupport/lib/active_support.rb
+++ b/activesupport/lib/active_support.rb
@@ -29,6 +29,7 @@ require 'active_support/callbacks'
 require 'active_support/core_ext'

 require 'active_support/buffered_logger'
+require 'active_support/nil_logger'

 require 'active_support/gzip'
 require 'active_support/cache'
diff --git a/activesupport/lib/active_support/nil_logger.rb b/activesupport/lib/active_support/nil_logger.rb
new file mode 100644
index 0000000..c4aa3d9
--- /dev/null
+++ b/activesupport/lib/active_support/nil_logger.rb
@@ -0,0 +1,38 @@
+module ActiveSupport #:nodoc:
+  # Dummy logger class
+  class NilLogger #:nodoc:
+    def initialize(*args)
+    end
+
+    def silence(*args)
+      yield self
+    end
+    
+    def level
+      1.0/0.0
+    end
+
+    def level=(*args)
+    end
+
+    def add(*args)
+    end
+
+    def close
+    end
+
+    def <<(*args)
+    end
+
+    [:debug, :info, :warn, :error, :fatal, :unknonw].each do |severity|
+      class_eval <<-EOT, __FILE__, __LINE__
+        def #{severity}(*args)
+        end
+
+        def #{severity}?
+          false
+        end
+      EOT
+    end
+  end
+end
diff --git a/activesupport/test/nil_logger_test.rb b/activesupport/test/nil_logger_test.rb
new file mode 100644
index 0000000..e5f8221
--- /dev/null
+++ b/activesupport/test/nil_logger_test.rb
@@ -0,0 +1,46 @@
+require 'abstract_unit'
+
+class NilLoggerTest < Test::Unit::TestCase
+  def setup
+    @logger = ActiveSupport::NilLogger.new
+  end
+
+  def test_initialize_should_take_any_args
+    assert_nothing_raised do
+      ActiveSupport::NilLogger.new
+      ActiveSupport::NilLogger.new(1)
+      ActiveSupport::NilLogger.new(:hello, :nil)
+    end
+  end
+
+  def test_should_respond_to_logger_methods
+    [:debug, :info, :warn, :error, :fatal, :unknonw].each do |m|
+      assert @logger.respond_to?(m), "ActiveSupport::NilLogger does not respond to :#{m}"
+      assert !@logger.send(:"#{m}?")
+    end
+  end
+
+  def test_should_respond_to_add
+    assert @logger.respond_to?(:add)
+  end
+
+  def test_should_respond_to_close
+    assert @logger.respond_to?(:close)
+  end
+
+  def test_should_respond_to_append
+    assert_nothing_raised { @logger << 'Hello Log' }
+  end
+
+  def test_should_have_infinite_level
+    assert_equal 'Infinity', @logger.level.to_s
+  end
+
+  def test_should_take_silence_block_and_execute
+    done = false
+    @logger.silence do
+      done = true
+    end
+    assert done
+  end
+end