1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

* Introduce ActiveSupport.core_ext Integer, %w(conversions time etc)

* Convert some extension modules to simply reopening the class
* Remove deprecated Float time extensions
* Fold Base64 extension into ActiveSupport::Base64 since stdlib Base64 is gone
This commit is contained in:
Jeremy Kemper 2009-02-28 16:48:14 -08:00
parent 6ed42ebdff
commit a4e3aac40a
33 changed files with 167 additions and 335 deletions

View file

@ -30,4 +30,13 @@ module ActiveSupport
end
end
end
# Encodes the value as base64 without the newline breaks. This makes the base64 encoding readily usable as URL parameters
# or memcache keys without further processing.
#
# ActiveSupport::Base64.encode64s("Original unencoded string")
# # => "T3JpZ2luYWwgdW5lbmNvZGVkIHN0cmluZw=="
def Base64.encode64s(value)
encode64(value).gsub(/\n/, '')
end
end

View file

@ -1,4 +1,4 @@
Dir[File.dirname(__FILE__) + "/core_ext/*.rb"].sort.each do |path|
filename = File.basename(path, '.rb')
require "active_support/core_ext/#{filename}"
require 'active_support/core_ext/util'
Dir["#{File.dirname(__FILE__)}/core_ext/*.rb"].sort.each do |path|
require "active_support/core_ext/#{File.basename(path, '.rb')}"
end

View file

@ -1,15 +1,3 @@
require 'active_support/core_ext/array/access'
require 'active_support/core_ext/array/conversions'
require 'active_support/core_ext/array/extract_options'
require 'active_support/core_ext/array/grouping'
require 'active_support/core_ext/array/random_access'
require 'active_support/core_ext/array/wrapper'
class Array #:nodoc:
include ActiveSupport::CoreExtensions::Array::Access
include ActiveSupport::CoreExtensions::Array::Conversions
include ActiveSupport::CoreExtensions::Array::ExtractOptions
include ActiveSupport::CoreExtensions::Array::Grouping
include ActiveSupport::CoreExtensions::Array::RandomAccess
extend ActiveSupport::CoreExtensions::Array::Wrapper
end
require 'active_support/core_ext/util'
require 'active_support/core_ext/array/wrap'
ActiveSupport.core_ext Array, %w(access conversions extract_options grouping random_access)

View file

@ -0,0 +1,18 @@
class Array
# Wraps the object in an Array unless it's an Array. Converts the
# object to an Array using #to_ary if it implements that.
def self.wrap(object)
case object
when nil
[]
when self
object
else
if object.respond_to?(:to_ary)
object.to_ary
else
[object]
end
end
end
end

View file

@ -1,24 +0,0 @@
module ActiveSupport #:nodoc:
module CoreExtensions #:nodoc:
module Array #:nodoc:
module Wrapper
# Wraps the object in an Array unless it's an Array. Converts the
# object to an Array using #to_ary if it implements that.
def wrap(object)
case object
when nil
[]
when self
object
else
if object.respond_to?(:to_ary)
object.to_ary
else
[object]
end
end
end
end
end
end
end

View file

@ -1,4 +0,0 @@
require 'active_support/base64'
require 'active_support/core_ext/base64/encoding'
ActiveSupport::Base64.extend ActiveSupport::CoreExtensions::Base64::Encoding

View file

@ -1,16 +0,0 @@
module ActiveSupport #:nodoc:
module CoreExtensions #:nodoc:
module Base64 #:nodoc:
module Encoding
# Encodes the value as base64 without the newline breaks. This makes the base64 encoding readily usable as URL parameters
# or memcache keys without further processing.
#
# ActiveSupport::Base64.encode64s("Original unencoded string")
# # => "T3JpZ2luYWwgdW5lbmNvZGVkIHN0cmluZw=="
def encode64s(value)
encode64(value).gsub(/\n/, '')
end
end
end
end
end

View file

@ -0,0 +1,3 @@
require 'active_support/core_ext/util'
require 'bigdecimal'
ActiveSupport.core_ext BigDecimal, %w(conversions)

View file

@ -1,6 +0,0 @@
require 'bigdecimal'
require 'active_support/core_ext/bigdecimal/conversions'
class BigDecimal#:nodoc:
include ActiveSupport::CoreExtensions::BigDecimal::Conversions
end

View file

@ -1,5 +1 @@
require 'active_support/core_ext/cgi/escape_skipping_slashes'
class CGI #:nodoc:
extend ActiveSupport::CoreExtensions::CGI::EscapeSkippingSlashes
end

View file

@ -1,23 +1,17 @@
module ActiveSupport #:nodoc:
module CoreExtensions #:nodoc:
module CGI #:nodoc:
module EscapeSkippingSlashes #:nodoc:
if RUBY_VERSION >= '1.9'
def escape_skipping_slashes(str)
str = str.join('/') if str.respond_to? :join
str.gsub(/([^ \/a-zA-Z0-9_.-])/n) do
"%#{$1.unpack('H2' * $1.bytesize).join('%').upcase}"
end.tr(' ', '+')
end
else
def escape_skipping_slashes(str)
str = str.join('/') if str.respond_to? :join
str.gsub(/([^ \/a-zA-Z0-9_.-])/n) do
"%#{$1.unpack('H2').first.upcase}"
end.tr(' ', '+')
end
end
end
class CGI #:nodoc:
if RUBY_VERSION >= '1.9'
def self.escape_skipping_slashes(str)
str = str.join('/') if str.respond_to? :join
str.gsub(/([^ \/a-zA-Z0-9_.-])/n) do
"%#{$1.unpack('H2' * $1.bytesize).join('%').upcase}"
end.tr(' ', '+')
end
else
def self.escape_skipping_slashes(str)
str = str.join('/') if str.respond_to? :join
str.gsub(/([^ \/a-zA-Z0-9_.-])/n) do
"%#{$1.unpack('H2').first.upcase}"
end.tr(' ', '+')
end
end
end

View file

@ -1,10 +1,3 @@
require 'active_support/core_ext/util'
require 'date'
require 'active_support/core_ext/date/behavior'
require 'active_support/core_ext/date/calculations'
require 'active_support/core_ext/date/conversions'
class Date#:nodoc:
include ActiveSupport::CoreExtensions::Date::Behavior
include ActiveSupport::CoreExtensions::Date::Calculations
include ActiveSupport::CoreExtensions::Date::Conversions
end
ActiveSupport.core_ext Date, %w(behavior calculations conversions)

View file

@ -1,12 +1,11 @@
require 'active_support/core_ext/util'
require 'date'
require 'active_support/core_ext/time/behavior'
require 'active_support/core_ext/time/zones'
require 'active_support/core_ext/date_time/calculations'
require 'active_support/core_ext/date_time/conversions'
class DateTime
include ActiveSupport::CoreExtensions::Time::Behavior
include ActiveSupport::CoreExtensions::Time::Zones
include ActiveSupport::CoreExtensions::DateTime::Calculations
include ActiveSupport::CoreExtensions::DateTime::Conversions
end
ActiveSupport.core_ext DateTime, %w(calculations conversions)

View file

@ -1,9 +1,5 @@
module ActiveSupport
if RUBY_VERSION >= '1.9'
FrozenObjectError = RuntimeError
else
FrozenObjectError = TypeError
end
FrozenObjectError = RUBY_VERSION < '1.9' ? TypeError : RuntimeError
end
# TODO: Turn all this into using the BacktraceCleaner.

View file

@ -1,5 +1 @@
require 'active_support/core_ext/file/atomic'
class File #:nodoc:
extend ActiveSupport::CoreExtensions::File::Atomic
end

View file

@ -1,46 +1,40 @@
module ActiveSupport #:nodoc:
module CoreExtensions #:nodoc:
module File #:nodoc:
module Atomic
# Write to a file atomically. Useful for situations where you don't
# want other processes or threads to see half-written files.
#
# File.atomic_write("important.file") do |file|
# file.write("hello")
# end
#
# If your temp directory is not on the same filesystem as the file you're
# trying to write, you can provide a different temporary directory.
#
# File.atomic_write("/data/something.important", "/data/tmp") do |f|
# file.write("hello")
# end
def atomic_write(file_name, temp_dir = Dir.tmpdir)
require 'tempfile' unless defined?(Tempfile)
class File
# Write to a file atomically. Useful for situations where you don't
# want other processes or threads to see half-written files.
#
# File.atomic_write("important.file") do |file|
# file.write("hello")
# end
#
# If your temp directory is not on the same filesystem as the file you're
# trying to write, you can provide a different temporary directory.
#
# File.atomic_write("/data/something.important", "/data/tmp") do |f|
# file.write("hello")
# end
def self.atomic_write(file_name, temp_dir = Dir.tmpdir)
require 'tempfile' unless defined?(Tempfile)
temp_file = Tempfile.new(basename(file_name), temp_dir)
yield temp_file
temp_file.close
temp_file = Tempfile.new(basename(file_name), temp_dir)
yield temp_file
temp_file.close
begin
# Get original file permissions
old_stat = stat(file_name)
rescue Errno::ENOENT
# No old permissions, write a temp file to determine the defaults
check_name = join(dirname(file_name), ".permissions_check.#{Thread.current.object_id}.#{Process.pid}.#{rand(1000000)}")
open(check_name, "w") { }
old_stat = stat(check_name)
unlink(check_name)
end
# Overwrite original file with temp file
rename(temp_file.path, file_name)
# Set correct permissions on new file
chown(old_stat.uid, old_stat.gid, file_name)
chmod(old_stat.mode, file_name)
end
end
begin
# Get original file permissions
old_stat = stat(file_name)
rescue Errno::ENOENT
# No old permissions, write a temp file to determine the defaults
check_name = join(dirname(file_name), ".permissions_check.#{Thread.current.object_id}.#{Process.pid}.#{rand(1000000)}")
open(check_name, "w") { }
old_stat = stat(check_name)
unlink(check_name)
end
# Overwrite original file with temp file
rename(temp_file.path, file_name)
# Set correct permissions on new file
chown(old_stat.uid, old_stat.gid, file_name)
chmod(old_stat.mode, file_name)
end
end

View file

@ -1,7 +1 @@
require 'active_support/core_ext/float/rounding'
require 'active_support/core_ext/float/time'
class Float #:nodoc:
include ActiveSupport::CoreExtensions::Float::Rounding
include ActiveSupport::CoreExtensions::Float::Time
end

View file

@ -1,24 +1,18 @@
module ActiveSupport #:nodoc:
module CoreExtensions #:nodoc:
module Float #:nodoc:
module Rounding
def self.included(base) #:nodoc:
base.class_eval do
alias_method :round_without_precision, :round
alias_method :round, :round_with_precision
end
end
class Float
remove_method :round
# Rounds the float with the specified precision.
#
# x = 1.337
# x.round # => 1
# x.round(1) # => 1.3
# x.round(2) # => 1.34
def round_with_precision(precision = nil)
precision.nil? ? round_without_precision : (self * (10 ** precision)).round / (10 ** precision).to_f
end
end
# Rounds the float with the specified precision.
#
# x = 1.337
# x.round # => 1
# x.round(1) # => 1.3
# x.round(2) # => 1.34
def round(precision = nil)
if precision
magnitude = 10.0 ** precision
(self * magnitude).round / magnitude
else
super()
end
end
end

View file

@ -1,27 +0,0 @@
module ActiveSupport #:nodoc:
module CoreExtensions #:nodoc:
module Float #:nodoc:
module Time
# Deprication helper methods not available as core_ext is loaded first.
def years
::ActiveSupport::Deprecation.warn(self.class.deprecated_method_warning(:years, "Fractional years are not respected. Convert value to integer before calling #years."), caller)
years_without_deprecation
end
def months
::ActiveSupport::Deprecation.warn(self.class.deprecated_method_warning(:months, "Fractional months are not respected. Convert value to integer before calling #months."), caller)
months_without_deprecation
end
def months_without_deprecation
ActiveSupport::Duration.new(self * 30.days, [[:months, self]])
end
alias :month :months
def years_without_deprecation
ActiveSupport::Duration.new(self * 365.25.days, [[:years, self]])
end
alias :year :years
end
end
end
end

View file

@ -1,14 +1,2 @@
%w(keys indifferent_access deep_merge reverse_merge conversions diff slice except).each do |ext|
require "active_support/core_ext/hash/#{ext}"
end
class Hash #:nodoc:
include ActiveSupport::CoreExtensions::Hash::Keys
include ActiveSupport::CoreExtensions::Hash::IndifferentAccess
include ActiveSupport::CoreExtensions::Hash::DeepMerge
include ActiveSupport::CoreExtensions::Hash::ReverseMerge
include ActiveSupport::CoreExtensions::Hash::Conversions
include ActiveSupport::CoreExtensions::Hash::Diff
include ActiveSupport::CoreExtensions::Hash::Slice
include ActiveSupport::CoreExtensions::Hash::Except
end
require 'active_support/core_ext/util'
ActiveSupport.core_ext Hash, %w(keys indifferent_access deep_merge reverse_merge conversions diff slice except)

View file

@ -1,9 +1,2 @@
require 'active_support/core_ext/integer/even_odd'
require 'active_support/core_ext/integer/inflections'
require 'active_support/core_ext/integer/time'
class Integer #:nodoc:
include ActiveSupport::CoreExtensions::Integer::EvenOdd
include ActiveSupport::CoreExtensions::Integer::Inflections
include ActiveSupport::CoreExtensions::Integer::Time
end
require 'active_support/core_ext/util'
ActiveSupport.core_ext Integer, %w(even_odd inflections time)

View file

@ -1,9 +1,2 @@
require 'active_support/core_ext/numeric/time'
require 'active_support/core_ext/numeric/bytes'
require 'active_support/core_ext/numeric/conversions'
class Numeric #:nodoc:
include ActiveSupport::CoreExtensions::Numeric::Time
include ActiveSupport::CoreExtensions::Numeric::Bytes
include ActiveSupport::CoreExtensions::Numeric::Conversions
end
require 'active_support/core_ext/util'
ActiveSupport.core_ext Numeric, %w(time bytes conversions)

View file

@ -1,7 +1 @@
require 'pathname'
require 'active_support/core_ext/pathname/clean_within'
class Pathname#:nodoc:
extend ActiveSupport::CoreExtensions::Pathname::CleanWithin
end

View file

@ -1,14 +1,10 @@
module ActiveSupport #:nodoc:
module CoreExtensions #:nodoc:
module Pathname #:nodoc:
module CleanWithin
# Clean the paths contained in the provided string.
def clean_within(string)
string.gsub(%r{[\w. ]+(/[\w. ]+)+(\.rb)?(\b|$)}) do |path|
new(path).cleanpath
end
end
end
require 'pathname'
class Pathname
# Clean the paths contained in the provided string.
def self.clean_within(string)
string.gsub(%r{[\w. ]+(/[\w. ]+)+(\.rb)?(\b|$)}) do |path|
new(path).cleanpath
end
end
end

View file

@ -1,25 +1,23 @@
if RUBY_VERSION < "1.9"
module Process
def self.daemon(nochdir = nil, noclose = nil)
exit if fork # Parent exits, child continues.
Process.setsid # Become session leader.
exit if fork # Zap session leader. See [1].
module Process
def self.daemon(nochdir = nil, noclose = nil)
exit if fork # Parent exits, child continues.
Process.setsid # Become session leader.
exit if fork # Zap session leader. See [1].
unless nochdir
Dir.chdir "/" # Release old working directory.
end
File.umask 0000 # Ensure sensible umask. Adjust as needed.
unless noclose
STDIN.reopen "/dev/null" # Free file descriptors and
STDOUT.reopen "/dev/null", "a" # point them somewhere sensible.
STDERR.reopen '/dev/null', 'a'
end
trap("TERM") { exit }
return 0
unless nochdir
Dir.chdir "/" # Release old working directory.
end
end
File.umask 0000 # Ensure sensible umask. Adjust as needed.
unless noclose
STDIN.reopen "/dev/null" # Free file descriptors and
STDOUT.reopen "/dev/null", "a" # point them somewhere sensible.
STDERR.reopen '/dev/null', 'a'
end
trap("TERM") { exit }
return 0
end unless respond_to?(:daemon)
end

View file

@ -1,11 +1,2 @@
require 'active_support/core_ext/range/conversions'
require 'active_support/core_ext/range/overlaps'
require 'active_support/core_ext/range/include_range'
require 'active_support/core_ext/range/blockless_step'
class Range #:nodoc:
include ActiveSupport::CoreExtensions::Range::Conversions
include ActiveSupport::CoreExtensions::Range::Overlaps
include ActiveSupport::CoreExtensions::Range::IncludeRange
include ActiveSupport::CoreExtensions::Range::BlocklessStep
end
require 'active_support/core_ext/util'
ActiveSupport.core_ext Range, %w(conversions overlaps include_range blockless_step)

View file

@ -7,7 +7,7 @@ require 'rexml/rexml'
unless (defined?(REXML::VERSION) ? REXML::VERSION : REXML::Version) > "3.1.7.2"
require 'rexml/document'
# REXML in 1.8.7 has the patch but didn't update Version from 3.1.7.2.
# REXML in 1.8.7 has the patch but early patchlevels didn't update Version from 3.1.7.2.
unless REXML::Document.respond_to?(:entity_expansion_limit=)
require 'rexml/entity'

View file

@ -1,14 +1,14 @@
unless :to_proc.respond_to?(:to_proc)
class Symbol
# Turns the symbol into a simple proc, which is especially useful for enumerations. Examples:
#
# # The same as people.collect { |p| p.name }
# people.collect(&:name)
#
# # The same as people.select { |p| p.manager? }.collect { |p| p.salary }
# people.select(&:manager?).collect(&:salary)
def to_proc
Proc.new { |*args| args.shift.__send__(self, *args) }
end
end
class Symbol
# Turns the symbol into a simple proc, which is especially useful for enumerations. Examples:
#
# # The same as people.collect { |p| p.name }
# people.collect(&:name)
#
# # The same as people.select { |p| p.manager? }.collect { |p| p.salary }
# people.select(&:manager?).collect(&:salary)
#
# This is a builtin method in Ruby 1.8.7 and later.
def to_proc
Proc.new { |*args| args.shift.__send__(self, *args) }
end unless :to_proc.respond_to?(:to_proc)
end

View file

@ -29,14 +29,5 @@ class Time
end
end
require 'active_support/core_ext/time/behavior'
require 'active_support/core_ext/time/calculations'
require 'active_support/core_ext/time/conversions'
require 'active_support/core_ext/time/zones'
class Time#:nodoc:
include ActiveSupport::CoreExtensions::Time::Behavior
include ActiveSupport::CoreExtensions::Time::Calculations
include ActiveSupport::CoreExtensions::Time::Conversions
include ActiveSupport::CoreExtensions::Time::Zones
end
require 'active_support/core_ext/util'
ActiveSupport.core_ext Time, %w(behavior calculations conversions zones)

View file

@ -0,0 +1,10 @@
module ActiveSupport
class << self
def core_ext(subject, names)
names.each do |name|
require "active_support/core_ext/#{Inflector.underscore(subject.name)}/#{name}"
subject.send :include, Inflector.constantize("ActiveSupport::CoreExtensions::#{subject.name}::#{Inflector.camelize(name)}")
end
end
end
end

View file

@ -60,26 +60,6 @@ class DurationTest < ActiveSupport::TestCase
assert_equal((7 * 24 * 1.7).hours.ago, 1.7.weeks.ago)
end
def test_deprecated_fractional_years
years_re = /Fractional years are not respected\. Convert value to integer before calling #years\./
assert_deprecated(years_re){1.0.years}
assert_deprecated(years_re){1.5.years}
assert_not_deprecated{1.years}
assert_deprecated(years_re){1.0.year}
assert_deprecated(years_re){1.5.year}
assert_not_deprecated{1.year}
end
def test_deprecated_fractional_months
months_re = /Fractional months are not respected\. Convert value to integer before calling #months\./
assert_deprecated(months_re){1.5.months}
assert_deprecated(months_re){1.0.months}
assert_not_deprecated{1.months}
assert_deprecated(months_re){1.5.month}
assert_deprecated(months_re){1.0.month}
assert_not_deprecated{1.month}
end
def test_since_and_ago_anchored_to_time_now_when_time_zone_default_not_set
Time.zone_default = nil
with_env_tz 'US/Eastern' do

View file

@ -1,4 +1,5 @@
require 'abstract_unit'
require 'active_support/core_ext/float/rounding'
class FloatExtRoundingTests < Test::Unit::TestCase
def test_round_for_positive_number