diff options
Diffstat (limited to 'activesupport')
17 files changed, 138 insertions, 172 deletions
diff --git a/activesupport/README b/activesupport/README.rdoc index 9fb9a80cbe..aa86f1fd65 100644 --- a/activesupport/README +++ b/activesupport/README.rdoc @@ -7,22 +7,13 @@ Ruby sweeter. == Download -The latest version of Active Support can be found at +The latest version of Active Support can be installed with Rubygems: -* http://rubyforge.org/project/showfiles.php?group_id=182 +* gem install activesupport Documentation can be found at -* http://as.rubyonrails.com - - -== Installation - -The preferred method of installing Active Support is through its GEM file. You'll need to have -RubyGems[http://rubygems.rubyforge.org/wiki/wiki.pl] installed for that, though. If you have it, -then use: - - % [sudo] gem install activesupport-1.0.0.gem +* http://api.rubyonrails.org == License diff --git a/activesupport/Rakefile b/activesupport/Rakefile index 2aebe05de2..77b1a8431d 100644 --- a/activesupport/Rakefile +++ b/activesupport/Rakefile @@ -28,7 +28,7 @@ Rake::RDocTask.new { |rdoc| rdoc.options << '--line-numbers' << '--inline-source' rdoc.options << '--charset' << 'utf-8' rdoc.template = ENV['template'] ? "#{ENV['template']}.rb" : '../doc/template/horo' - rdoc.rdoc_files.include('README', 'CHANGELOG') + rdoc.rdoc_files.include('README.rdoc', 'CHANGELOG') rdoc.rdoc_files.include('lib/active_support.rb') rdoc.rdoc_files.include('lib/active_support/**/*.rb') } diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec index 8611a1e5fa..df7f68fecf 100644 --- a/activesupport/activesupport.gemspec +++ b/activesupport/activesupport.gemspec @@ -14,7 +14,7 @@ Gem::Specification.new do |s| s.homepage = 'http://www.rubyonrails.org' s.rubyforge_project = 'activesupport' - s.files = Dir['CHANGELOG', 'README', 'lib/**/*'] + s.files = Dir['CHANGELOG', 'README.rdoc', 'lib/**/*'] s.require_path = 'lib' s.has_rdoc = true diff --git a/activesupport/install.rb b/activesupport/install.rb deleted file mode 100644 index 9c54d8c1a9..0000000000 --- a/activesupport/install.rb +++ /dev/null @@ -1,30 +0,0 @@ -require 'rbconfig' -require 'find' -require 'ftools' - -include Config - -# this was adapted from rdoc's install.rb by ways of Log4r - -$sitedir = CONFIG["sitelibdir"] -unless $sitedir - version = CONFIG["MAJOR"] + "." + CONFIG["MINOR"] - $libdir = File.join(CONFIG["libdir"], "ruby", version) - $sitedir = $:.find {|x| x =~ /site_ruby/ } - if !$sitedir - $sitedir = File.join($libdir, "site_ruby") - elsif $sitedir !~ Regexp.quote(version) - $sitedir = File.join($sitedir, version) - end -end - -# the actual gruntwork -Dir.chdir("lib") - -Find.find("active_support", "active_support.rb") { |f| - if f[-3..-1] == ".rb" - File::install(f, File.join($sitedir, *f.split(/\//)), 0644, true) - else - File::makedirs(File.join($sitedir, *f.split(/\//))) - end -} diff --git a/activesupport/lib/active_support/buffered_logger.rb b/activesupport/lib/active_support/buffered_logger.rb index 29c3843d16..b861a6f62a 100644 --- a/activesupport/lib/active_support/buffered_logger.rb +++ b/activesupport/lib/active_support/buffered_logger.rb @@ -101,7 +101,11 @@ module ActiveSupport @guard.synchronize do unless buffer.empty? old_buffer = buffer - @log.write(old_buffer.join) + all_content = StringIO.new + old_buffer.each do |content| + all_content << content + end + @log.write(all_content.string) end # Important to do this even if buffer was empty or else @buffer will diff --git a/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb b/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb index 9c4d5fae26..2d88cb57e5 100644 --- a/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb +++ b/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb @@ -5,9 +5,7 @@ class Module options = syms.extract_options! syms.each do |sym| class_eval(<<-EOS, __FILE__, __LINE__ + 1) - unless defined? @@#{sym} - @@#{sym} = nil - end + @@#{sym} = nil unless defined? @@#{sym} def self.#{sym} @@#{sym} @@ -28,10 +26,6 @@ class Module options = syms.extract_options! syms.each do |sym| class_eval(<<-EOS, __FILE__, __LINE__ + 1) - unless defined? @@#{sym} - @@#{sym} = nil - end - def self.#{sym}=(obj) @@#{sym} = obj end diff --git a/activesupport/lib/active_support/core_ext/module/remove_method.rb b/activesupport/lib/active_support/core_ext/module/remove_method.rb index 2714a46b28..b8c01aca0e 100644 --- a/activesupport/lib/active_support/core_ext/module/remove_method.rb +++ b/activesupport/lib/active_support/core_ext/module/remove_method.rb @@ -3,4 +3,9 @@ class Module remove_method(method) rescue NameError end + + def redefine_method(method, &block) + remove_possible_method(method) + define_method(method, &block) + end end
\ No newline at end of file diff --git a/activesupport/lib/active_support/core_ext/object/to_param.rb b/activesupport/lib/active_support/core_ext/object/to_param.rb index 06f077e920..f2e7c2351e 100644 --- a/activesupport/lib/active_support/core_ext/object/to_param.rb +++ b/activesupport/lib/active_support/core_ext/object/to_param.rb @@ -44,6 +44,6 @@ class Hash def to_param(namespace = nil) collect do |key, value| value.to_query(namespace ? "#{namespace}[#{key}]" : key) - end.sort * '&' + end * '&' end end diff --git a/activesupport/lib/active_support/log_subscriber.rb b/activesupport/lib/active_support/log_subscriber.rb index 891d718af3..7611aff964 100644 --- a/activesupport/lib/active_support/log_subscriber.rb +++ b/activesupport/lib/active_support/log_subscriber.rb @@ -63,15 +63,9 @@ module ActiveSupport @@flushable_loggers = nil log_subscriber.public_methods(false).each do |event| - notifier.subscribe("#{event}.#{namespace}") do |*args| - next if log_subscriber.logger.nil? - - begin - log_subscriber.send(event, ActiveSupport::Notifications::Event.new(*args)) - rescue Exception => e - log_subscriber.logger.error "Could not log #{args[0].inspect} event. #{e.class}: #{e.message}" - end - end + next if 'call' == event.to_s + + notifier.subscribe("#{event}.#{namespace}", log_subscriber) end end @@ -92,6 +86,17 @@ module ActiveSupport flushable_loggers.each(&:flush) end + def call(message, *args) + return unless logger + + method = message.split('.').first + begin + send(method, ActiveSupport::Notifications::Event.new(message, *args)) + rescue Exception => e + logger.error "Could not log #{message.inspect} event. #{e.class}: #{e.message}" + end + end + protected %w(info debug warn error fatal unknown).each do |level| diff --git a/activesupport/lib/active_support/log_subscriber/test_helper.rb b/activesupport/lib/active_support/log_subscriber/test_helper.rb index 96506a4b2b..9e52cb97a9 100644 --- a/activesupport/lib/active_support/log_subscriber/test_helper.rb +++ b/activesupport/lib/active_support/log_subscriber/test_helper.rb @@ -1,4 +1,5 @@ require 'active_support/log_subscriber' +require 'active_support/buffered_logger' module ActiveSupport class LogSubscriber @@ -33,7 +34,7 @@ module ActiveSupport module TestHelper def setup @logger = MockLogger.new - @notifier = ActiveSupport::Notifications::Notifier.new(queue) + @notifier = ActiveSupport::Notifications::Fanout.new ActiveSupport::LogSubscriber.colorize_logging = false @@ -47,10 +48,14 @@ module ActiveSupport end class MockLogger + include ActiveSupport::BufferedLogger::Severity + attr_reader :flush_count + attr_accessor :level - def initialize + def initialize(level = DEBUG) @flush_count = 0 + @level = level @logged = Hash.new { |h,k| h[k] = [] } end @@ -65,6 +70,14 @@ module ActiveSupport def flush @flush_count += 1 end + + ActiveSupport::BufferedLogger::Severity.constants.each do |severity| + class_eval <<-EOT, __FILE__, __LINE__ + 1 + def #{severity.downcase}? + #{severity} >= @level + end + EOT + end end # Wait notifications to be published. @@ -81,10 +94,6 @@ module ActiveSupport def set_logger(logger) ActiveSupport::LogSubscriber.logger = logger end - - def queue - ActiveSupport::Notifications::Fanout.new - end end end -end
\ No newline at end of file +end diff --git a/activesupport/lib/active_support/notifications.rb b/activesupport/lib/active_support/notifications.rb index 1444fc1609..93d1907edc 100644 --- a/activesupport/lib/active_support/notifications.rb +++ b/activesupport/lib/active_support/notifications.rb @@ -47,34 +47,12 @@ module ActiveSupport delegate :instrument, :to => :instrumenter def notifier - @notifier ||= Notifier.new + @notifier ||= Fanout.new end def instrumenter Thread.current[:"instrumentation_#{notifier.object_id}"] ||= Instrumenter.new(notifier) end end - - class Notifier - def initialize(queue = Fanout.new) - @queue = queue - end - - def publish(*args) - @queue.publish(*args) - end - - def subscribe(pattern = nil, &block) - @queue.bind(pattern).subscribe(&block) - end - - def unsubscribe(subscriber) - @queue.unsubscribe(subscriber) - end - - def wait - @queue.wait - end - end end end diff --git a/activesupport/lib/active_support/notifications/fanout.rb b/activesupport/lib/active_support/notifications/fanout.rb index 300ec842a9..64f315cb6a 100644 --- a/activesupport/lib/active_support/notifications/fanout.rb +++ b/activesupport/lib/active_support/notifications/fanout.rb @@ -8,14 +8,11 @@ module ActiveSupport @listeners_for = {} end - def bind(pattern) - Binding.new(self, pattern) - end - - def subscribe(pattern = nil, &block) + def subscribe(pattern = nil, block = Proc.new) @listeners_for.clear - @subscribers << Subscriber.new(pattern, &block) - @subscribers.last + Subscriber.new(pattern, block).tap do |s| + @subscribers << s + end end def unsubscribe(subscriber) @@ -24,69 +21,35 @@ module ActiveSupport end def publish(name, *args) - if listeners = @listeners_for[name] - listeners.each { |s| s.publish(name, *args) } - else - @listeners_for[name] = @subscribers.select { |s| s.publish(name, *args) } - end + listeners_for(name).each { |s| s.publish(name, *args) } end - # This is a sync queue, so there is not waiting. - def wait + def listeners_for(name) + @listeners_for[name] ||= @subscribers.select { |s| s.subscribed_to?(name) } end - # Used for internal implementation only. - class Binding #:nodoc: - def initialize(queue, pattern) - @queue = queue - @pattern = - case pattern - when Regexp, NilClass - pattern - else - /^#{Regexp.escape(pattern.to_s)}$/ - end - end - - def subscribe(&block) - @queue.subscribe(@pattern, &block) - end + # This is a sync queue, so there is not waiting. + def wait end class Subscriber #:nodoc: - def initialize(pattern, &block) + def initialize(pattern, delegate) @pattern = pattern - @block = block + @delegate = delegate end - def publish(*args) - return unless subscribed_to?(args.first) - push(*args) - true - end - - def drained? - true + def publish(message, *args) + @delegate.call(message, *args) end def subscribed_to?(name) - !@pattern || @pattern =~ name.to_s + !@pattern || @pattern === name.to_s end def matches?(subscriber_or_name) - case subscriber_or_name - when String - @pattern && @pattern =~ subscriber_or_name - when self - true - end + self === subscriber_or_name || + @pattern && @pattern === subscriber_or_name end - - private - - def push(*args) - @block.call(*args) - end end end end diff --git a/activesupport/lib/active_support/notifications/instrumenter.rb b/activesupport/lib/active_support/notifications/instrumenter.rb index 7e89402822..e98189f899 100644 --- a/activesupport/lib/active_support/notifications/instrumenter.rb +++ b/activesupport/lib/active_support/notifications/instrumenter.rb @@ -9,23 +9,30 @@ module ActiveSupport def initialize(notifier) @id = unique_id @notifier = notifier + @started = nil + @finished = nil end # Instrument the given block by measuring the time taken to execute it # and publish it. Notice that events get sent even if an error occurs # in the passed-in block def instrument(name, payload={}) - time = Time.now begin + @started = Time.now yield(payload) if block_given? rescue Exception => e payload[:exception] = [e.class.name, e.message] raise e ensure - @notifier.publish(name, time, Time.now, @id, payload) + @finished = Time.now + @notifier.publish(name, @started, @finished, @id, payload) end end + def elapsed + 1000.0 * (@finished.to_f - @started.to_f) + end + private def unique_id SecureRandom.hex(10) @@ -33,7 +40,7 @@ module ActiveSupport end class Event - attr_reader :name, :time, :end, :transaction_id, :payload + attr_reader :name, :time, :end, :transaction_id, :payload, :duration def initialize(name, start, ending, transaction_id, payload) @name = name @@ -41,14 +48,11 @@ module ActiveSupport @time = start @transaction_id = transaction_id @end = ending - end - - def duration - @duration ||= 1000.0 * (@end - @time) + @duration = 1000.0 * (@end - @time) end def parent_of?(event) - start = (self.time - event.time) * 1000 + start = (time - event.time) * 1000 start <= 0 && (start + duration >= event.duration) end end diff --git a/activesupport/test/buffered_logger_test.rb b/activesupport/test/buffered_logger_test.rb index 850febb959..97c0ef14db 100644 --- a/activesupport/test/buffered_logger_test.rb +++ b/activesupport/test/buffered_logger_test.rb @@ -1,9 +1,12 @@ require 'abstract_unit' +require 'multibyte_test_helpers' require 'stringio' require 'fileutils' require 'active_support/buffered_logger' class BufferedLoggerTest < Test::Unit::TestCase + include MultibyteTestHelpers + Logger = ActiveSupport::BufferedLogger def setup @@ -146,4 +149,16 @@ class BufferedLoggerTest < Test::Unit::TestCase @logger.expects :clear_buffer @logger.flush end + + def test_buffer_multibyte + @logger.auto_flushing = 2 + @logger.info(UNICODE_STRING) + @logger.info(BYTE_STRING) + assert @output.string.include?(UNICODE_STRING) + byte_string = @output.string.dup + if byte_string.respond_to?(:force_encoding) + byte_string.force_encoding("ASCII-8BIT") + end + assert byte_string.include?(BYTE_STRING) + end end diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index 7b2c10908f..5d9846a216 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -2,6 +2,8 @@ require 'abstract_unit' require 'active_support/core_ext/hash' require 'bigdecimal' require 'active_support/core_ext/string/access' +require 'active_support/ordered_hash' +require 'active_support/core_ext/object/conversions' class HashExtTest < Test::Unit::TestCase def setup @@ -449,6 +451,33 @@ class IWriteMyOwnXML end end +class HashExtToParamTests < Test::Unit::TestCase + class ToParam < String + def to_param + "#{self}-1" + end + end + + def test_string_hash + assert_equal '', {}.to_param + assert_equal 'hello=world', { :hello => "world" }.to_param + assert_equal 'hello=10', { "hello" => 10 }.to_param + assert_equal 'hello=world&say_bye=true', ActiveSupport::OrderedHash[:hello, "world", "say_bye", true].to_param + end + + def test_number_hash + assert_equal '10=20&30=40&50=60', ActiveSupport::OrderedHash[10, 20, 30, 40, 50, 60].to_param + end + + def test_to_param_hash + assert_equal 'custom=param-1&custom2=param2-1', ActiveSupport::OrderedHash[ToParam.new('custom'), ToParam.new('param'), ToParam.new('custom2'), ToParam.new('param2')].to_param + end + + def test_to_param_hash_escapes_its_keys_and_values + assert_equal 'param+1=A+string+with+%2F+characters+%26+that+should+be+%3F+escaped', { 'param 1' => 'A string with / characters & that should be ? escaped' }.to_param + end +end + class HashToXmlTest < Test::Unit::TestCase def setup @xml_options = { :root => :person, :skip_instruct => true, :indent => 0 } diff --git a/activesupport/test/multibyte_test_helpers.rb b/activesupport/test/multibyte_test_helpers.rb index 597f949059..8839b75601 100644 --- a/activesupport/test/multibyte_test_helpers.rb +++ b/activesupport/test/multibyte_test_helpers.rb @@ -4,6 +4,9 @@ module MultibyteTestHelpers UNICODE_STRING = 'こにちわ' ASCII_STRING = 'ohayo' BYTE_STRING = "\270\236\010\210\245" + if BYTE_STRING.respond_to?(:force_encoding) + BYTE_STRING.force_encoding("ASCII-8BIT") + end def chars(str) ActiveSupport::Multibyte::Chars.new(str) @@ -16,4 +19,4 @@ module MultibyteTestHelpers def assert_equal_codepoints(expected, actual, message=nil) assert_equal(inspect_codepoints(expected), inspect_codepoints(actual), message) end -end
\ No newline at end of file +end diff --git a/activesupport/test/notifications_test.rb b/activesupport/test/notifications_test.rb index 3e16e01d89..41e8ca4ae7 100644 --- a/activesupport/test/notifications_test.rb +++ b/activesupport/test/notifications_test.rb @@ -11,14 +11,11 @@ module Notifications @named_subscription = @notifier.subscribe("named.subscription") { |*args| @named_events << event(*args) } end - private - def event(*args) - ActiveSupport::Notifications::Event.new(*args) - end + private - def drain - @notifier.wait - end + def event(*args) + ActiveSupport::Notifications::Event.new(*args) + end end class UnsubscribeTest < TestCase @@ -132,13 +129,10 @@ module Notifications def test_instrument_returns_block_result assert_equal 2, instrument(:awesome) { 1 + 1 } - drain end def test_instrument_yields_the_paylod_for_further_modification assert_equal 2, instrument(:awesome) { |p| p[:result] = 1 + 1 } - drain - assert_equal 1, @events.size assert_equal :awesome, @events.first.name assert_equal Hash[:result => 2], @events.first.payload @@ -154,15 +148,11 @@ module Notifications 1 + 1 end - drain - assert_equal 1, @events.size assert_equal :wot, @events.first.name assert_equal Hash[:payload => "child"], @events.first.payload end - drain - assert_equal 2, @events.size assert_equal :awesome, @events.last.name assert_equal Hash[:payload => "notifications"], @events.last.payload @@ -177,16 +167,22 @@ module Notifications assert_equal "FAIL", e.message end - drain assert_equal 1, @events.size assert_equal Hash[:payload => "notifications", :exception => ["RuntimeError", "FAIL"]], @events.last.payload end + def test_elapsed + instrument(:something) do + sleep(0.001) + end + + # Elapsed returns duration in ms + assert_in_delta 1, ActiveSupport::Notifications.instrumenter.elapsed, 100 + end + def test_event_is_pushed_even_without_block instrument(:awesome, :payload => "notifications") - drain - assert_equal 1, @events.size assert_equal :awesome, @events.last.name assert_equal Hash[:payload => "notifications"], @events.last.payload @@ -200,7 +196,7 @@ module Notifications assert_equal :foo, event.name assert_equal time, event.time - assert_in_delta 10.0, event.duration, 0.00000000000001 + assert_in_delta 10.0, event.duration, 0.00001 end def test_events_consumes_information_given_as_payload |