diff options
Diffstat (limited to 'activesupport/lib')
28 files changed, 100 insertions, 253 deletions
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb index 6b87774978..a846f81c12 100644 --- a/activesupport/lib/active_support.rb +++ b/activesupport/lib/active_support.rb @@ -1,5 +1,5 @@ #-- -# Copyright (c) 2005 David Heinemeier Hansson +# Copyright (c) 2005-2011 David Heinemeier Hansson # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the diff --git a/activesupport/lib/active_support/buffered_logger.rb b/activesupport/lib/active_support/buffered_logger.rb index 88b50fc506..a14f008be5 100644 --- a/activesupport/lib/active_support/buffered_logger.rb +++ b/activesupport/lib/active_support/buffered_logger.rb @@ -49,10 +49,12 @@ module ActiveSupport @log = log elsif File.exist?(log) @log = open(log, (File::WRONLY | File::APPEND)) + @log.binmode @log.sync = true else FileUtils.mkdir_p(File.dirname(log)) @log = open(log, (File::WRONLY | File::APPEND | File::CREAT)) + @log.binmode @log.sync = true end end diff --git a/activesupport/lib/active_support/core_ext/array/conversions.rb b/activesupport/lib/active_support/core_ext/array/conversions.rb index baefa9cae4..3b22e8b4f9 100644 --- a/activesupport/lib/active_support/core_ext/array/conversions.rb +++ b/activesupport/lib/active_support/core_ext/array/conversions.rb @@ -37,12 +37,12 @@ class Array # Converts a collection of elements into a formatted string by calling # <tt>to_s</tt> on all elements and joining them: # - # Blog.find(:all).to_formatted_s # => "First PostSecond PostThird Post" + # Blog.all.to_formatted_s # => "First PostSecond PostThird Post" # # Adding in the <tt>:db</tt> argument as the format yields a prettier # output: # - # Blog.find(:all).to_formatted_s(:db) # => "First Post,Second Post,Third Post" + # Blog.all.to_formatted_s(:db) # => "First Post,Second Post,Third Post" def to_formatted_s(format = :default) case format when :db diff --git a/activesupport/lib/active_support/core_ext/array/random_access.rb b/activesupport/lib/active_support/core_ext/array/random_access.rb index 9eba4642b8..bb1807a68a 100644 --- a/activesupport/lib/active_support/core_ext/array/random_access.rb +++ b/activesupport/lib/active_support/core_ext/array/random_access.rb @@ -7,7 +7,7 @@ class Array # # [1,2,3,4,5,6].sample # => 4 # [1,2,3,4,5,6].sample(3) # => [2, 4, 5] - # [1,2,3,4,5,6].sample(-3) # => ArgumentError: negative sample number + # [1,2,3,4,5,6].sample(-3) # => ArgumentError: negative array size # [].sample # => nil # [].sample(3) # => [] def sample(n=nil) diff --git a/activesupport/lib/active_support/core_ext/array/uniq_by.rb b/activesupport/lib/active_support/core_ext/array/uniq_by.rb index bd5c7a187f..9c5f97b0e9 100644 --- a/activesupport/lib/active_support/core_ext/array/uniq_by.rb +++ b/activesupport/lib/active_support/core_ext/array/uniq_by.rb @@ -1,8 +1,7 @@ class Array - # Return an unique array based on the criteria given as a proc. + # Returns an unique array based on the criteria given as a +Proc+. # - # [1, 2, 3, 4].uniq_by { |i| i.odd? } - # # => [1, 2] + # [1, 2, 3, 4].uniq_by { |i| i.odd? } # => [1, 2] # def uniq_by hash, array = {}, [] diff --git a/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb b/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb index ca3db2349e..ec475134ef 100644 --- a/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb +++ b/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb @@ -130,7 +130,6 @@ class Class # :nodoc: end def write_inheritable_attribute(key, value) - ActiveSupport::Deprecation.warn ClassInheritableAttributes::DEPRECATION_WARNING_MESSAGE if inheritable_attributes.equal?(EMPTY_INHERITABLE_ATTRIBUTES) @inheritable_attributes = {} end @@ -148,7 +147,6 @@ class Class # :nodoc: end def read_inheritable_attribute(key) - ActiveSupport::Deprecation.warn ClassInheritableAttributes::DEPRECATION_WARNING_MESSAGE inheritable_attributes[key] end diff --git a/activesupport/lib/active_support/core_ext/date/calculations.rb b/activesupport/lib/active_support/core_ext/date/calculations.rb index 724e076407..236055d77a 100644 --- a/activesupport/lib/active_support/core_ext/date/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date/calculations.rb @@ -206,7 +206,7 @@ class Date # Returns a new ; DateTime objects will have time set to 0:00DateTime representing the start of the month (1st of the month; DateTime objects will have time set to 0:00) def beginning_of_month - self.acts_like?(:time) ? change(:day => 1,:hour => 0, :min => 0, :sec => 0) : change(:day => 1) + self.acts_like?(:time) ? change(:day => 1, :hour => 0) : change(:day => 1) end alias :at_beginning_of_month :beginning_of_month @@ -231,13 +231,13 @@ class Date # Returns a new Date/DateTime representing the start of the year (1st of january; DateTime objects will have time set to 0:00) def beginning_of_year - self.acts_like?(:time) ? change(:month => 1, :day => 1, :hour => 0, :min => 0, :sec => 0) : change(:month => 1, :day => 1) + self.acts_like?(:time) ? change(:month => 1, :day => 1, :hour => 0) : change(:month => 1, :day => 1) end alias :at_beginning_of_year :beginning_of_year # Returns a new Time representing the end of the year (31st of december; DateTime objects will have time set to 23:59:59) def end_of_year - self.acts_like?(:time) ? change(:month => 12,:day => 31,:hour => 23, :min => 59, :sec => 59) : change(:month => 12, :day => 31) + self.acts_like?(:time) ? change(:month => 12, :day => 31, :hour => 23, :min => 59, :sec => 59) : change(:month => 12, :day => 31) end alias :at_end_of_year :end_of_year diff --git a/activesupport/lib/active_support/core_ext/date/conversions.rb b/activesupport/lib/active_support/core_ext/date/conversions.rb index 769ead9544..338104fd05 100644 --- a/activesupport/lib/active_support/core_ext/date/conversions.rb +++ b/activesupport/lib/active_support/core_ext/date/conversions.rb @@ -1,6 +1,7 @@ require 'date' require 'active_support/inflector/methods' require 'active_support/core_ext/date/zones' +require 'active_support/core_ext/module/remove_method' class Date DATE_FORMATS = { @@ -13,10 +14,10 @@ class Date } # Ruby 1.9 has Date#to_time which converts to localtime only. - remove_method :to_time if method_defined?(:to_time) + remove_possible_method :to_time # Ruby 1.9 has Date#xmlschema which converts to a string without the time component. - remove_method :xmlschema if method_defined?(:xmlschema) + remove_possible_method :xmlschema # Convert to a formatted string. See DATE_FORMATS for predefined formats. # diff --git a/activesupport/lib/active_support/core_ext/date_time/conversions.rb b/activesupport/lib/active_support/core_ext/date_time/conversions.rb index 21b84b994b..ca899c714c 100644 --- a/activesupport/lib/active_support/core_ext/date_time/conversions.rb +++ b/activesupport/lib/active_support/core_ext/date_time/conversions.rb @@ -51,25 +51,25 @@ class DateTime utc? && alternate_utc_string || ActiveSupport::TimeZone.seconds_to_utc_offset(utc_offset, colon) end - # Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005 14:30:00 +0000" + # Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005 14:30:00 +0000". def readable_inspect to_s(:rfc822) end alias_method :default_inspect, :inspect alias_method :inspect, :readable_inspect - # Converts self to a Ruby Date object; time portion is discarded + # Converts self to a Ruby Date object; time portion is discarded. def to_date ::Date.new(year, month, day) end unless instance_methods(false).include?(:to_date) - # Attempts to convert self to a Ruby Time object; returns self if out of range of Ruby Time class - # If self has an offset other than 0, self will just be returned unaltered, since there's no clean way to map it to a Time + # Attempts to convert self to a Ruby Time object; returns self if out of range of Ruby Time class. + # If self has an offset other than 0, self will just be returned unaltered, since there's no clean way to map it to a Time. def to_time self.offset == 0 ? ::Time.utc_time(year, month, day, hour, min, sec, sec_fraction * (RUBY_VERSION < '1.9' ? 86400000000 : 1000000)) : self end - # To be able to keep Times, Dates and DateTimes interchangeable on conversions + # To be able to keep Times, Dates and DateTimes interchangeable on conversions. def to_datetime self end unless instance_methods(false).include?(:to_datetime) @@ -79,17 +79,17 @@ class DateTime civil(year, month, day, hour, min, sec, offset) end - # Converts datetime to an appropriate format for use in XML + # Converts datetime to an appropriate format for use in XML. def xmlschema strftime("%Y-%m-%dT%H:%M:%S%Z") end unless instance_methods(false).include?(:xmlschema) - # Converts self to a floating-point number of seconds since the Unix epoch + # Converts self to a floating-point number of seconds since the Unix epoch. def to_f seconds_since_unix_epoch.to_f end - # Converts self to an integer number of seconds since the Unix epoch + # Converts self to an integer number of seconds since the Unix epoch. def to_i seconds_since_unix_epoch.to_i end diff --git a/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb b/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb index aad4b61e16..c2a6476604 100644 --- a/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb +++ b/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb @@ -9,4 +9,16 @@ class Hash def with_indifferent_access ActiveSupport::HashWithIndifferentAccess.new_from_hash_copying_default(self) end + + # Called when object is nested under an object that receives + # #with_indifferent_access. This method with be called on the current object + # by the enclosing object and is aliased to #with_indifferent_access by + # default. Subclasses of Hash may overwrite this method to return +self+ if + # converting to an +ActiveSupport::HashWithIndifferentAccess+ would not be + # desirable. + # + # b = {:b => 1} + # {:a => b}.with_indifferent_access["a"] # calls b.nested_under_indifferent_access + # + alias nested_under_indifferent_access with_indifferent_access end diff --git a/activesupport/lib/active_support/core_ext/hash/slice.rb b/activesupport/lib/active_support/core_ext/hash/slice.rb index e4a864c20f..d7fb2da0fb 100644 --- a/activesupport/lib/active_support/core_ext/hash/slice.rb +++ b/activesupport/lib/active_support/core_ext/hash/slice.rb @@ -21,7 +21,7 @@ class Hash # Replaces the hash with only the given keys. # Returns a hash contained the removed key/value pairs - # {:a => 1, :b => 2, :c => 3, :d => 4}.slice!(:a, :b) # => {:c => 3, :d =>4} + # {:a => 1, :b => 2, :c => 3, :d => 4}.slice!(:a, :b) # => {:c => 3, :d => 4} def slice!(*keys) keys = keys.map! { |key| convert_key(key) } if respond_to?(:convert_key) omit = slice(*self.keys - keys) diff --git a/activesupport/lib/active_support/core_ext/integer/inflections.rb b/activesupport/lib/active_support/core_ext/integer/inflections.rb index e81e7af436..0e606056c0 100644 --- a/activesupport/lib/active_support/core_ext/integer/inflections.rb +++ b/activesupport/lib/active_support/core_ext/integer/inflections.rb @@ -4,10 +4,13 @@ class Integer # Ordinalize turns a number into an ordinal string used to denote the # position in an ordered sequence such as 1st, 2nd, 3rd, 4th. # - # 1.ordinalize # => "1st" - # 2.ordinalize # => "2nd" - # 1002.ordinalize # => "1002nd" - # 1003.ordinalize # => "1003rd" + # 1.ordinalize # => "1st" + # 2.ordinalize # => "2nd" + # 1002.ordinalize # => "1002nd" + # 1003.ordinalize # => "1003rd" + # -11.ordinalize # => "-11th" + # -1001.ordinalize # => "-1001st" + # def ordinalize ActiveSupport::Inflector.ordinalize(self) end diff --git a/activesupport/lib/active_support/core_ext/kernel/reporting.rb b/activesupport/lib/active_support/core_ext/kernel/reporting.rb index 37a827123a..c6920098a8 100644 --- a/activesupport/lib/active_support/core_ext/kernel/reporting.rb +++ b/activesupport/lib/active_support/core_ext/kernel/reporting.rb @@ -62,7 +62,7 @@ module Kernel # Captures the given stream and returns it: # - # stream = capture(:stdout){ puts "Cool" } + # stream = capture(:stdout) { puts "Cool" } # stream # => "Cool\n" # def capture(stream) @@ -78,4 +78,16 @@ module Kernel result end alias :silence :capture + + # Silences both STDOUT and STDERR, even for subprocesses. + # + # quietly { system 'bundle install' } + # + def quietly + silence_stream(STDOUT) do + silence_stream(STDERR) do + yield + end + end + end end diff --git a/activesupport/lib/active_support/core_ext/module/attr_accessor_with_default.rb b/activesupport/lib/active_support/core_ext/module/attr_accessor_with_default.rb index e3259a0a84..984f6fb957 100644 --- a/activesupport/lib/active_support/core_ext/module/attr_accessor_with_default.rb +++ b/activesupport/lib/active_support/core_ext/module/attr_accessor_with_default.rb @@ -19,6 +19,7 @@ class Module # attr_accessor_with_default(:element_name) { name.underscore } # def attr_accessor_with_default(sym, default = Proc.new) + ActiveSupport::Deprecation.warn "attr_accessor_with_default is deprecated. Use Ruby instead!" define_method(sym, block_given? ? default : Proc.new { default }) module_eval(<<-EVAL, __FILE__, __LINE__ + 1) def #{sym}=(value) # def age=(value) diff --git a/activesupport/lib/active_support/core_ext/module/deprecation.rb b/activesupport/lib/active_support/core_ext/module/deprecation.rb index 9c169a2598..5a5b4e3f80 100644 --- a/activesupport/lib/active_support/core_ext/module/deprecation.rb +++ b/activesupport/lib/active_support/core_ext/module/deprecation.rb @@ -1,5 +1,3 @@ -require 'active_support/deprecation' - class Module # Declare that a method has been deprecated. # deprecate :foo diff --git a/activesupport/lib/active_support/core_ext/object/blank.rb b/activesupport/lib/active_support/core_ext/object/blank.rb index 20085c4fb3..fb5abf2aa5 100644 --- a/activesupport/lib/active_support/core_ext/object/blank.rb +++ b/activesupport/lib/active_support/core_ext/object/blank.rb @@ -1,14 +1,14 @@ class Object # An object is blank if it's false, empty, or a whitespace string. - # For example, "", " ", +nil+, [], and {} are blank. + # For example, "", " ", +nil+, [], and {} are all blank. # # This simplifies: # - # if !address.nil? && !address.empty? + # if address.nil? || address.empty? # # ...to: # - # if !address.blank? + # if address.blank? def blank? respond_to?(:empty?) ? empty? : !self end diff --git a/activesupport/lib/active_support/core_ext/object/with_options.rb b/activesupport/lib/active_support/core_ext/object/with_options.rb index c23afabfdb..1397142c04 100644 --- a/activesupport/lib/active_support/core_ext/object/with_options.rb +++ b/activesupport/lib/active_support/core_ext/object/with_options.rb @@ -7,7 +7,7 @@ class Object # provided. Each method called on the block variable must take an options # hash as its final argument. # - # Without with_options, this code contains duplication: + # Without <tt>with_options></tt>, this code contains duplication: # # class Account < ActiveRecord::Base # has_many :customers, :dependent => :destroy @@ -16,7 +16,7 @@ class Object # has_many :expenses, :dependent => :destroy # end # - # Using with_options, we can remove the duplication: + # Using <tt>with_options</tt>, we can remove the duplication: # # class Account < ActiveRecord::Base # with_options :dependent => :destroy do |assoc| @@ -29,11 +29,14 @@ class Object # # It can also be used with an explicit receiver: # - # map.with_options :controller => "people" do |people| - # people.connect "/people", :action => "index" - # people.connect "/people/:id", :action => "show" + # I18n.with_options :locale => user.locale, :scope => "newsletter" do |i18n| + # subject i18n.t :subject + # body i18n.t :body, :user_name => user.name # end # + # <tt>with_options</tt> can also be nested since the call is forwarded to its receiver. + # Each nesting level will merge inherited defaults in addition to their own. + # def with_options(options) yield ActiveSupport::OptionMerger.new(self, options) end diff --git a/activesupport/lib/active_support/core_ext/string/behavior.rb b/activesupport/lib/active_support/core_ext/string/behavior.rb index 9d45fbca45..4aa960039b 100644 --- a/activesupport/lib/active_support/core_ext/string/behavior.rb +++ b/activesupport/lib/active_support/core_ext/string/behavior.rb @@ -1,6 +1,5 @@ class String - # Enable more predictable duck-typing on String-like classes. See - # Object#acts_like?. + # Enable more predictable duck-typing on String-like classes. See <tt>Object#acts_like?</tt>. def acts_like_string? true end diff --git a/activesupport/lib/active_support/core_ext/string/exclude.rb b/activesupport/lib/active_support/core_ext/string/exclude.rb index 5ca268b953..5e184ec1b3 100644 --- a/activesupport/lib/active_support/core_ext/string/exclude.rb +++ b/activesupport/lib/active_support/core_ext/string/exclude.rb @@ -1,5 +1,5 @@ class String - # The inverse of String#include?. Returns true if the string does not include the other string. + # The inverse of <tt>String#include?</tt>. Returns true if the string does not include the other string. def exclude?(string) !include?(string) end diff --git a/activesupport/lib/active_support/core_ext/string/inquiry.rb b/activesupport/lib/active_support/core_ext/string/inquiry.rb index 604f3bf4dc..5f0a017de6 100644 --- a/activesupport/lib/active_support/core_ext/string/inquiry.rb +++ b/activesupport/lib/active_support/core_ext/string/inquiry.rb @@ -1,7 +1,7 @@ require 'active_support/string_inquirer' class String - # Wraps the current string in the ActiveSupport::StringInquirer class, + # Wraps the current string in the <tt>ActiveSupport::StringInquirer</tt> class, # which gives you a prettier way to test for equality. Example: # # env = "production".inquiry diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index 7e134db118..dcac17536a 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -187,7 +187,7 @@ class Time # Returns a new Time representing the start of the day (0:00) def beginning_of_day #(self - seconds_since_midnight).change(:usec => 0) - change(:hour => 0, :min => 0, :sec => 0, :usec => 0) + change(:hour => 0) end alias :midnight :beginning_of_day alias :at_midnight :beginning_of_day @@ -201,7 +201,7 @@ class Time # Returns a new Time representing the start of the month (1st of the month, 0:00) def beginning_of_month #self - ((self.mday-1).days + self.seconds_since_midnight) - change(:day => 1,:hour => 0, :min => 0, :sec => 0, :usec => 0) + change(:day => 1, :hour => 0) end alias :at_beginning_of_month :beginning_of_month @@ -227,7 +227,7 @@ class Time # Returns a new Time representing the start of the year (1st of january, 0:00) def beginning_of_year - change(:month => 1, :day => 1, :hour => 0, :min => 0, :sec => 0, :usec => 0) + change(:month => 1, :day => 1, :hour => 0) end alias :at_beginning_of_year :beginning_of_year diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb index 79a0de7940..39ebc1ec82 100644 --- a/activesupport/lib/active_support/hash_with_indifferent_access.rb +++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb @@ -10,6 +10,10 @@ module ActiveSupport true end + def with_indifferent_access + self + end + def initialize(constructor = {}) if constructor.is_a?(Hash) super() @@ -58,8 +62,12 @@ module ActiveSupport # hash_1.update(hash_2) # => {"key"=>"New Value!"} # def update(other_hash) - other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) } - self + if other_hash.is_a? HashWithIndifferentAccess + super(other_hash) + else + other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) } + self + end end alias_method :merge!, :update @@ -140,8 +148,8 @@ module ActiveSupport end def convert_value(value) - if value.class == Hash - self.class.new_from_hash_copying_default(value) + if value.is_a? Hash + value.nested_under_indifferent_access elsif value.is_a?(Array) value.dup.replace(value.map { |e| convert_value(e) }) else diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb index dd2beef89d..a2c4f7bfda 100644 --- a/activesupport/lib/active_support/inflector/methods.rb +++ b/activesupport/lib/active_support/inflector/methods.rb @@ -135,6 +135,8 @@ module ActiveSupport # ordinalize(2) # => "2nd" # ordinalize(1002) # => "1002nd" # ordinalize(1003) # => "1003rd" + # ordinalize(-11) # => "-11th" + # ordinalize(-1021) # => "-1021st" def ordinalize(number) if (11..13).include?(number.to_i.abs % 100) "#{number}th" @@ -148,4 +150,4 @@ module ActiveSupport end end end -end
\ No newline at end of file +end diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb index 1fafc36ee8..d22fe14b33 100644 --- a/activesupport/lib/active_support/json/encoding.rb +++ b/activesupport/lib/active_support/json/encoding.rb @@ -2,6 +2,7 @@ require 'active_support/core_ext/object/to_json' require 'active_support/core_ext/module/delegation' require 'active_support/deprecation' require 'active_support/json/variable' +require 'active_support/ordered_hash' require 'bigdecimal' require 'active_support/core_ext/big_decimal/conversions' # for #to_s diff --git a/activesupport/lib/active_support/log_subscriber/test_helper.rb b/activesupport/lib/active_support/log_subscriber/test_helper.rb index 392e33edbc..3e54134c5c 100644 --- a/activesupport/lib/active_support/log_subscriber/test_helper.rb +++ b/activesupport/lib/active_support/log_subscriber/test_helper.rb @@ -1,5 +1,6 @@ require 'active_support/log_subscriber' require 'active_support/buffered_logger' +require 'active_support/notifications' module ActiveSupport class LogSubscriber diff --git a/activesupport/lib/active_support/ordered_hash.rb b/activesupport/lib/active_support/ordered_hash.rb index fbc40d1b69..762a64a881 100644 --- a/activesupport/lib/active_support/ordered_hash.rb +++ b/activesupport/lib/active_support/ordered_hash.rb @@ -43,6 +43,10 @@ module ActiveSupport end end + def nested_under_indifferent_access + self + end + # Hash is ordered in Ruby 1.9! if RUBY_VERSION < '1.9' diff --git a/activesupport/lib/active_support/secure_random.rb b/activesupport/lib/active_support/secure_random.rb index 368954907f..52f8c72b77 100644 --- a/activesupport/lib/active_support/secure_random.rb +++ b/activesupport/lib/active_support/secure_random.rb @@ -1,205 +1,6 @@ -begin - require 'securerandom' -rescue LoadError -end +require 'securerandom' module ActiveSupport - if defined?(::SecureRandom) - # Use Ruby's SecureRandom library if available. - SecureRandom = ::SecureRandom # :nodoc: - else - # = Secure random number generator interface. - # - # This library is an interface for secure random number generator which is - # suitable for generating session key in HTTP cookies, etc. - # - # It supports following secure random number generators. - # - # * openssl - # * /dev/urandom - # * Win32 - # - # *Note*: This module is based on the SecureRandom library from Ruby 1.9, - # revision 18786, August 23 2008. It's 100% interface-compatible with Ruby 1.9's - # SecureRandom library. - # - # == Example - # - # # random hexadecimal string. - # p SecureRandom.hex(10) # => "52750b30ffbc7de3b362" - # p SecureRandom.hex(10) # => "92b15d6c8dc4beb5f559" - # p SecureRandom.hex(11) # => "6aca1b5c58e4863e6b81b8" - # p SecureRandom.hex(12) # => "94b2fff3e7fd9b9c391a2306" - # p SecureRandom.hex(13) # => "39b290146bea6ce975c37cfc23" - # ... - # - # # random base64 string. - # p SecureRandom.base64(10) # => "EcmTPZwWRAozdA==" - # p SecureRandom.base64(10) # => "9b0nsevdwNuM/w==" - # p SecureRandom.base64(10) # => "KO1nIU+p9DKxGg==" - # p SecureRandom.base64(11) # => "l7XEiFja+8EKEtY=" - # p SecureRandom.base64(12) # => "7kJSM/MzBJI+75j8" - # p SecureRandom.base64(13) # => "vKLJ0tXBHqQOuIcSIg==" - # ... - # - # # random binary string. - # p SecureRandom.random_bytes(10) # => "\016\t{\370g\310pbr\301" - # p SecureRandom.random_bytes(10) # => "\323U\030TO\234\357\020\a\337" - # ... - # - module SecureRandom - - # Generates a random binary string. - # - # The argument n specifies the length of the result string. - # - # If n is not specified, 16 is assumed. - # It may be larger in future. - # - # If secure random number generator is not available, - # NotImplementedError is raised. - # - def self.random_bytes(n=nil) - n ||= 16 - - unless defined? OpenSSL - begin - require 'openssl' - rescue LoadError - end - end - - if defined? OpenSSL::Random - return OpenSSL::Random.random_bytes(n) - end - - if !defined?(@has_urandom) || @has_urandom - flags = File::RDONLY - flags |= File::NONBLOCK if defined? File::NONBLOCK - flags |= File::NOCTTY if defined? File::NOCTTY - flags |= File::NOFOLLOW if defined? File::NOFOLLOW - begin - File.open("/dev/urandom", flags) {|f| - unless f.stat.chardev? - raise Errno::ENOENT - end - @has_urandom = true - ret = f.readpartial(n) - if ret.length != n - raise NotImplementedError, "Unexpected partial read from random device" - end - return ret - } - rescue Errno::ENOENT - @has_urandom = false - end - end - - unless defined?(@has_win32) - begin - require 'Win32API' - - crypt_acquire_context = Win32API.new("advapi32", "CryptAcquireContext", 'PPPII', 'L') - @crypt_gen_random = Win32API.new("advapi32", "CryptGenRandom", 'LIP', 'L') - - hProvStr = " " * 4 - prov_rsa_full = 1 - crypt_verifycontext = 0xF0000000 - - if crypt_acquire_context.call(hProvStr, nil, nil, prov_rsa_full, crypt_verifycontext) == 0 - raise SystemCallError, "CryptAcquireContext failed: #{lastWin32ErrorMessage}" - end - @hProv, = hProvStr.unpack('L') - - @has_win32 = true - rescue LoadError - @has_win32 = false - end - end - if @has_win32 - bytes = " " * n - if @crypt_gen_random.call(@hProv, bytes.size, bytes) == 0 - raise SystemCallError, "CryptGenRandom failed: #{lastWin32ErrorMessage}" - end - return bytes - end - - raise NotImplementedError, "No random device" - end - - # Generates a random hex string. - # - # The argument n specifies the length of the random length. - # The length of the result string is twice of n. - # - # If n is not specified, 16 is assumed. - # It may be larger in future. - # - # If secure random number generator is not available, - # NotImplementedError is raised. - # - def self.hex(n=nil) - random_bytes(n).unpack("H*")[0] - end - - # Generates a random base64 string. - # - # The argument n specifies the length of the random length. - # The length of the result string is about 4/3 of n. - # - # If n is not specified, 16 is assumed. - # It may be larger in future. - # - # If secure random number generator is not available, - # NotImplementedError is raised. - # - def self.base64(n=nil) - [random_bytes(n)].pack("m*").delete("\n") - end - - # Generates a random number. - # - # If an positive integer is given as n, - # SecureRandom.random_number returns an integer: - # 0 <= SecureRandom.random_number(n) < n. - # - # If 0 is given or an argument is not given, - # SecureRandom.random_number returns an float: - # 0.0 <= SecureRandom.random_number() < 1.0. - # - def self.random_number(n=0) - if 0 < n - hex = n.to_s(16) - hex = '0' + hex if (hex.length & 1) == 1 - bin = [hex].pack("H*") - mask = bin[0] - mask |= mask >> 1 - mask |= mask >> 2 - mask |= mask >> 4 - begin - rnd = SecureRandom.random_bytes(bin.length) - rnd[0] = rnd[0] & mask - end until rnd < bin - rnd.unpack("H*")[0].hex - else - # assumption: Float::MANT_DIG <= 64 - i64 = SecureRandom.random_bytes(8).unpack("Q")[0] - Math.ldexp(i64 >> (64-Float::MANT_DIG), -Float::MANT_DIG) - end - end - - # Following code is based on David Garamond's GUID library for Ruby. - def self.lastWin32ErrorMessage # :nodoc: - get_last_error = Win32API.new("kernel32", "GetLastError", '', 'L') - format_message = Win32API.new("kernel32", "FormatMessageA", 'LPLLPLPPPPPPPP', 'L') - format_message_ignore_inserts = 0x00000200 - format_message_from_system = 0x00001000 - - code = get_last_error.call - msg = "\0" * 1024 - len = format_message.call(format_message_ignore_inserts + format_message_from_system, 0, code, 0, msg, 1024, nil, nil, nil, nil, nil, nil, nil, nil) - msg[0, len].tr("\r", '').chomp - end - end - end + # Use Ruby's SecureRandom library. + SecureRandom = ::SecureRandom # :nodoc: end diff --git a/activesupport/lib/active_support/xml_mini.rb b/activesupport/lib/active_support/xml_mini.rb index dff8a8f4c4..6e12404ad4 100644 --- a/activesupport/lib/active_support/xml_mini.rb +++ b/activesupport/lib/active_support/xml_mini.rb @@ -139,7 +139,9 @@ module ActiveSupport protected def _dasherize(key) - key.gsub(/(?!^[_]*)_(?![_]*$)/, '-') + # $2 must be a non-greedy regex for this to work + left, middle, right = /\A(_*)(.*?)(_*)\Z/.match(key.strip)[1,3] + "#{left}#{middle.tr('_ ', '--')}#{right}" end # TODO: Add support for other encodings |