aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport/lib')
-rw-r--r--activesupport/lib/active_support.rb7
-rw-r--r--activesupport/lib/active_support/base64.rb9
-rw-r--r--activesupport/lib/active_support/basic_object.rb17
-rw-r--r--activesupport/lib/active_support/buffered_logger.rb2
-rw-r--r--activesupport/lib/active_support/cache.rb10
-rw-r--r--activesupport/lib/active_support/cache/drb_store.rb14
-rw-r--r--activesupport/lib/active_support/cache/file_store.rb2
-rw-r--r--activesupport/lib/active_support/core.rb7
-rw-r--r--activesupport/lib/active_support/core/all.rb4
-rw-r--r--activesupport/lib/active_support/core/time.rb4
-rw-r--r--activesupport/lib/active_support/core/time/autoload.rb5
-rw-r--r--activesupport/lib/active_support/core_ext.rb5
-rw-r--r--activesupport/lib/active_support/core_ext/array.rb11
-rw-r--r--activesupport/lib/active_support/core_ext/array/access.rb85
-rw-r--r--activesupport/lib/active_support/core_ext/array/conversions.rb346
-rw-r--r--activesupport/lib/active_support/core_ext/array/extract_options.rb30
-rw-r--r--activesupport/lib/active_support/core_ext/array/grouping.rb180
-rw-r--r--activesupport/lib/active_support/core_ext/array/random_access.rb14
-rw-r--r--activesupport/lib/active_support/core_ext/array/wrap.rb18
-rw-r--r--activesupport/lib/active_support/core_ext/array/wrapper.rb24
-rw-r--r--activesupport/lib/active_support/core_ext/base64.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/base64/encoding.rb16
-rw-r--r--activesupport/lib/active_support/core_ext/big_decimal.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/big_decimal/conversions.rb27
-rw-r--r--activesupport/lib/active_support/core_ext/bigdecimal.rb6
-rw-r--r--activesupport/lib/active_support/core_ext/bigdecimal/conversions.rb37
-rw-r--r--activesupport/lib/active_support/core_ext/cgi.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb34
-rw-r--r--activesupport/lib/active_support/core_ext/class/delegating_attributes.rb48
-rw-r--r--activesupport/lib/active_support/core_ext/date.rb11
-rw-r--r--activesupport/lib/active_support/core_ext/date/acts_like.rb8
-rw-r--r--activesupport/lib/active_support/core_ext/date/behavior.rb42
-rw-r--r--activesupport/lib/active_support/core_ext/date/calculations.rb439
-rw-r--r--activesupport/lib/active_support/core_ext/date/conversions.rb182
-rw-r--r--activesupport/lib/active_support/core_ext/date/freeze.rb31
-rw-r--r--activesupport/lib/active_support/core_ext/date_time.rb12
-rw-r--r--activesupport/lib/active_support/core_ext/date_time/acts_like.rb13
-rw-r--r--activesupport/lib/active_support/core_ext/date_time/calculations.rb202
-rw-r--r--activesupport/lib/active_support/core_ext/date_time/conversions.rb162
-rw-r--r--activesupport/lib/active_support/core_ext/date_time/zones.rb17
-rw-r--r--activesupport/lib/active_support/core_ext/enumerable.rb7
-rw-r--r--activesupport/lib/active_support/core_ext/exception.rb21
-rw-r--r--activesupport/lib/active_support/core_ext/file.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/file/atomic.rb74
-rw-r--r--activesupport/lib/active_support/core_ext/float.rb6
-rw-r--r--activesupport/lib/active_support/core_ext/float/rounding.rb34
-rw-r--r--activesupport/lib/active_support/core_ext/float/time.rb27
-rw-r--r--activesupport/lib/active_support/core_ext/hash.rb22
-rw-r--r--activesupport/lib/active_support/core_ext/hash/conversions.rb424
-rw-r--r--activesupport/lib/active_support/core_ext/hash/deep_merge.rb33
-rw-r--r--activesupport/lib/active_support/core_ext/hash/diff.rb28
-rw-r--r--activesupport/lib/active_support/core_ext/hash/except.rb35
-rw-r--r--activesupport/lib/active_support/core_ext/hash/indifferent_access.rb146
-rw-r--r--activesupport/lib/active_support/core_ext/hash/keys.rb84
-rw-r--r--activesupport/lib/active_support/core_ext/hash/reverse_merge.rb57
-rw-r--r--activesupport/lib/active_support/core_ext/hash/slice.rb66
-rw-r--r--activesupport/lib/active_support/core_ext/integer.rb6
-rw-r--r--activesupport/lib/active_support/core_ext/integer/even_odd.rb39
-rw-r--r--activesupport/lib/active_support/core_ext/integer/inflections.rb26
-rw-r--r--activesupport/lib/active_support/core_ext/integer/time.rb78
-rw-r--r--activesupport/lib/active_support/core_ext/kernel/reporting.rb14
-rw-r--r--activesupport/lib/active_support/core_ext/load_error.rb15
-rw-r--r--activesupport/lib/active_support/core_ext/module.rb5
-rw-r--r--activesupport/lib/active_support/core_ext/module/aliasing.rb132
-rw-r--r--activesupport/lib/active_support/core_ext/module/attribute_accessors.rb52
-rw-r--r--activesupport/lib/active_support/core_ext/module/deprecation.rb9
-rw-r--r--activesupport/lib/active_support/core_ext/module/introspection.rb154
-rw-r--r--activesupport/lib/active_support/core_ext/name_error.rb7
-rw-r--r--activesupport/lib/active_support/core_ext/numeric.rb9
-rw-r--r--activesupport/lib/active_support/core_ext/numeric/bytes.rb69
-rw-r--r--activesupport/lib/active_support/core_ext/numeric/conversions.rb19
-rw-r--r--activesupport/lib/active_support/core_ext/numeric/time.rb144
-rw-r--r--activesupport/lib/active_support/core_ext/object.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/object/acts_like.rb10
-rw-r--r--activesupport/lib/active_support/core_ext/object/blank.rb (renamed from activesupport/lib/active_support/core_ext/blank.rb)2
-rw-r--r--activesupport/lib/active_support/core_ext/object/duplicable.rb (renamed from activesupport/lib/active_support/core_ext/duplicable.rb)0
-rw-r--r--activesupport/lib/active_support/core_ext/object/misc.rb10
-rw-r--r--activesupport/lib/active_support/core_ext/object/try.rb (renamed from activesupport/lib/active_support/core_ext/try.rb)8
-rw-r--r--activesupport/lib/active_support/core_ext/pathname.rb7
-rw-r--r--activesupport/lib/active_support/core_ext/pathname/clean_within.rb14
-rw-r--r--activesupport/lib/active_support/core_ext/process/daemon.rb36
-rw-r--r--activesupport/lib/active_support/core_ext/range.rb11
-rw-r--r--activesupport/lib/active_support/core_ext/range/blockless_step.rb51
-rw-r--r--activesupport/lib/active_support/core_ext/range/conversions.rb40
-rw-r--r--activesupport/lib/active_support/core_ext/range/include_range.rb45
-rw-r--r--activesupport/lib/active_support/core_ext/range/overlaps.rb19
-rw-r--r--activesupport/lib/active_support/core_ext/rexml.rb8
-rw-r--r--activesupport/lib/active_support/core_ext/string.rb13
-rw-r--r--activesupport/lib/active_support/core_ext/string/conversions.rb35
-rw-r--r--activesupport/lib/active_support/core_ext/string/filters.rb40
-rw-r--r--activesupport/lib/active_support/core_ext/string/iterators.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/string/multibyte.rb145
-rw-r--r--activesupport/lib/active_support/core_ext/string/starts_ends_with.rb45
-rw-r--r--activesupport/lib/active_support/core_ext/string/xchar.rb13
-rw-r--r--activesupport/lib/active_support/core_ext/symbol.rb26
-rw-r--r--activesupport/lib/active_support/core_ext/time.rb38
-rw-r--r--activesupport/lib/active_support/core_ext/time/acts_like.rb8
-rw-r--r--activesupport/lib/active_support/core_ext/time/behavior.rb13
-rw-r--r--activesupport/lib/active_support/core_ext/time/calculations.rb564
-rw-r--r--activesupport/lib/active_support/core_ext/time/conversions.rb160
-rw-r--r--activesupport/lib/active_support/core_ext/time/marshal_with_utc_flag.rb22
-rw-r--r--activesupport/lib/active_support/core_ext/time/publicize_conversion_methods.rb10
-rw-r--r--activesupport/lib/active_support/core_ext/time/zones.rb154
-rw-r--r--activesupport/lib/active_support/core_ext/util.rb10
-rw-r--r--activesupport/lib/active_support/dependencies.rb20
-rw-r--r--activesupport/lib/active_support/deprecation.rb196
-rw-r--r--activesupport/lib/active_support/deprecation/behaviors.rb32
-rw-r--r--activesupport/lib/active_support/deprecation/method_wrappers.rb27
-rw-r--r--activesupport/lib/active_support/deprecation/proxy_wrappers.rb72
-rw-r--r--activesupport/lib/active_support/deprecation/reporting.rb55
-rw-r--r--activesupport/lib/active_support/hash_with_indifferent_access.rb133
-rw-r--r--activesupport/lib/active_support/inflector.rb7
-rw-r--r--activesupport/lib/active_support/json/decoding.rb12
-rw-r--r--activesupport/lib/active_support/json/encoders/hash.rb2
-rw-r--r--activesupport/lib/active_support/json/encoders/object.rb2
-rw-r--r--activesupport/lib/active_support/option_merger.rb2
-rw-r--r--activesupport/lib/active_support/ordered_options.rb4
-rw-r--r--activesupport/lib/active_support/rescuable.rb3
-rw-r--r--activesupport/lib/active_support/time_with_zone.rb14
-rw-r--r--activesupport/lib/active_support/values/time_zone.rb23
-rw-r--r--activesupport/lib/active_support/vendor.rb1
-rwxr-xr-xactivesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n.rb9
-rw-r--r--activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n/backend/simple.rb5
-rw-r--r--activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n/exceptions.rb2
-rw-r--r--activesupport/lib/active_support/xml_mini/libxml.rb8
-rw-r--r--activesupport/lib/active_support/xml_mini/nokogiri.rb6
-rw-r--r--activesupport/lib/active_support/xml_mini/rexml.rb4
127 files changed, 2901 insertions, 3237 deletions
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb
index dbd30f9271..21b730fa0c 100644
--- a/activesupport/lib/active_support.rb
+++ b/activesupport/lib/active_support.rb
@@ -23,7 +23,7 @@
module ActiveSupport
def self.load_all!
- [Dependencies, Deprecation, Gzip, MessageVerifier, Multibyte, SecureRandom, TimeWithZone]
+ [Dependencies, Deprecation, Gzip, MessageVerifier, Multibyte, SecureRandom] + Core.load_all!
end
autoload :BacktraceCleaner, 'active_support/backtrace_cleaner'
@@ -35,7 +35,6 @@ module ActiveSupport
autoload :NewCallbacks, 'active_support/new_callbacks'
autoload :ConcurrentHash, 'active_support/concurrent_hash'
autoload :Deprecation, 'active_support/deprecation'
- autoload :Duration, 'active_support/duration'
autoload :Gzip, 'active_support/gzip'
autoload :Inflector, 'active_support/inflector'
autoload :Memoizable, 'active_support/memoizable'
@@ -48,11 +47,11 @@ module ActiveSupport
autoload :Rescuable, 'active_support/rescuable'
autoload :SecureRandom, 'active_support/secure_random'
autoload :StringInquirer, 'active_support/string_inquirer'
- autoload :TimeWithZone, 'active_support/time_with_zone'
- autoload :TimeZone, 'active_support/values/time_zone'
autoload :XmlMini, 'active_support/xml_mini'
end
+require 'active_support/core/all'
+
require 'active_support/vendor'
require 'active_support/core_ext'
require 'active_support/dependencies'
diff --git a/activesupport/lib/active_support/base64.rb b/activesupport/lib/active_support/base64.rb
index acb8e5a967..b8c01628ce 100644
--- a/activesupport/lib/active_support/base64.rb
+++ b/activesupport/lib/active_support/base64.rb
@@ -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
diff --git a/activesupport/lib/active_support/basic_object.rb b/activesupport/lib/active_support/basic_object.rb
index 1f77209e7f..3b5277c205 100644
--- a/activesupport/lib/active_support/basic_object.rb
+++ b/activesupport/lib/active_support/basic_object.rb
@@ -1,13 +1,7 @@
-# A base class with no predefined methods that tries to behave like Builder's
-# BlankSlate in Ruby 1.9. In Ruby pre-1.9, this is actually the
-# Builder::BlankSlate class.
-#
-# Ruby 1.9 introduces BasicObject which differs slightly from Builder's
-# BlankSlate that has been used so far. ActiveSupport::BasicObject provides a
-# barebones base class that emulates Builder::BlankSlate while still relying on
-# Ruby 1.9's BasicObject in Ruby 1.9.
module ActiveSupport
if defined? ::BasicObject
+ # A class with no predefined methods that behaves similarly to Builder's
+ # BlankSlate. Used for proxy classes.
class BasicObject < ::BasicObject
undef_method :==
undef_method :equal?
@@ -18,7 +12,10 @@ module ActiveSupport
end
end
else
- require 'blankslate'
- BasicObject = BlankSlate
+ class BasicObject #:nodoc:
+ instance_methods.each do |m|
+ undef_method(m) if m.to_s !~ /(?:^__|^nil\?$|^send$|^object_id$)/
+ end
+ end
end
end
diff --git a/activesupport/lib/active_support/buffered_logger.rb b/activesupport/lib/active_support/buffered_logger.rb
index 568c596f91..ee66479dde 100644
--- a/activesupport/lib/active_support/buffered_logger.rb
+++ b/activesupport/lib/active_support/buffered_logger.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/class/attribute_accessors'
+
module ActiveSupport
# Inspired by the buffered logger idea by Ezra
class BufferedLogger
diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb
index 83174d3a85..4b2eebb007 100644
--- a/activesupport/lib/active_support/cache.rb
+++ b/activesupport/lib/active_support/cache.rb
@@ -1,4 +1,7 @@
require 'benchmark'
+require 'active_support/core_ext/benchmark'
+require 'active_support/core_ext/exception'
+require 'active_support/core_ext/class/attribute_accessors'
module ActiveSupport
# See ActiveSupport::Cache::Store for documentation.
@@ -6,7 +9,6 @@ module ActiveSupport
autoload :FileStore, 'active_support/cache/file_store'
autoload :MemoryStore, 'active_support/cache/memory_store'
autoload :SynchronizedMemoryStore, 'active_support/cache/synchronized_memory_store'
- autoload :DRbStore, 'active_support/cache/drb_store'
autoload :MemCacheStore, 'active_support/cache/mem_cache_store'
autoload :CompressedMemCacheStore, 'active_support/cache/compressed_mem_cache_store'
@@ -26,8 +28,8 @@ module ActiveSupport
# ActiveSupport::Cache.lookup_store(:memory_store)
# # => returns a new ActiveSupport::Cache::MemoryStore object
#
- # ActiveSupport::Cache.lookup_store(:drb_store)
- # # => returns a new ActiveSupport::Cache::DRbStore object
+ # ActiveSupport::Cache.lookup_store(:mem_cache_store)
+ # # => returns a new ActiveSupport::Cache::MemCacheStore object
#
# Any additional arguments will be passed to the corresponding cache store
# class's constructor:
@@ -44,7 +46,7 @@ module ActiveSupport
case store
when Symbol
- store_class_name = (store == :drb_store ? "DRbStore" : store.to_s.camelize)
+ store_class_name = store.to_s.camelize
store_class = ActiveSupport::Cache.const_get(store_class_name)
store_class.new(*parameters)
when nil
diff --git a/activesupport/lib/active_support/cache/drb_store.rb b/activesupport/lib/active_support/cache/drb_store.rb
deleted file mode 100644
index b16ed25aa3..0000000000
--- a/activesupport/lib/active_support/cache/drb_store.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-module ActiveSupport
- module Cache
- class DRbStore < MemoryStore #:nodoc:
- attr_reader :address
-
- def initialize(address = 'druby://localhost:9192')
- require 'drb' unless defined?(DRbObject)
- super()
- @address = address
- @data = DRbObject.new(nil, address)
- end
- end
- end
-end
diff --git a/activesupport/lib/active_support/cache/file_store.rb b/activesupport/lib/active_support/cache/file_store.rb
index 7f34cb52a1..3217350d58 100644
--- a/activesupport/lib/active_support/cache/file_store.rb
+++ b/activesupport/lib/active_support/cache/file_store.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/file/atomic'
+
module ActiveSupport
module Cache
# A cache store implementation which stores everything on the filesystem.
diff --git a/activesupport/lib/active_support/core.rb b/activesupport/lib/active_support/core.rb
new file mode 100644
index 0000000000..ad8db94941
--- /dev/null
+++ b/activesupport/lib/active_support/core.rb
@@ -0,0 +1,7 @@
+module ActiveSupport
+ module Core
+ def self.load_all!
+ [TimeWithZone]
+ end
+ end
+end
diff --git a/activesupport/lib/active_support/core/all.rb b/activesupport/lib/active_support/core/all.rb
new file mode 100644
index 0000000000..f397f48e9c
--- /dev/null
+++ b/activesupport/lib/active_support/core/all.rb
@@ -0,0 +1,4 @@
+require 'active_support/core'
+Dir["#{File.dirname(__FILE__)}/*.rb"].sort.each do |path|
+ require "active_support/core/#{File.basename(path, '.rb')}"
+end
diff --git a/activesupport/lib/active_support/core/time.rb b/activesupport/lib/active_support/core/time.rb
new file mode 100644
index 0000000000..43e13b5e58
--- /dev/null
+++ b/activesupport/lib/active_support/core/time.rb
@@ -0,0 +1,4 @@
+require 'active_support/core/time/autoload'
+require 'active_support/core_ext/time'
+require 'active_support/core_ext/date'
+require 'active_support/core_ext/date_time'
diff --git a/activesupport/lib/active_support/core/time/autoload.rb b/activesupport/lib/active_support/core/time/autoload.rb
new file mode 100644
index 0000000000..c9a7731b39
--- /dev/null
+++ b/activesupport/lib/active_support/core/time/autoload.rb
@@ -0,0 +1,5 @@
+module ActiveSupport
+ autoload :Duration, 'active_support/duration'
+ autoload :TimeWithZone, 'active_support/time_with_zone'
+ autoload :TimeZone, 'active_support/values/time_zone'
+end
diff --git a/activesupport/lib/active_support/core_ext.rb b/activesupport/lib/active_support/core_ext.rb
index f2f976df9b..46a8609dd7 100644
--- a/activesupport/lib/active_support/core_ext.rb
+++ b/activesupport/lib/active_support/core_ext.rb
@@ -1,4 +1,3 @@
-Dir[File.dirname(__FILE__) + "/core_ext/*.rb"].sort.each do |path|
- filename = File.basename(path, '.rb')
- require "active_support/core_ext/#{filename}"
+Dir["#{File.dirname(__FILE__)}/core_ext/*.rb"].sort.each do |path|
+ require "active_support/core_ext/#{File.basename(path, '.rb')}"
end
diff --git a/activesupport/lib/active_support/core_ext/array.rb b/activesupport/lib/active_support/core_ext/array.rb
index 82c6b1243a..b583c7533e 100644
--- a/activesupport/lib/active_support/core_ext/array.rb
+++ b/activesupport/lib/active_support/core_ext/array.rb
@@ -1,15 +1,6 @@
+require 'active_support/core_ext/array/wrap'
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
diff --git a/activesupport/lib/active_support/core_ext/array/access.rb b/activesupport/lib/active_support/core_ext/array/access.rb
index 6de338bfcc..d7606bb9b0 100644
--- a/activesupport/lib/active_support/core_ext/array/access.rb
+++ b/activesupport/lib/active_support/core_ext/array/access.rb
@@ -1,53 +1,46 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Array #:nodoc:
- # Makes it easier to access parts of an array.
- module Access
- # Returns the tail of the array from +position+.
- #
- # %w( a b c d ).from(0) # => %w( a b c d )
- # %w( a b c d ).from(2) # => %w( c d )
- # %w( a b c d ).from(10) # => nil
- # %w().from(0) # => nil
- def from(position)
- self[position..-1]
- end
-
- # Returns the beginning of the array up to +position+.
- #
- # %w( a b c d ).to(0) # => %w( a )
- # %w( a b c d ).to(2) # => %w( a b c )
- # %w( a b c d ).to(10) # => %w( a b c d )
- # %w().to(0) # => %w()
- def to(position)
- self[0..position]
- end
+class Array
+ # Returns the tail of the array from +position+.
+ #
+ # %w( a b c d ).from(0) # => %w( a b c d )
+ # %w( a b c d ).from(2) # => %w( c d )
+ # %w( a b c d ).from(10) # => nil
+ # %w().from(0) # => nil
+ def from(position)
+ self[position..-1]
+ end
- # Equal to <tt>self[1]</tt>.
- def second
- self[1]
- end
+ # Returns the beginning of the array up to +position+.
+ #
+ # %w( a b c d ).to(0) # => %w( a )
+ # %w( a b c d ).to(2) # => %w( a b c )
+ # %w( a b c d ).to(10) # => %w( a b c d )
+ # %w().to(0) # => %w()
+ def to(position)
+ self[0..position]
+ end
- # Equal to <tt>self[2]</tt>.
- def third
- self[2]
- end
+ # Equal to <tt>self[1]</tt>.
+ def second
+ self[1]
+ end
- # Equal to <tt>self[3]</tt>.
- def fourth
- self[3]
- end
+ # Equal to <tt>self[2]</tt>.
+ def third
+ self[2]
+ end
- # Equal to <tt>self[4]</tt>.
- def fifth
- self[4]
- end
+ # Equal to <tt>self[3]</tt>.
+ def fourth
+ self[3]
+ end
+
+ # Equal to <tt>self[4]</tt>.
+ def fifth
+ self[4]
+ end
- # Equal to <tt>self[41]</tt>. Also known as accessing "the reddit".
- def forty_two
- self[41]
- end
- end
- end
+ # Equal to <tt>self[41]</tt>. Also known as accessing "the reddit".
+ def forty_two
+ self[41]
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 ba8e022fb2..81e466779e 100644
--- a/activesupport/lib/active_support/core_ext/array/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/array/conversions.rb
@@ -1,196 +1,184 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Array #:nodoc:
- module Conversions
- # Converts the array to a comma-separated sentence where the last element is joined by the connector word. Options:
- # * <tt>:words_connector</tt> - The sign or word used to join the elements in arrays with two or more elements (default: ", ")
- # * <tt>:two_words_connector</tt> - The sign or word used to join the elements in arrays with two elements (default: " and ")
- # * <tt>:last_word_connector</tt> - The sign or word used to join the last element in arrays with three or more elements (default: ", and ")
- def to_sentence(options = {})
- default_words_connector = I18n.translate(:'support.array.words_connector', :locale => options[:locale])
- default_two_words_connector = I18n.translate(:'support.array.two_words_connector', :locale => options[:locale])
- default_last_word_connector = I18n.translate(:'support.array.last_word_connector', :locale => options[:locale])
+class Array
+ # Converts the array to a comma-separated sentence where the last element is joined by the connector word. Options:
+ # * <tt>:words_connector</tt> - The sign or word used to join the elements in arrays with two or more elements (default: ", ")
+ # * <tt>:two_words_connector</tt> - The sign or word used to join the elements in arrays with two elements (default: " and ")
+ # * <tt>:last_word_connector</tt> - The sign or word used to join the last element in arrays with three or more elements (default: ", and ")
+ def to_sentence(options = {})
+ default_words_connector = I18n.translate(:'support.array.words_connector', :locale => options[:locale])
+ default_two_words_connector = I18n.translate(:'support.array.two_words_connector', :locale => options[:locale])
+ default_last_word_connector = I18n.translate(:'support.array.last_word_connector', :locale => options[:locale])
- # Try to emulate to_senteces previous to 2.3
- if options.has_key?(:connector) || options.has_key?(:skip_last_comma)
- ::ActiveSupport::Deprecation.warn(":connector has been deprecated. Use :words_connector instead", caller) if options.has_key? :connector
- ::ActiveSupport::Deprecation.warn(":skip_last_comma has been deprecated. Use :last_word_connector instead", caller) if options.has_key? :skip_last_comma
+ # Try to emulate to_senteces previous to 2.3
+ if options.has_key?(:connector) || options.has_key?(:skip_last_comma)
+ ::ActiveSupport::Deprecation.warn(":connector has been deprecated. Use :words_connector instead", caller) if options.has_key? :connector
+ ::ActiveSupport::Deprecation.warn(":skip_last_comma has been deprecated. Use :last_word_connector instead", caller) if options.has_key? :skip_last_comma
- skip_last_comma = options.delete :skip_last_comma
- if connector = options.delete(:connector)
- options[:last_word_connector] ||= skip_last_comma ? connector : ", #{connector}"
- else
- options[:last_word_connector] ||= skip_last_comma ? default_two_words_connector : default_last_word_connector
- end
- end
-
- options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector, :locale)
- options.reverse_merge! :words_connector => default_words_connector, :two_words_connector => default_two_words_connector, :last_word_connector => default_last_word_connector
-
- case length
- when 0
- ""
- when 1
- self[0].to_s
- when 2
- "#{self[0]}#{options[:two_words_connector]}#{self[1]}"
- else
- "#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
- end
- end
-
+ skip_last_comma = options.delete :skip_last_comma
+ if connector = options.delete(:connector)
+ options[:last_word_connector] ||= skip_last_comma ? connector : ", #{connector}"
+ else
+ options[:last_word_connector] ||= skip_last_comma ? default_two_words_connector : default_last_word_connector
+ end
+ end
- # Calls <tt>to_param</tt> on all its elements and joins the result with
- # slashes. This is used by <tt>url_for</tt> in Action Pack.
- def to_param
- collect { |e| e.to_param }.join '/'
- end
+ options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector, :locale)
+ options.reverse_merge! :words_connector => default_words_connector, :two_words_connector => default_two_words_connector, :last_word_connector => default_last_word_connector
- # Converts an array into a string suitable for use as a URL query string,
- # using the given +key+ as the param name.
- #
- # ['Rails', 'coding'].to_query('hobbies') # => "hobbies%5B%5D=Rails&hobbies%5B%5D=coding"
- def to_query(key)
- prefix = "#{key}[]"
- collect { |value| value.to_query(prefix) }.join '&'
- end
+ case length
+ when 0
+ ""
+ when 1
+ self[0].to_s
+ when 2
+ "#{self[0]}#{options[:two_words_connector]}#{self[1]}"
+ else
+ "#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
+ end
+ end
- def self.included(base) #:nodoc:
- base.class_eval do
- alias_method :to_default_s, :to_s
- alias_method :to_s, :to_formatted_s
- end
- end
- # 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"
- #
- # 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"
- def to_formatted_s(format = :default)
- case format
- when :db
- if respond_to?(:empty?) && self.empty?
- "null"
- else
- collect { |element| element.id }.join(",")
- end
- else
- to_default_s
- end
- end
+ # Calls <tt>to_param</tt> on all its elements and joins the result with
+ # slashes. This is used by <tt>url_for</tt> in Action Pack.
+ def to_param
+ collect { |e| e.to_param }.join '/'
+ end
- # Returns a string that represents this array in XML by sending +to_xml+
- # to each element. Active Record collections delegate their representation
- # in XML to this method.
- #
- # All elements are expected to respond to +to_xml+, if any of them does
- # not an exception is raised.
- #
- # The root node reflects the class name of the first element in plural
- # if all elements belong to the same type and that's not Hash:
- #
- # customer.projects.to_xml
- #
- # <?xml version="1.0" encoding="UTF-8"?>
- # <projects type="array">
- # <project>
- # <amount type="decimal">20000.0</amount>
- # <customer-id type="integer">1567</customer-id>
- # <deal-date type="date">2008-04-09</deal-date>
- # ...
- # </project>
- # <project>
- # <amount type="decimal">57230.0</amount>
- # <customer-id type="integer">1567</customer-id>
- # <deal-date type="date">2008-04-15</deal-date>
- # ...
- # </project>
- # </projects>
- #
- # Otherwise the root element is "records":
- #
- # [{:foo => 1, :bar => 2}, {:baz => 3}].to_xml
- #
- # <?xml version="1.0" encoding="UTF-8"?>
- # <records type="array">
- # <record>
- # <bar type="integer">2</bar>
- # <foo type="integer">1</foo>
- # </record>
- # <record>
- # <baz type="integer">3</baz>
- # </record>
- # </records>
- #
- # If the collection is empty the root element is "nil-classes" by default:
- #
- # [].to_xml
- #
- # <?xml version="1.0" encoding="UTF-8"?>
- # <nil-classes type="array"/>
- #
- # To ensure a meaningful root element use the <tt>:root</tt> option:
- #
- # customer_with_no_projects.projects.to_xml(:root => "projects")
- #
- # <?xml version="1.0" encoding="UTF-8"?>
- # <projects type="array"/>
- #
- # By default root children have as node name the one of the root
- # singularized. You can change it with the <tt>:children</tt> option.
- #
- # The +options+ hash is passed downwards:
- #
- # Message.all.to_xml(:skip_types => true)
- #
- # <?xml version="1.0" encoding="UTF-8"?>
- # <messages>
- # <message>
- # <created-at>2008-03-07T09:58:18+01:00</created-at>
- # <id>1</id>
- # <name>1</name>
- # <updated-at>2008-03-07T09:58:18+01:00</updated-at>
- # <user-id>1</user-id>
- # </message>
- # </messages>
- #
- def to_xml(options = {})
- raise "Not all elements respond to to_xml" unless all? { |e| e.respond_to? :to_xml }
- require 'builder' unless defined?(Builder)
+ # Converts an array into a string suitable for use as a URL query string,
+ # using the given +key+ as the param name.
+ #
+ # ['Rails', 'coding'].to_query('hobbies') # => "hobbies%5B%5D=Rails&hobbies%5B%5D=coding"
+ def to_query(key)
+ prefix = "#{key}[]"
+ collect { |value| value.to_query(prefix) }.join '&'
+ end
- options[:root] ||= all? { |e| e.is_a?(first.class) && first.class.to_s != "Hash" } ? first.class.to_s.underscore.pluralize : "records"
- options[:children] ||= options[:root].singularize
- options[:indent] ||= 2
- options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
+ # 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"
+ #
+ # 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"
+ def to_formatted_s(format = :default)
+ case format
+ when :db
+ if respond_to?(:empty?) && self.empty?
+ "null"
+ else
+ collect { |element| element.id }.join(",")
+ end
+ else
+ to_default_s
+ end
+ end
+ alias_method :to_default_s, :to_s
+ alias_method :to_s, :to_formatted_s
- root = options.delete(:root).to_s
- children = options.delete(:children)
+ # Returns a string that represents this array in XML by sending +to_xml+
+ # to each element. Active Record collections delegate their representation
+ # in XML to this method.
+ #
+ # All elements are expected to respond to +to_xml+, if any of them does
+ # not an exception is raised.
+ #
+ # The root node reflects the class name of the first element in plural
+ # if all elements belong to the same type and that's not Hash:
+ #
+ # customer.projects.to_xml
+ #
+ # <?xml version="1.0" encoding="UTF-8"?>
+ # <projects type="array">
+ # <project>
+ # <amount type="decimal">20000.0</amount>
+ # <customer-id type="integer">1567</customer-id>
+ # <deal-date type="date">2008-04-09</deal-date>
+ # ...
+ # </project>
+ # <project>
+ # <amount type="decimal">57230.0</amount>
+ # <customer-id type="integer">1567</customer-id>
+ # <deal-date type="date">2008-04-15</deal-date>
+ # ...
+ # </project>
+ # </projects>
+ #
+ # Otherwise the root element is "records":
+ #
+ # [{:foo => 1, :bar => 2}, {:baz => 3}].to_xml
+ #
+ # <?xml version="1.0" encoding="UTF-8"?>
+ # <records type="array">
+ # <record>
+ # <bar type="integer">2</bar>
+ # <foo type="integer">1</foo>
+ # </record>
+ # <record>
+ # <baz type="integer">3</baz>
+ # </record>
+ # </records>
+ #
+ # If the collection is empty the root element is "nil-classes" by default:
+ #
+ # [].to_xml
+ #
+ # <?xml version="1.0" encoding="UTF-8"?>
+ # <nil-classes type="array"/>
+ #
+ # To ensure a meaningful root element use the <tt>:root</tt> option:
+ #
+ # customer_with_no_projects.projects.to_xml(:root => "projects")
+ #
+ # <?xml version="1.0" encoding="UTF-8"?>
+ # <projects type="array"/>
+ #
+ # By default root children have as node name the one of the root
+ # singularized. You can change it with the <tt>:children</tt> option.
+ #
+ # The +options+ hash is passed downwards:
+ #
+ # Message.all.to_xml(:skip_types => true)
+ #
+ # <?xml version="1.0" encoding="UTF-8"?>
+ # <messages>
+ # <message>
+ # <created-at>2008-03-07T09:58:18+01:00</created-at>
+ # <id>1</id>
+ # <name>1</name>
+ # <updated-at>2008-03-07T09:58:18+01:00</updated-at>
+ # <user-id>1</user-id>
+ # </message>
+ # </messages>
+ #
+ def to_xml(options = {})
+ raise "Not all elements respond to to_xml" unless all? { |e| e.respond_to? :to_xml }
+ require 'builder' unless defined?(Builder)
- if !options.has_key?(:dasherize) || options[:dasherize]
- root = root.dasherize
- end
+ options[:root] ||= all? { |e| e.is_a?(first.class) && first.class.to_s != "Hash" } ? first.class.to_s.underscore.pluralize : "records"
+ options[:children] ||= options[:root].singularize
+ options[:indent] ||= 2
+ options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
- options[:builder].instruct! unless options.delete(:skip_instruct)
+ root = options.delete(:root).to_s
+ children = options.delete(:children)
- opts = options.merge({ :root => children })
+ if !options.has_key?(:dasherize) || options[:dasherize]
+ root = root.dasherize
+ end
- xml = options[:builder]
- if empty?
- xml.tag!(root, options[:skip_types] ? {} : {:type => "array"})
- else
- xml.tag!(root, options[:skip_types] ? {} : {:type => "array"}) {
- yield xml if block_given?
- each { |e| e.to_xml(opts.merge({ :skip_instruct => true })) }
- }
- end
- end
+ options[:builder].instruct! unless options.delete(:skip_instruct)
- end
+ opts = options.merge({ :root => children })
+
+ xml = options[:builder]
+ if empty?
+ xml.tag!(root, options[:skip_types] ? {} : {:type => "array"})
+ else
+ xml.tag!(root, options[:skip_types] ? {} : {:type => "array"}) {
+ yield xml if block_given?
+ each { |e| e.to_xml(opts.merge({ :skip_instruct => true })) }
+ }
end
end
end
diff --git a/activesupport/lib/active_support/core_ext/array/extract_options.rb b/activesupport/lib/active_support/core_ext/array/extract_options.rb
index eb917576d7..9ca32dc7aa 100644
--- a/activesupport/lib/active_support/core_ext/array/extract_options.rb
+++ b/activesupport/lib/active_support/core_ext/array/extract_options.rb
@@ -1,20 +1,14 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Array #:nodoc:
- module ExtractOptions
- # Extracts options from a set of arguments. Removes and returns the last
- # element in the array if it's a hash, otherwise returns a blank hash.
- #
- # def options(*args)
- # args.extract_options!
- # end
- #
- # options(1, 2) # => {}
- # options(1, 2, :a => :b) # => {:a=>:b}
- def extract_options!
- last.is_a?(::Hash) ? pop : {}
- end
- end
- end
+class Array
+ # Extracts options from a set of arguments. Removes and returns the last
+ # element in the array if it's a hash, otherwise returns a blank hash.
+ #
+ # def options(*args)
+ # args.extract_options!
+ # end
+ #
+ # options(1, 2) # => {}
+ # options(1, 2, :a => :b) # => {:a=>:b}
+ def extract_options!
+ last.is_a?(::Hash) ? pop : {}
end
end
diff --git a/activesupport/lib/active_support/core_ext/array/grouping.rb b/activesupport/lib/active_support/core_ext/array/grouping.rb
index f782f8facf..ef416787a9 100644
--- a/activesupport/lib/active_support/core_ext/array/grouping.rb
+++ b/activesupport/lib/active_support/core_ext/array/grouping.rb
@@ -1,106 +1,100 @@
require 'enumerator'
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Array #:nodoc:
- module Grouping
- # Splits or iterates over the array in groups of size +number+,
- # padding any remaining slots with +fill_with+ unless it is +false+.
- #
- # %w(1 2 3 4 5 6 7).in_groups_of(3) {|group| p group}
- # ["1", "2", "3"]
- # ["4", "5", "6"]
- # ["7", nil, nil]
- #
- # %w(1 2 3).in_groups_of(2, '&nbsp;') {|group| p group}
- # ["1", "2"]
- # ["3", "&nbsp;"]
- #
- # %w(1 2 3).in_groups_of(2, false) {|group| p group}
- # ["1", "2"]
- # ["3"]
- def in_groups_of(number, fill_with = nil)
- if fill_with == false
- collection = self
- else
- # size % number gives how many extra we have;
- # subtracting from number gives how many to add;
- # modulo number ensures we don't add group of just fill.
- padding = (number - size % number) % number
- collection = dup.concat([fill_with] * padding)
- end
-
- if block_given?
- collection.each_slice(number) { |slice| yield(slice) }
- else
- returning [] do |groups|
- collection.each_slice(number) { |group| groups << group }
- end
- end
- end
+class Array
+ # Splits or iterates over the array in groups of size +number+,
+ # padding any remaining slots with +fill_with+ unless it is +false+.
+ #
+ # %w(1 2 3 4 5 6 7).in_groups_of(3) {|group| p group}
+ # ["1", "2", "3"]
+ # ["4", "5", "6"]
+ # ["7", nil, nil]
+ #
+ # %w(1 2 3).in_groups_of(2, '&nbsp;') {|group| p group}
+ # ["1", "2"]
+ # ["3", "&nbsp;"]
+ #
+ # %w(1 2 3).in_groups_of(2, false) {|group| p group}
+ # ["1", "2"]
+ # ["3"]
+ def in_groups_of(number, fill_with = nil)
+ if fill_with == false
+ collection = self
+ else
+ # size % number gives how many extra we have;
+ # subtracting from number gives how many to add;
+ # modulo number ensures we don't add group of just fill.
+ padding = (number - size % number) % number
+ collection = dup.concat([fill_with] * padding)
+ end
- # Splits or iterates over the array in +number+ of groups, padding any
- # remaining slots with +fill_with+ unless it is +false+.
- #
- # %w(1 2 3 4 5 6 7 8 9 10).in_groups(3) {|group| p group}
- # ["1", "2", "3", "4"]
- # ["5", "6", "7", nil]
- # ["8", "9", "10", nil]
- #
- # %w(1 2 3 4 5 6 7).in_groups(3, '&nbsp;') {|group| p group}
- # ["1", "2", "3"]
- # ["4", "5", "&nbsp;"]
- # ["6", "7", "&nbsp;"]
- #
- # %w(1 2 3 4 5 6 7).in_groups(3, false) {|group| p group}
- # ["1", "2", "3"]
- # ["4", "5"]
- # ["6", "7"]
- def in_groups(number, fill_with = nil)
- # size / number gives minor group size;
- # size % number gives how many objects need extra accomodation;
- # each group hold either division or division + 1 items.
- division = size / number
- modulo = size % number
+ if block_given?
+ collection.each_slice(number) { |slice| yield(slice) }
+ else
+ groups = []
+ collection.each_slice(number) { |group| groups << group }
+ groups
+ end
+ end
- # create a new array avoiding dup
- groups = []
- start = 0
+ # Splits or iterates over the array in +number+ of groups, padding any
+ # remaining slots with +fill_with+ unless it is +false+.
+ #
+ # %w(1 2 3 4 5 6 7 8 9 10).in_groups(3) {|group| p group}
+ # ["1", "2", "3", "4"]
+ # ["5", "6", "7", nil]
+ # ["8", "9", "10", nil]
+ #
+ # %w(1 2 3 4 5 6 7).in_groups(3, '&nbsp;') {|group| p group}
+ # ["1", "2", "3"]
+ # ["4", "5", "&nbsp;"]
+ # ["6", "7", "&nbsp;"]
+ #
+ # %w(1 2 3 4 5 6 7).in_groups(3, false) {|group| p group}
+ # ["1", "2", "3"]
+ # ["4", "5"]
+ # ["6", "7"]
+ def in_groups(number, fill_with = nil)
+ # size / number gives minor group size;
+ # size % number gives how many objects need extra accomodation;
+ # each group hold either division or division + 1 items.
+ division = size / number
+ modulo = size % number
- number.times do |index|
- length = division + (modulo > 0 && modulo > index ? 1 : 0)
- padding = fill_with != false &&
- modulo > 0 && length == division ? 1 : 0
- groups << slice(start, length).concat([fill_with] * padding)
- start += length
- end
+ # create a new array avoiding dup
+ groups = []
+ start = 0
- if block_given?
- groups.each{|g| yield(g) }
- else
- groups
- end
- end
+ number.times do |index|
+ length = division + (modulo > 0 && modulo > index ? 1 : 0)
+ padding = fill_with != false &&
+ modulo > 0 && length == division ? 1 : 0
+ groups << slice(start, length).concat([fill_with] * padding)
+ start += length
+ end
- # Divides the array into one or more subarrays based on a delimiting +value+
- # or the result of an optional block.
- #
- # [1, 2, 3, 4, 5].split(3) # => [[1, 2], [4, 5]]
- # (1..10).to_a.split { |i| i % 3 == 0 } # => [[1, 2], [4, 5], [7, 8], [10]]
- def split(value = nil)
- using_block = block_given?
+ if block_given?
+ groups.each { |g| yield(g) }
+ else
+ groups
+ end
+ end
- inject([[]]) do |results, element|
- if (using_block && yield(element)) || (value == element)
- results << []
- else
- results.last << element
- end
+ # Divides the array into one or more subarrays based on a delimiting +value+
+ # or the result of an optional block.
+ #
+ # [1, 2, 3, 4, 5].split(3) # => [[1, 2], [4, 5]]
+ # (1..10).to_a.split { |i| i % 3 == 0 } # => [[1, 2], [4, 5], [7, 8], [10]]
+ def split(value = nil)
+ using_block = block_given?
- results
- end
- end
+ inject([[]]) do |results, element|
+ if (using_block && yield(element)) || (value == element)
+ results << []
+ else
+ results.last << element
end
+
+ results
end
end
end
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 54d17cbf30..343003f6f7 100644
--- a/activesupport/lib/active_support/core_ext/array/random_access.rb
+++ b/activesupport/lib/active_support/core_ext/array/random_access.rb
@@ -1,12 +1,6 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Array #:nodoc:
- module RandomAccess
- # Returns a random element from the array.
- def rand
- self[Kernel.rand(length)]
- end
- end
- end
+class Array
+ # Returns a random element from the array.
+ def rand
+ self[Kernel.rand(length)]
end
end
diff --git a/activesupport/lib/active_support/core_ext/array/wrap.rb b/activesupport/lib/active_support/core_ext/array/wrap.rb
new file mode 100644
index 0000000000..9d45c2739b
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/array/wrap.rb
@@ -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
diff --git a/activesupport/lib/active_support/core_ext/array/wrapper.rb b/activesupport/lib/active_support/core_ext/array/wrapper.rb
deleted file mode 100644
index 80b8f05531..0000000000
--- a/activesupport/lib/active_support/core_ext/array/wrapper.rb
+++ /dev/null
@@ -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
diff --git a/activesupport/lib/active_support/core_ext/base64.rb b/activesupport/lib/active_support/core_ext/base64.rb
deleted file mode 100644
index 235e2edf57..0000000000
--- a/activesupport/lib/active_support/core_ext/base64.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'active_support/base64'
-require 'active_support/core_ext/base64/encoding'
-
-ActiveSupport::Base64.extend ActiveSupport::CoreExtensions::Base64::Encoding
diff --git a/activesupport/lib/active_support/core_ext/base64/encoding.rb b/activesupport/lib/active_support/core_ext/base64/encoding.rb
deleted file mode 100644
index a9656c138e..0000000000
--- a/activesupport/lib/active_support/core_ext/base64/encoding.rb
+++ /dev/null
@@ -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
diff --git a/activesupport/lib/active_support/core_ext/big_decimal.rb b/activesupport/lib/active_support/core_ext/big_decimal.rb
new file mode 100644
index 0000000000..8143113cfa
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/big_decimal.rb
@@ -0,0 +1 @@
+require 'active_support/core_ext/big_decimal/conversions'
diff --git a/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb b/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb
new file mode 100644
index 0000000000..f7f03f4d95
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb
@@ -0,0 +1,27 @@
+require 'bigdecimal'
+require 'yaml'
+
+class BigDecimal
+ YAML_TAG = 'tag:yaml.org,2002:float'
+ YAML_MAPPING = { 'Infinity' => '.Inf', '-Infinity' => '-.Inf', 'NaN' => '.NaN' }
+
+ yaml_as YAML_TAG
+
+ # This emits the number without any scientific notation.
+ # This is better than self.to_f.to_s since it doesn't lose precision.
+ #
+ # Note that reconstituting YAML floats to native floats may lose precision.
+ def to_yaml(opts = {})
+ YAML.quick_emit(nil, opts) do |out|
+ string = to_s
+ out.scalar(YAML_TAG, YAML_MAPPING[string] || string, :plain)
+ end
+ end
+
+ DEFAULT_STRING_FORMAT = 'F'
+ def to_formatted_s(format = DEFAULT_STRING_FORMAT)
+ _original_to_s(format)
+ end
+ alias_method :_original_to_s, :to_s
+ alias_method :to_s, :to_formatted_s
+end
diff --git a/activesupport/lib/active_support/core_ext/bigdecimal.rb b/activesupport/lib/active_support/core_ext/bigdecimal.rb
deleted file mode 100644
index d429078c91..0000000000
--- a/activesupport/lib/active_support/core_ext/bigdecimal.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-require 'bigdecimal'
-require 'active_support/core_ext/bigdecimal/conversions'
-
-class BigDecimal#:nodoc:
- include ActiveSupport::CoreExtensions::BigDecimal::Conversions
-end
diff --git a/activesupport/lib/active_support/core_ext/bigdecimal/conversions.rb b/activesupport/lib/active_support/core_ext/bigdecimal/conversions.rb
deleted file mode 100644
index bc9d578f38..0000000000
--- a/activesupport/lib/active_support/core_ext/bigdecimal/conversions.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-require 'yaml'
-
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module BigDecimal #:nodoc:
- module Conversions
- DEFAULT_STRING_FORMAT = 'F'.freeze
- YAML_TAG = 'tag:yaml.org,2002:float'.freeze
- YAML_MAPPING = { 'Infinity' => '.Inf', '-Infinity' => '-.Inf', 'NaN' => '.NaN' }
-
- def self.included(base) #:nodoc:
- base.class_eval do
- alias_method :_original_to_s, :to_s
- alias_method :to_s, :to_formatted_s
-
- yaml_as YAML_TAG
- end
- end
-
- def to_formatted_s(format = DEFAULT_STRING_FORMAT)
- _original_to_s(format)
- end
-
- # This emits the number without any scientific notation.
- # This is better than self.to_f.to_s since it doesn't lose precision.
- #
- # Note that reconstituting YAML floats to native floats may lose precision.
- def to_yaml(opts = {})
- YAML.quick_emit(nil, opts) do |out|
- string = to_s
- out.scalar(YAML_TAG, YAML_MAPPING[string] || string, :plain)
- end
- end
- end
- end
- end
-end
diff --git a/activesupport/lib/active_support/core_ext/cgi.rb b/activesupport/lib/active_support/core_ext/cgi.rb
index db90e5c745..7279a3d4da 100644
--- a/activesupport/lib/active_support/core_ext/cgi.rb
+++ b/activesupport/lib/active_support/core_ext/cgi.rb
@@ -1,5 +1 @@
require 'active_support/core_ext/cgi/escape_skipping_slashes'
-
-class CGI #:nodoc:
- extend ActiveSupport::CoreExtensions::CGI::EscapeSkippingSlashes
-end
diff --git a/activesupport/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb b/activesupport/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb
index 1edb3771a2..1c3ef05526 100644
--- a/activesupport/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb
+++ b/activesupport/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb
@@ -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
diff --git a/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb b/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb
index d893818695..da798c67e7 100644
--- a/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb
+++ b/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb
@@ -1,31 +1,25 @@
-# These class attributes behave something like the class
-# inheritable accessors. But instead of copying the hash over at
-# the time the subclass is first defined, the accessors simply
-# delegate to their superclass unless they have been given a
-# specific value. This stops the strange situation where values
-# set after class definition don't get applied to subclasses.
class Class
def superclass_delegating_reader(*names)
- class_name_to_stop_searching_on = self.superclass.name.blank? ? "Object" : self.superclass.name
+ class_name_to_stop_searching_on = superclass.name.blank? ? "Object" : superclass.name
names.each do |name|
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
- def self.#{name} # def self.only_reader
- if defined?(@#{name}) # if defined?(@only_reader)
- @#{name} # @only_reader
- elsif superclass < #{class_name_to_stop_searching_on} && # elsif superclass < Object &&
- superclass.respond_to?(:#{name}) # superclass.respond_to?(:only_reader)
- superclass.#{name} # superclass.only_reader
- end # end
- end # end
- def #{name} # def only_reader
- self.class.#{name} # self.class.only_reader
- end # end
- def self.#{name}? # def self.only_reader?
- !!#{name} # !!only_reader
- end # end
- def #{name}? # def only_reader?
- !!#{name} # !!only_reader
- end # end
+ def self.#{name} # def self.only_reader
+ if defined?(@#{name}) # if defined?(@only_reader)
+ @#{name} # @only_reader
+ elsif superclass < #{class_name_to_stop_searching_on} && # elsif superclass < Object &&
+ superclass.respond_to?(:#{name}) # superclass.respond_to?(:only_reader)
+ superclass.#{name} # superclass.only_reader
+ end # end
+ end # end
+ def #{name} # def only_reader
+ self.class.#{name} # self.class.only_reader
+ end # end
+ def self.#{name}? # def self.only_reader?
+ !!#{name} # !!only_reader
+ end # end
+ def #{name}? # def only_reader?
+ !!#{name} # !!only_reader
+ end # end
EOS
end
end
@@ -40,6 +34,12 @@ class Class
end
end
+ # These class attributes behave something like the class
+ # inheritable accessors. But instead of copying the hash over at
+ # the time the subclass is first defined, the accessors simply
+ # delegate to their superclass unless they have been given a
+ # specific value. This stops the strange situation where values
+ # set after class definition don't get applied to subclasses.
def superclass_delegating_accessor(*names)
superclass_delegating_reader(*names)
superclass_delegating_writer(*names)
diff --git a/activesupport/lib/active_support/core_ext/date.rb b/activesupport/lib/active_support/core_ext/date.rb
index 3f56c560b6..6672129076 100644
--- a/activesupport/lib/active_support/core_ext/date.rb
+++ b/activesupport/lib/active_support/core_ext/date.rb
@@ -1,10 +1,7 @@
require 'date'
-require 'active_support/core_ext/date/behavior'
+
+require 'active_support/core_ext/date/acts_like'
+require 'active_support/core_ext/date/freeze'
+
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
diff --git a/activesupport/lib/active_support/core_ext/date/acts_like.rb b/activesupport/lib/active_support/core_ext/date/acts_like.rb
new file mode 100644
index 0000000000..cd90cee236
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/date/acts_like.rb
@@ -0,0 +1,8 @@
+require 'active_support/core_ext/object/acts_like'
+
+class Date
+ # Duck-types as a Date-like class. See Object#acts_like?.
+ def acts_like_date?
+ true
+ end
+end
diff --git a/activesupport/lib/active_support/core_ext/date/behavior.rb b/activesupport/lib/active_support/core_ext/date/behavior.rb
deleted file mode 100644
index bd378eb375..0000000000
--- a/activesupport/lib/active_support/core_ext/date/behavior.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-require 'date'
-
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Date #:nodoc:
- module Behavior
- # Enable more predictable duck-typing on Date-like classes. See
- # Object#acts_like?.
- def acts_like_date?
- true
- end
-
- # Date memoizes some instance methods using metaprogramming to wrap
- # the methods with one that caches the result in an instance variable.
- #
- # If a Date is frozen but the memoized method hasn't been called, the
- # first call will result in a frozen object error since the memo
- # instance variable is uninitialized.
- #
- # Work around by eagerly memoizing before freezing.
- #
- # Ruby 1.9 uses a preinitialized instance variable so it's unaffected.
- # This hack is as close as we can get to feature detection:
- begin
- ::Date.today.freeze.jd
- rescue => frozen_object_error
- if frozen_object_error.message =~ /frozen/
- def freeze #:nodoc:
- self.class.private_instance_methods(false).each do |m|
- if m.to_s =~ /\A__\d+__\Z/
- instance_variable_set(:"@#{m}", [send(m)])
- end
- end
-
- super
- end
- end
- end
- end
- end
- end
-end
diff --git a/activesupport/lib/active_support/core_ext/date/calculations.rb b/activesupport/lib/active_support/core_ext/date/calculations.rb
index 7f94da015b..59efdbd1b6 100644
--- a/activesupport/lib/active_support/core_ext/date/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/date/calculations.rb
@@ -1,230 +1,215 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Date #:nodoc:
- # Enables the use of time calculations within Date itself
- module Calculations
- def self.included(base) #:nodoc:
- base.extend ClassMethods
-
- base.instance_eval do
- alias_method :plus_without_duration, :+
- alias_method :+, :plus_with_duration
-
- alias_method :minus_without_duration, :-
- alias_method :-, :minus_with_duration
- end
- end
-
- module ClassMethods
- # Returns a new Date representing the date 1 day ago (i.e. yesterday's date).
- def yesterday
- ::Date.today.yesterday
- end
-
- # Returns a new Date representing the date 1 day after today (i.e. tomorrow's date).
- def tomorrow
- ::Date.today.tomorrow
- end
-
- # Returns Time.zone.today when config.time_zone is set, otherwise just returns Date.today.
- def current
- ::Time.zone_default ? ::Time.zone.today : ::Date.today
- end
- end
-
- # Tells whether the Date object's date lies in the past
- def past?
- self < ::Date.current
- end
-
- # Tells whether the Date object's date is today
- def today?
- self.to_date == ::Date.current # we need the to_date because of DateTime
- end
-
- # Tells whether the Date object's date lies in the future
- def future?
- self > ::Date.current
- end
-
- # Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00)
- # and then subtracts the specified number of seconds
- def ago(seconds)
- to_time.since(-seconds)
- end
-
- # Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00)
- # and then adds the specified number of seconds
- def since(seconds)
- to_time.since(seconds)
- end
- alias :in :since
-
- # Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00)
- def beginning_of_day
- to_time
- end
- alias :midnight :beginning_of_day
- alias :at_midnight :beginning_of_day
- alias :at_beginning_of_day :beginning_of_day
-
- # Converts Date to a Time (or DateTime if necessary) with the time portion set to the end of the day (23:59:59)
- def end_of_day
- to_time.end_of_day
- end
-
- def plus_with_duration(other) #:nodoc:
- if ActiveSupport::Duration === other
- other.since(self)
- else
- plus_without_duration(other)
- end
- end
-
- def minus_with_duration(other) #:nodoc:
- if ActiveSupport::Duration === other
- plus_with_duration(-other)
- else
- minus_without_duration(other)
- end
- end
-
- # Provides precise Date calculations for years, months, and days. The +options+ parameter takes a hash with
- # any of these keys: <tt>:years</tt>, <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>.
- def advance(options)
- d = self
- d = d >> options.delete(:years) * 12 if options[:years]
- d = d >> options.delete(:months) if options[:months]
- d = d + options.delete(:weeks) * 7 if options[:weeks]
- d = d + options.delete(:days) if options[:days]
- d
- end
-
- # Returns a new Date where one or more of the elements have been changed according to the +options+ parameter.
- #
- # Examples:
- #
- # Date.new(2007, 5, 12).change(:day => 1) # => Date.new(2007, 5, 1)
- # Date.new(2007, 5, 12).change(:year => 2005, :month => 1) # => Date.new(2005, 1, 12)
- def change(options)
- ::Date.new(
- options[:year] || self.year,
- options[:month] || self.month,
- options[:day] || self.day
- )
- end
-
- # Returns a new Date/DateTime representing the time a number of specified months ago
- def months_ago(months)
- advance(:months => -months)
- end
-
- # Returns a new Date/DateTime representing the time a number of specified months in the future
- def months_since(months)
- advance(:months => months)
- end
-
- # Returns a new Date/DateTime representing the time a number of specified years ago
- def years_ago(years)
- advance(:years => -years)
- end
-
- # Returns a new Date/DateTime representing the time a number of specified years in the future
- def years_since(years)
- advance(:years => years)
- end
-
- # Short-hand for years_ago(1)
- def last_year
- years_ago(1)
- end
-
- # Short-hand for years_since(1)
- def next_year
- years_since(1)
- end
-
- # Short-hand for months_ago(1)
- def last_month
- months_ago(1)
- end
-
- # Short-hand for months_since(1)
- def next_month
- months_since(1)
- end
-
- # Returns a new Date/DateTime representing the "start" of this week (i.e, Monday; DateTime objects will have time set to 0:00)
- def beginning_of_week
- days_to_monday = self.wday!=0 ? self.wday-1 : 6
- result = self - days_to_monday
- self.acts_like?(:time) ? result.midnight : result
- end
- alias :monday :beginning_of_week
- alias :at_beginning_of_week :beginning_of_week
-
- # Returns a new Date/DateTime representing the end of this week (Sunday, DateTime objects will have time set to 23:59:59)
- def end_of_week
- days_to_sunday = self.wday!=0 ? 7-self.wday : 0
- result = self + days_to_sunday.days
- self.acts_like?(:time) ? result.end_of_day : result
- end
- alias :at_end_of_week :end_of_week
-
- # Returns a new Date/DateTime representing the start of the given day in next week (default is Monday).
- def next_week(day = :monday)
- days_into_week = { :monday => 0, :tuesday => 1, :wednesday => 2, :thursday => 3, :friday => 4, :saturday => 5, :sunday => 6}
- result = (self + 7).beginning_of_week + days_into_week[day]
- self.acts_like?(:time) ? result.change(:hour => 0) : result
- end
-
- # 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)
- end
- alias :at_beginning_of_month :beginning_of_month
-
- # Returns a new Date/DateTime representing the end of the month (last day of the month; DateTime objects will have time set to 0:00)
- def end_of_month
- last_day = ::Time.days_in_month( self.month, self.year )
- self.acts_like?(:time) ? change(:day => last_day, :hour => 23, :min => 59, :sec => 59) : change(:day => last_day)
- end
- alias :at_end_of_month :end_of_month
-
- # Returns a new Date/DateTime representing the start of the quarter (1st of january, april, july, october; DateTime objects will have time set to 0:00)
- def beginning_of_quarter
- beginning_of_month.change(:month => [10, 7, 4, 1].detect { |m| m <= self.month })
- end
- alias :at_beginning_of_quarter :beginning_of_quarter
-
- # Returns a new Date/DateTime representing the end of the quarter (last day of march, june, september, december; DateTime objects will have time set to 23:59:59)
- def end_of_quarter
- beginning_of_month.change(:month => [3, 6, 9, 12].detect { |m| m >= self.month }).end_of_month
- end
- alias :at_end_of_quarter :end_of_quarter
-
- # 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)
- 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)
- end
- alias :at_end_of_year :end_of_year
-
- # Convenience method which returns a new Date/DateTime representing the time 1 day ago
- def yesterday
- self - 1
- end
-
- # Convenience method which returns a new Date/DateTime representing the time 1 day since the instance time
- def tomorrow
- self + 1
- end
- end
+class Date
+ class << self
+ # Returns a new Date representing the date 1 day ago (i.e. yesterday's date).
+ def yesterday
+ ::Date.today.yesterday
end
+
+ # Returns a new Date representing the date 1 day after today (i.e. tomorrow's date).
+ def tomorrow
+ ::Date.today.tomorrow
+ end
+
+ # Returns Time.zone.today when config.time_zone is set, otherwise just returns Date.today.
+ def current
+ ::Time.zone_default ? ::Time.zone.today : ::Date.today
+ end
+ end
+
+ # Tells whether the Date object's date lies in the past
+ def past?
+ self < ::Date.current
+ end
+
+ # Tells whether the Date object's date is today
+ def today?
+ self.to_date == ::Date.current # we need the to_date because of DateTime
+ end
+
+ # Tells whether the Date object's date lies in the future
+ def future?
+ self > ::Date.current
+ end
+
+ # Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00)
+ # and then subtracts the specified number of seconds
+ def ago(seconds)
+ to_time.since(-seconds)
+ end
+
+ # Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00)
+ # and then adds the specified number of seconds
+ def since(seconds)
+ to_time.since(seconds)
+ end
+ alias :in :since
+
+ # Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00)
+ def beginning_of_day
+ to_time
+ end
+ alias :midnight :beginning_of_day
+ alias :at_midnight :beginning_of_day
+ alias :at_beginning_of_day :beginning_of_day
+
+ # Converts Date to a Time (or DateTime if necessary) with the time portion set to the end of the day (23:59:59)
+ def end_of_day
+ to_time.end_of_day
+ end
+
+ def plus_with_duration(other) #:nodoc:
+ if ActiveSupport::Duration === other
+ other.since(self)
+ else
+ plus_without_duration(other)
+ end
+ end
+ alias_method :plus_without_duration, :+
+ alias_method :+, :plus_with_duration
+
+ def minus_with_duration(other) #:nodoc:
+ if ActiveSupport::Duration === other
+ plus_with_duration(-other)
+ else
+ minus_without_duration(other)
+ end
+ end
+ alias_method :minus_without_duration, :-
+ alias_method :-, :minus_with_duration
+
+ # Provides precise Date calculations for years, months, and days. The +options+ parameter takes a hash with
+ # any of these keys: <tt>:years</tt>, <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>.
+ def advance(options)
+ d = self
+ d = d >> options.delete(:years) * 12 if options[:years]
+ d = d >> options.delete(:months) if options[:months]
+ d = d + options.delete(:weeks) * 7 if options[:weeks]
+ d = d + options.delete(:days) if options[:days]
+ d
+ end
+
+ # Returns a new Date where one or more of the elements have been changed according to the +options+ parameter.
+ #
+ # Examples:
+ #
+ # Date.new(2007, 5, 12).change(:day => 1) # => Date.new(2007, 5, 1)
+ # Date.new(2007, 5, 12).change(:year => 2005, :month => 1) # => Date.new(2005, 1, 12)
+ def change(options)
+ ::Date.new(
+ options[:year] || self.year,
+ options[:month] || self.month,
+ options[:day] || self.day
+ )
+ end
+
+ # Returns a new Date/DateTime representing the time a number of specified months ago
+ def months_ago(months)
+ advance(:months => -months)
+ end
+
+ # Returns a new Date/DateTime representing the time a number of specified months in the future
+ def months_since(months)
+ advance(:months => months)
+ end
+
+ # Returns a new Date/DateTime representing the time a number of specified years ago
+ def years_ago(years)
+ advance(:years => -years)
+ end
+
+ # Returns a new Date/DateTime representing the time a number of specified years in the future
+ def years_since(years)
+ advance(:years => years)
+ end
+
+ # Short-hand for years_ago(1)
+ def last_year
+ years_ago(1)
+ end
+
+ # Short-hand for years_since(1)
+ def next_year
+ years_since(1)
+ end
+
+ # Short-hand for months_ago(1)
+ def last_month
+ months_ago(1)
+ end
+
+ # Short-hand for months_since(1)
+ def next_month
+ months_since(1)
+ end
+
+ # Returns a new Date/DateTime representing the "start" of this week (i.e, Monday; DateTime objects will have time set to 0:00)
+ def beginning_of_week
+ days_to_monday = self.wday!=0 ? self.wday-1 : 6
+ result = self - days_to_monday
+ self.acts_like?(:time) ? result.midnight : result
+ end
+ alias :monday :beginning_of_week
+ alias :at_beginning_of_week :beginning_of_week
+
+ # Returns a new Date/DateTime representing the end of this week (Sunday, DateTime objects will have time set to 23:59:59)
+ def end_of_week
+ days_to_sunday = self.wday!=0 ? 7-self.wday : 0
+ result = self + days_to_sunday.days
+ self.acts_like?(:time) ? result.end_of_day : result
+ end
+ alias :at_end_of_week :end_of_week
+
+ # Returns a new Date/DateTime representing the start of the given day in next week (default is Monday).
+ def next_week(day = :monday)
+ days_into_week = { :monday => 0, :tuesday => 1, :wednesday => 2, :thursday => 3, :friday => 4, :saturday => 5, :sunday => 6}
+ result = (self + 7).beginning_of_week + days_into_week[day]
+ self.acts_like?(:time) ? result.change(:hour => 0) : result
+ end
+
+ # 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)
+ end
+ alias :at_beginning_of_month :beginning_of_month
+
+ # Returns a new Date/DateTime representing the end of the month (last day of the month; DateTime objects will have time set to 0:00)
+ def end_of_month
+ last_day = ::Time.days_in_month( self.month, self.year )
+ self.acts_like?(:time) ? change(:day => last_day, :hour => 23, :min => 59, :sec => 59) : change(:day => last_day)
+ end
+ alias :at_end_of_month :end_of_month
+
+ # Returns a new Date/DateTime representing the start of the quarter (1st of january, april, july, october; DateTime objects will have time set to 0:00)
+ def beginning_of_quarter
+ beginning_of_month.change(:month => [10, 7, 4, 1].detect { |m| m <= self.month })
+ end
+ alias :at_beginning_of_quarter :beginning_of_quarter
+
+ # Returns a new Date/DateTime representing the end of the quarter (last day of march, june, september, december; DateTime objects will have time set to 23:59:59)
+ def end_of_quarter
+ beginning_of_month.change(:month => [3, 6, 9, 12].detect { |m| m >= self.month }).end_of_month
+ end
+ alias :at_end_of_quarter :end_of_quarter
+
+ # 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)
+ 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)
+ end
+ alias :at_end_of_year :end_of_year
+
+ # Convenience method which returns a new Date/DateTime representing the time 1 day ago
+ def yesterday
+ self - 1
+ end
+
+ # Convenience method which returns a new Date/DateTime representing the time 1 day since the instance time
+ def tomorrow
+ self + 1
end
end
diff --git a/activesupport/lib/active_support/core_ext/date/conversions.rb b/activesupport/lib/active_support/core_ext/date/conversions.rb
index 8d9f023361..f6c870035b 100644
--- a/activesupport/lib/active_support/core_ext/date/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/date/conversions.rb
@@ -1,107 +1,97 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Date #:nodoc:
- # Converting dates to formatted strings, times, and datetimes.
- module Conversions
- DATE_FORMATS = {
- :short => "%e %b",
- :long => "%B %e, %Y",
- :db => "%Y-%m-%d",
- :number => "%Y%m%d",
- :long_ordinal => lambda { |date| date.strftime("%B #{date.day.ordinalize}, %Y") }, # => "April 25th, 2007"
- :rfc822 => "%e %b %Y"
- }
+require 'active_support/inflector'
- def self.included(base) #:nodoc:
- base.instance_eval do
- alias_method :to_default_s, :to_s
- alias_method :to_s, :to_formatted_s
- alias_method :default_inspect, :inspect
- alias_method :inspect, :readable_inspect
+class Date
+ DATE_FORMATS = {
+ :short => "%e %b",
+ :long => "%B %e, %Y",
+ :db => "%Y-%m-%d",
+ :number => "%Y%m%d",
+ :long_ordinal => lambda { |date| date.strftime("%B #{ActiveSupport::Inflector.ordinalize(date.day)}, %Y") }, # => "April 25th, 2007"
+ :rfc822 => "%e %b %Y"
+ }
- # Ruby 1.9 has Date#to_time which converts to localtime only.
- remove_method :to_time if base.instance_methods.include?(:to_time)
+ # Ruby 1.9 has Date#to_time which converts to localtime only.
+ remove_method :to_time if instance_methods.include?(:to_time)
- # Ruby 1.9 has Date#xmlschema which converts to a string without the time component.
- remove_method :xmlschema if base.instance_methods.include?(:xmlschema)
- end
- end
+ # Ruby 1.9 has Date#xmlschema which converts to a string without the time component.
+ remove_method :xmlschema if instance_methods.include?(:xmlschema)
- # Convert to a formatted string. See DATE_FORMATS for predefined formats.
- #
- # This method is aliased to <tt>to_s</tt>.
- #
- # ==== Examples
- # date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
- #
- # date.to_formatted_s(:db) # => "2007-11-10"
- # date.to_s(:db) # => "2007-11-10"
- #
- # date.to_formatted_s(:short) # => "10 Nov"
- # date.to_formatted_s(:long) # => "November 10, 2007"
- # date.to_formatted_s(:long_ordinal) # => "November 10th, 2007"
- # date.to_formatted_s(:rfc822) # => "10 Nov 2007"
- #
- # == Adding your own time formats to to_formatted_s
- # You can add your own formats to the Date::DATE_FORMATS hash.
- # Use the format name as the hash key and either a strftime string
- # or Proc instance that takes a date argument as the value.
- #
- # # config/initializers/time_formats.rb
- # Date::DATE_FORMATS[:month_and_year] = "%B %Y"
- # Date::DATE_FORMATS[:short_ordinal] = lambda { |date| date.strftime("%B #{date.day.ordinalize}") }
- def to_formatted_s(format = :default)
- if formatter = DATE_FORMATS[format]
- if formatter.respond_to?(:call)
- formatter.call(self).to_s
- else
- strftime(formatter)
- end
- else
- to_default_s
- end
- end
+ # Convert to a formatted string. See DATE_FORMATS for predefined formats.
+ #
+ # This method is aliased to <tt>to_s</tt>.
+ #
+ # ==== Examples
+ # date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
+ #
+ # date.to_formatted_s(:db) # => "2007-11-10"
+ # date.to_s(:db) # => "2007-11-10"
+ #
+ # date.to_formatted_s(:short) # => "10 Nov"
+ # date.to_formatted_s(:long) # => "November 10, 2007"
+ # date.to_formatted_s(:long_ordinal) # => "November 10th, 2007"
+ # date.to_formatted_s(:rfc822) # => "10 Nov 2007"
+ #
+ # == Adding your own time formats to to_formatted_s
+ # You can add your own formats to the Date::DATE_FORMATS hash.
+ # Use the format name as the hash key and either a strftime string
+ # or Proc instance that takes a date argument as the value.
+ #
+ # # config/initializers/time_formats.rb
+ # Date::DATE_FORMATS[:month_and_year] = "%B %Y"
+ # Date::DATE_FORMATS[:short_ordinal] = lambda { |date| date.strftime("%B #{date.day.ordinalize}") }
+ def to_formatted_s(format = :default)
+ if formatter = DATE_FORMATS[format]
+ if formatter.respond_to?(:call)
+ formatter.call(self).to_s
+ else
+ strftime(formatter)
+ end
+ else
+ to_default_s
+ end
+ end
+ alias_method :to_default_s, :to_s
+ alias_method :to_s, :to_formatted_s
- # Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005"
- def readable_inspect
- strftime("%a, %d %b %Y")
- end
+ # Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005"
+ def readable_inspect
+ strftime("%a, %d %b %Y")
+ end
+ alias_method :default_inspect, :inspect
+ alias_method :inspect, :readable_inspect
- # A method to keep Time, Date and DateTime instances interchangeable on conversions.
- # In this case, it simply returns +self+.
- def to_date
- self
- end if RUBY_VERSION < '1.9'
+ # A method to keep Time, Date and DateTime instances interchangeable on conversions.
+ # In this case, it simply returns +self+.
+ def to_date
+ self
+ end if RUBY_VERSION < '1.9'
- # Converts a Date instance to a Time, where the time is set to the beginning of the day.
- # The timezone can be either :local or :utc (default :local).
- #
- # ==== Examples
- # date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
- #
- # date.to_time # => Sat Nov 10 00:00:00 0800 2007
- # date.to_time(:local) # => Sat Nov 10 00:00:00 0800 2007
- #
- # date.to_time(:utc) # => Sat Nov 10 00:00:00 UTC 2007
- def to_time(form = :local)
- ::Time.send("#{form}_time", year, month, day)
- end
+ # Converts a Date instance to a Time, where the time is set to the beginning of the day.
+ # The timezone can be either :local or :utc (default :local).
+ #
+ # ==== Examples
+ # date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
+ #
+ # date.to_time # => Sat Nov 10 00:00:00 0800 2007
+ # date.to_time(:local) # => Sat Nov 10 00:00:00 0800 2007
+ #
+ # date.to_time(:utc) # => Sat Nov 10 00:00:00 UTC 2007
+ def to_time(form = :local)
+ ::Time.send("#{form}_time", year, month, day)
+ end
- # Converts a Date instance to a DateTime, where the time is set to the beginning of the day
- # and UTC offset is set to 0.
- #
- # ==== Examples
- # date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
- #
- # date.to_datetime # => Sat, 10 Nov 2007 00:00:00 0000
- def to_datetime
- ::DateTime.civil(year, month, day, 0, 0, 0, 0)
- end if RUBY_VERSION < '1.9'
+ # Converts a Date instance to a DateTime, where the time is set to the beginning of the day
+ # and UTC offset is set to 0.
+ #
+ # ==== Examples
+ # date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
+ #
+ # date.to_datetime # => Sat, 10 Nov 2007 00:00:00 0000
+ def to_datetime
+ ::DateTime.civil(year, month, day, 0, 0, 0, 0)
+ end if RUBY_VERSION < '1.9'
- def xmlschema
- to_time.xmlschema
- end
- end
- end
+ def xmlschema
+ to_time.xmlschema
end
end
diff --git a/activesupport/lib/active_support/core_ext/date/freeze.rb b/activesupport/lib/active_support/core_ext/date/freeze.rb
new file mode 100644
index 0000000000..4edd715ba2
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/date/freeze.rb
@@ -0,0 +1,31 @@
+# Date memoizes some instance methods using metaprogramming to wrap
+# the methods with one that caches the result in an instance variable.
+#
+# If a Date is frozen but the memoized method hasn't been called, the
+# first call will result in a frozen object error since the memo
+# instance variable is uninitialized.
+#
+# Work around by eagerly memoizing before freezing.
+#
+# Ruby 1.9 uses a preinitialized instance variable so it's unaffected.
+# This hack is as close as we can get to feature detection:
+if RUBY_VERSION < '1.9'
+ require 'date'
+ begin
+ ::Date.today.freeze.jd
+ rescue => frozen_object_error
+ if frozen_object_error.message =~ /frozen/
+ class Date #:nodoc:
+ def freeze
+ self.class.private_instance_methods(false).each do |m|
+ if m.to_s =~ /\A__\d+__\Z/
+ instance_variable_set(:"@#{m}", [send(m)])
+ end
+ end
+
+ super
+ end
+ end
+ end
+ end
+end
diff --git a/activesupport/lib/active_support/core_ext/date_time.rb b/activesupport/lib/active_support/core_ext/date_time.rb
index 66a93eac43..83a11da1c7 100644
--- a/activesupport/lib/active_support/core_ext/date_time.rb
+++ b/activesupport/lib/active_support/core_ext/date_time.rb
@@ -1,12 +1,6 @@
require 'date'
-require 'active_support/core_ext/time/behavior'
-require 'active_support/core_ext/time/zones'
+
+require 'active_support/core_ext/date_time/acts_like'
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
+require 'active_support/core_ext/date_time/zones'
diff --git a/activesupport/lib/active_support/core_ext/date_time/acts_like.rb b/activesupport/lib/active_support/core_ext/date_time/acts_like.rb
new file mode 100644
index 0000000000..c79745c5aa
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/date_time/acts_like.rb
@@ -0,0 +1,13 @@
+require 'active_support/core_ext/object/acts_like'
+
+class DateTime
+ # Duck-types as a Date-like class. See Object#acts_like?.
+ def acts_like_date?
+ true
+ end
+
+ # Duck-types as a Time-like class. See Object#acts_like?.
+ def acts_like_time?
+ true
+ end
+end
diff --git a/activesupport/lib/active_support/core_ext/date_time/calculations.rb b/activesupport/lib/active_support/core_ext/date_time/calculations.rb
index 0099431e9d..41cf020f94 100644
--- a/activesupport/lib/active_support/core_ext/date_time/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/date_time/calculations.rb
@@ -1,126 +1,112 @@
require 'rational'
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module DateTime #:nodoc:
- # Enables the use of time calculations within DateTime itself
- module Calculations
- def self.included(base) #:nodoc:
- base.extend ClassMethods
-
- base.class_eval do
- alias_method :compare_without_coercion, :<=>
- alias_method :<=>, :compare_with_coercion
- end
- end
-
- module ClassMethods
- # DateTimes aren't aware of DST rules, so use a consistent non-DST offset when creating a DateTime with an offset in the local zone
- def local_offset
- ::Time.local(2007).utc_offset.to_r / 86400
- end
+class DateTime
+ class << self
+ # DateTimes aren't aware of DST rules, so use a consistent non-DST offset when creating a DateTime with an offset in the local zone
+ def local_offset
+ ::Time.local(2007).utc_offset.to_r / 86400
+ end
- def current
- ::Time.zone_default ? ::Time.zone.now.to_datetime : ::Time.now.to_datetime
- end
- end
+ def current
+ ::Time.zone_default ? ::Time.zone.now.to_datetime : ::Time.now.to_datetime
+ end
+ end
- # Tells whether the DateTime object's datetime lies in the past
- def past?
- self < ::DateTime.current
- end
+ # Tells whether the DateTime object's datetime lies in the past
+ def past?
+ self < ::DateTime.current
+ end
- # Tells whether the DateTime object's datetime lies in the future
- def future?
- self > ::DateTime.current
- end
+ # Tells whether the DateTime object's datetime lies in the future
+ def future?
+ self > ::DateTime.current
+ end
- # Seconds since midnight: DateTime.now.seconds_since_midnight
- def seconds_since_midnight
- self.sec + (self.min * 60) + (self.hour * 3600)
- end
+ # Seconds since midnight: DateTime.now.seconds_since_midnight
+ def seconds_since_midnight
+ sec + (min * 60) + (hour * 3600)
+ end
- # Returns a new DateTime where one or more of the elements have been changed according to the +options+ parameter. The time options
- # (hour, minute, sec) reset cascadingly, so if only the hour is passed, then minute and sec is set to 0. If the hour and
- # minute is passed, then sec is set to 0.
- def change(options)
- ::DateTime.civil(
- options[:year] || self.year,
- options[:month] || self.month,
- options[:day] || self.day,
- options[:hour] || self.hour,
- options[:min] || (options[:hour] ? 0 : self.min),
- options[:sec] || ((options[:hour] || options[:min]) ? 0 : self.sec),
- options[:offset] || self.offset,
- options[:start] || self.start
- )
- end
+ # Returns a new DateTime where one or more of the elements have been changed according to the +options+ parameter. The time options
+ # (hour, minute, sec) reset cascadingly, so if only the hour is passed, then minute and sec is set to 0. If the hour and
+ # minute is passed, then sec is set to 0.
+ def change(options)
+ ::DateTime.civil(
+ options[:year] || year,
+ options[:month] || month,
+ options[:day] || day,
+ options[:hour] || hour,
+ options[:min] || (options[:hour] ? 0 : min),
+ options[:sec] || ((options[:hour] || options[:min]) ? 0 : sec),
+ options[:offset] || offset,
+ options[:start] || start
+ )
+ end
- # Uses Date to provide precise Time calculations for years, months, and days.
- # The +options+ parameter takes a hash with any of these keys: <tt>:years</tt>,
- # <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>, <tt>:hours</tt>,
- # <tt>:minutes</tt>, <tt>:seconds</tt>.
- def advance(options)
- d = to_date.advance(options)
- datetime_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day)
- seconds_to_advance = (options[:seconds] || 0) + (options[:minutes] || 0) * 60 + (options[:hours] || 0) * 3600
- seconds_to_advance == 0 ? datetime_advanced_by_date : datetime_advanced_by_date.since(seconds_to_advance)
- end
+ # Uses Date to provide precise Time calculations for years, months, and days.
+ # The +options+ parameter takes a hash with any of these keys: <tt>:years</tt>,
+ # <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>, <tt>:hours</tt>,
+ # <tt>:minutes</tt>, <tt>:seconds</tt>.
+ def advance(options)
+ d = to_date.advance(options)
+ datetime_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day)
+ seconds_to_advance = (options[:seconds] || 0) + (options[:minutes] || 0) * 60 + (options[:hours] || 0) * 3600
+ seconds_to_advance == 0 ? datetime_advanced_by_date : datetime_advanced_by_date.since(seconds_to_advance)
+ end
- # Returns a new DateTime representing the time a number of seconds ago
- # Do not use this method in combination with x.months, use months_ago instead!
- def ago(seconds)
- self.since(-seconds)
- end
+ # Returns a new DateTime representing the time a number of seconds ago
+ # Do not use this method in combination with x.months, use months_ago instead!
+ def ago(seconds)
+ since(-seconds)
+ end
- # Returns a new DateTime representing the time a number of seconds since the instance time
- # Do not use this method in combination with x.months, use months_since instead!
- def since(seconds)
- self + Rational(seconds.round, 86400)
- end
- alias :in :since
+ # Returns a new DateTime representing the time a number of seconds since the instance time
+ # Do not use this method in combination with x.months, use months_since instead!
+ def since(seconds)
+ self + Rational(seconds.round, 86400)
+ end
+ alias :in :since
- # Returns a new DateTime representing the start of the day (0:00)
- def beginning_of_day
- change(:hour => 0)
- end
- alias :midnight :beginning_of_day
- alias :at_midnight :beginning_of_day
- alias :at_beginning_of_day :beginning_of_day
+ # Returns a new DateTime representing the start of the day (0:00)
+ def beginning_of_day
+ change(:hour => 0)
+ end
+ alias :midnight :beginning_of_day
+ alias :at_midnight :beginning_of_day
+ alias :at_beginning_of_day :beginning_of_day
- # Returns a new DateTime representing the end of the day (23:59:59)
- def end_of_day
- change(:hour => 23, :min => 59, :sec => 59)
- end
+ # Returns a new DateTime representing the end of the day (23:59:59)
+ def end_of_day
+ change(:hour => 23, :min => 59, :sec => 59)
+ end
- # Adjusts DateTime to UTC by adding its offset value; offset is set to 0
- #
- # Example:
- #
- # DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)) # => Mon, 21 Feb 2005 10:11:12 -0600
- # DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)).utc # => Mon, 21 Feb 2005 16:11:12 +0000
- def utc
- new_offset(0)
- end
- alias_method :getutc, :utc
+ # Adjusts DateTime to UTC by adding its offset value; offset is set to 0
+ #
+ # Example:
+ #
+ # DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)) # => Mon, 21 Feb 2005 10:11:12 -0600
+ # DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)).utc # => Mon, 21 Feb 2005 16:11:12 +0000
+ def utc
+ new_offset(0)
+ end
+ alias_method :getutc, :utc
- # Returns true if offset == 0
- def utc?
- offset == 0
- end
+ # Returns true if offset == 0
+ def utc?
+ offset == 0
+ end
- # Returns the offset value in seconds
- def utc_offset
- (offset * 86400).to_i
- end
+ # Returns the offset value in seconds
+ def utc_offset
+ (offset * 86400).to_i
+ end
- # Layers additional behavior on DateTime#<=> so that Time and ActiveSupport::TimeWithZone instances can be compared with a DateTime
- def compare_with_coercion(other)
- other = other.comparable_time if other.respond_to?(:comparable_time)
- other = other.to_datetime unless other.acts_like?(:date)
- compare_without_coercion(other)
- end
- end
- end
+ # Layers additional behavior on DateTime#<=> so that Time and ActiveSupport::TimeWithZone instances can be compared with a DateTime
+ def compare_with_coercion(other)
+ other = other.comparable_time if other.respond_to?(:comparable_time)
+ other = other.to_datetime unless other.acts_like?(:date)
+ compare_without_coercion(other)
end
+ alias_method :compare_without_coercion, :<=>
+ alias_method :<=>, :compare_with_coercion
end
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 7c948267b3..ddfa8d610d 100644
--- a/activesupport/lib/active_support/core_ext/date_time/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/date_time/conversions.rb
@@ -1,96 +1,84 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module DateTime #:nodoc:
- # Converting datetimes to formatted strings, dates, and times.
- module Conversions
- def self.append_features(base) #:nodoc:
- base.class_eval do
- alias_method :default_inspect, :inspect
- alias_method :to_default_s, :to_s unless (instance_methods(false) & [:to_s, 'to_s']).empty?
+require 'active_support/inflector'
- # Ruby 1.9 has DateTime#to_time which internally relies on Time. We define our own #to_time which allows
- # DateTimes outside the range of what can be created with Time.
- remove_method :to_time if instance_methods.include?(:to_time)
- end
+class DateTime
+ # Ruby 1.9 has DateTime#to_time which internally relies on Time. We define our own #to_time which allows
+ # DateTimes outside the range of what can be created with Time.
+ remove_method :to_time if instance_methods.include?(:to_time)
- super
-
- base.class_eval do
- alias_method :to_s, :to_formatted_s
- alias_method :inspect, :readable_inspect
- end
- end
-
- # Convert to a formatted string. See Time::DATE_FORMATS for predefined formats.
- #
- # This method is aliased to <tt>to_s</tt>.
- #
- # === Examples
- # datetime = DateTime.civil(2007, 12, 4, 0, 0, 0, 0) # => Tue, 04 Dec 2007 00:00:00 +0000
- #
- # datetime.to_formatted_s(:db) # => "2007-12-04 00:00:00"
- # datetime.to_s(:db) # => "2007-12-04 00:00:00"
- # datetime.to_s(:number) # => "20071204000000"
- # datetime.to_formatted_s(:short) # => "04 Dec 00:00"
- # datetime.to_formatted_s(:long) # => "December 04, 2007 00:00"
- # datetime.to_formatted_s(:long_ordinal) # => "December 4th, 2007 00:00"
- # datetime.to_formatted_s(:rfc822) # => "Tue, 04 Dec 2007 00:00:00 +0000"
- #
- # == Adding your own datetime formats to to_formatted_s
- # DateTime formats are shared with Time. You can add your own to the
- # Time::DATE_FORMATS hash. Use the format name as the hash key and
- # either a strftime string or Proc instance that takes a time or
- # datetime argument as the value.
- #
- # # config/initializers/time_formats.rb
- # Time::DATE_FORMATS[:month_and_year] = "%B %Y"
- # Time::DATE_FORMATS[:short_ordinal] = lambda { |time| time.strftime("%B #{time.day.ordinalize}") }
- def to_formatted_s(format = :default)
- return to_default_s unless formatter = ::Time::DATE_FORMATS[format]
- formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
- end
+ # Convert to a formatted string. See Time::DATE_FORMATS for predefined formats.
+ #
+ # This method is aliased to <tt>to_s</tt>.
+ #
+ # === Examples
+ # datetime = DateTime.civil(2007, 12, 4, 0, 0, 0, 0) # => Tue, 04 Dec 2007 00:00:00 +0000
+ #
+ # datetime.to_formatted_s(:db) # => "2007-12-04 00:00:00"
+ # datetime.to_s(:db) # => "2007-12-04 00:00:00"
+ # datetime.to_s(:number) # => "20071204000000"
+ # datetime.to_formatted_s(:short) # => "04 Dec 00:00"
+ # datetime.to_formatted_s(:long) # => "December 04, 2007 00:00"
+ # datetime.to_formatted_s(:long_ordinal) # => "December 4th, 2007 00:00"
+ # datetime.to_formatted_s(:rfc822) # => "Tue, 04 Dec 2007 00:00:00 +0000"
+ #
+ # == Adding your own datetime formats to to_formatted_s
+ # DateTime formats are shared with Time. You can add your own to the
+ # Time::DATE_FORMATS hash. Use the format name as the hash key and
+ # either a strftime string or Proc instance that takes a time or
+ # datetime argument as the value.
+ #
+ # # config/initializers/time_formats.rb
+ # Time::DATE_FORMATS[:month_and_year] = "%B %Y"
+ # Time::DATE_FORMATS[:short_ordinal] = lambda { |time| time.strftime("%B #{time.day.ordinalize}") }
+ def to_formatted_s(format = :default)
+ if formatter = ::Time::DATE_FORMATS[format]
+ formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
+ else
+ to_default_s
+ end
+ end
+ alias_method :to_default_s, :to_s unless (instance_methods(false) & [:to_s, 'to_s']).empty?
+ alias_method :to_s, :to_formatted_s
- # Returns the +utc_offset+ as an +HH:MM formatted string. Examples:
- #
- # datetime = DateTime.civil(2000, 1, 1, 0, 0, 0, Rational(-6, 24))
- # datetime.formatted_offset # => "-06:00"
- # datetime.formatted_offset(false) # => "-0600"
- def formatted_offset(colon = true, alternate_utc_string = nil)
- utc? && alternate_utc_string || utc_offset.to_utc_offset_s(colon)
- end
-
- # 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
+ # Returns the +utc_offset+ as an +HH:MM formatted string. Examples:
+ #
+ # datetime = DateTime.civil(2000, 1, 1, 0, 0, 0, Rational(-6, 24))
+ # datetime.formatted_offset # => "-06:00"
+ # datetime.formatted_offset(false) # => "-0600"
+ def formatted_offset(colon = true, alternate_utc_string = nil)
+ 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"
+ 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
- def to_date
- ::Date.new(year, month, day)
- end
+ # Converts self to a Ruby Date object; time portion is discarded
+ def to_date
+ ::Date.new(year, month, day)
+ end
- # 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) : self
- end
+ # 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) : self
+ end
- # To be able to keep Times, Dates and DateTimes interchangeable on conversions
- def to_datetime
- self
- end
+ # To be able to keep Times, Dates and DateTimes interchangeable on conversions
+ def to_datetime
+ self
+ end
- # Converts datetime to an appropriate format for use in XML
- def xmlschema
- strftime("%Y-%m-%dT%H:%M:%S%Z")
- end if RUBY_VERSION < '1.9'
-
- # Converts self to a floating-point number of seconds since the Unix epoch
- def to_f
- days_since_unix_epoch = self - ::DateTime.civil(1970)
- (days_since_unix_epoch * 86_400).to_f
- end
- end
- end
+ # Converts datetime to an appropriate format for use in XML
+ def xmlschema
+ strftime("%Y-%m-%dT%H:%M:%S%Z")
+ end if RUBY_VERSION < '1.9'
+
+ # Converts self to a floating-point number of seconds since the Unix epoch
+ def to_f
+ days_since_unix_epoch = self - ::DateTime.civil(1970)
+ (days_since_unix_epoch * 86_400).to_f
end
end
diff --git a/activesupport/lib/active_support/core_ext/date_time/zones.rb b/activesupport/lib/active_support/core_ext/date_time/zones.rb
new file mode 100644
index 0000000000..98565e6750
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/date_time/zones.rb
@@ -0,0 +1,17 @@
+class DateTime
+ # Returns the simultaneous time in <tt>Time.zone</tt>.
+ #
+ # Time.zone = 'Hawaii' # => 'Hawaii'
+ # DateTime.new(2000).in_time_zone # => Fri, 31 Dec 1999 14:00:00 HST -10:00
+ #
+ # This method is similar to Time#localtime, except that it uses <tt>Time.zone</tt> as the local zone
+ # instead of the operating system's time zone.
+ #
+ # You can also pass in a TimeZone instance or string that identifies a TimeZone as an argument,
+ # and the conversion will be based on that zone instead of <tt>Time.zone</tt>.
+ #
+ # DateTime.new(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00
+ def in_time_zone(zone = ::Time.zone)
+ ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.__send__(:get_zone, zone))
+ end
+end
diff --git a/activesupport/lib/active_support/core_ext/enumerable.rb b/activesupport/lib/active_support/core_ext/enumerable.rb
index a7eaccfed7..8309b617ae 100644
--- a/activesupport/lib/active_support/core_ext/enumerable.rb
+++ b/activesupport/lib/active_support/core_ext/enumerable.rb
@@ -77,11 +77,10 @@ module Enumerable
# (1..5).each_with_object(1) { |value, memo| memo *= value } # => 1
#
def each_with_object(memo, &block)
- returning memo do |m|
- each do |element|
- block.call(element, m)
- end
+ each do |element|
+ block.call(element, memo)
end
+ memo
end unless [].respond_to?(:each_with_object)
# Convert an enumerable to a hash. Examples:
diff --git a/activesupport/lib/active_support/core_ext/exception.rb b/activesupport/lib/active_support/core_ext/exception.rb
index cde0df4153..b594fbae8e 100644
--- a/activesupport/lib/active_support/core_ext/exception.rb
+++ b/activesupport/lib/active_support/core_ext/exception.rb
@@ -1,15 +1,19 @@
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.
class Exception # :nodoc:
+ # Clean the paths contained in the message.
+ def self.clean_paths(string)
+ require 'pathname' unless defined? Pathname
+ string.gsub(%r{[\w. ]+(/[\w. ]+)+(\.rb)?(\b|$)}) do |path|
+ Pathname.new(path).cleanpath
+ end
+ end
+
def clean_message
- Pathname.clean_within message
+ Exception.clean_paths(message)
end
TraceSubstitutions = []
@@ -18,9 +22,10 @@ class Exception # :nodoc:
def clean_backtrace
backtrace.collect do |line|
- Pathname.clean_within(TraceSubstitutions.inject(line) do |result, (regexp, sub)|
+ substituted = TraceSubstitutions.inject(line) do |result, (regexp, sub)|
result.gsub regexp, sub
- end)
+ end
+ Exception.clean_paths(substituted)
end
end
diff --git a/activesupport/lib/active_support/core_ext/file.rb b/activesupport/lib/active_support/core_ext/file.rb
index e03f8ac44e..dc24afbe7f 100644
--- a/activesupport/lib/active_support/core_ext/file.rb
+++ b/activesupport/lib/active_support/core_ext/file.rb
@@ -1,5 +1 @@
require 'active_support/core_ext/file/atomic'
-
-class File #:nodoc:
- extend ActiveSupport::CoreExtensions::File::Atomic
-end
diff --git a/activesupport/lib/active_support/core_ext/file/atomic.rb b/activesupport/lib/active_support/core_ext/file/atomic.rb
index 8cc5654a4b..249fb1362d 100644
--- a/activesupport/lib/active_support/core_ext/file/atomic.rb
+++ b/activesupport/lib/active_support/core_ext/file/atomic.rb
@@ -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
+ 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)
+ # 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
- end
+ # Set correct permissions on new file
+ chown(old_stat.uid, old_stat.gid, file_name)
+ chmod(old_stat.mode, file_name)
end
end
diff --git a/activesupport/lib/active_support/core_ext/float.rb b/activesupport/lib/active_support/core_ext/float.rb
index af166aa610..7570471b95 100644
--- a/activesupport/lib/active_support/core_ext/float.rb
+++ b/activesupport/lib/active_support/core_ext/float.rb
@@ -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
diff --git a/activesupport/lib/active_support/core_ext/float/rounding.rb b/activesupport/lib/active_support/core_ext/float/rounding.rb
index 062d466838..0b1ae4be7e 100644
--- a/activesupport/lib/active_support/core_ext/float/rounding.rb
+++ b/activesupport/lib/active_support/core_ext/float/rounding.rb
@@ -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
diff --git a/activesupport/lib/active_support/core_ext/float/time.rb b/activesupport/lib/active_support/core_ext/float/time.rb
deleted file mode 100644
index 13f2e0ddca..0000000000
--- a/activesupport/lib/active_support/core_ext/float/time.rb
+++ /dev/null
@@ -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 \ No newline at end of file
diff --git a/activesupport/lib/active_support/core_ext/hash.rb b/activesupport/lib/active_support/core_ext/hash.rb
index a6065ab48e..501483498d 100644
--- a/activesupport/lib/active_support/core_ext/hash.rb
+++ b/activesupport/lib/active_support/core_ext/hash.rb
@@ -1,14 +1,8 @@
-%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/hash/conversions'
+require 'active_support/core_ext/hash/deep_merge'
+require 'active_support/core_ext/hash/diff'
+require 'active_support/core_ext/hash/except'
+require 'active_support/core_ext/hash/indifferent_access'
+require 'active_support/core_ext/hash/keys'
+require 'active_support/core_ext/hash/reverse_merge'
+require 'active_support/core_ext/hash/slice'
diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb
index f8a5e70eea..fa171720f9 100644
--- a/activesupport/lib/active_support/core_ext/hash/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb
@@ -1,236 +1,228 @@
require 'date'
+require 'active_support/core_ext/object/conversions'
+require 'active_support/core_ext/array/conversions'
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Hash #:nodoc:
- module Conversions
- # This module exists to decorate files deserialized using Hash.from_xml with
- # the <tt>original_filename</tt> and <tt>content_type</tt> methods.
- module FileLike #:nodoc:
- attr_writer :original_filename, :content_type
-
- def original_filename
- @original_filename || 'untitled'
- end
-
- def content_type
- @content_type || 'application/octet-stream'
- end
- end
+class Hash
+ # This module exists to decorate files deserialized using Hash.from_xml with
+ # the <tt>original_filename</tt> and <tt>content_type</tt> methods.
+ module FileLike #:nodoc:
+ attr_writer :original_filename, :content_type
- XML_TYPE_NAMES = {
- "Symbol" => "symbol",
- "Fixnum" => "integer",
- "Bignum" => "integer",
- "BigDecimal" => "decimal",
- "Float" => "float",
- "TrueClass" => "boolean",
- "FalseClass" => "boolean",
- "Date" => "date",
- "DateTime" => "datetime",
- "Time" => "datetime"
- } unless defined?(XML_TYPE_NAMES)
-
- XML_FORMATTING = {
- "symbol" => Proc.new { |symbol| symbol.to_s },
- "date" => Proc.new { |date| date.to_s(:db) },
- "datetime" => Proc.new { |time| time.xmlschema },
- "binary" => Proc.new { |binary| ActiveSupport::Base64.encode64(binary) },
- "yaml" => Proc.new { |yaml| yaml.to_yaml }
- } unless defined?(XML_FORMATTING)
-
- # TODO: use Time.xmlschema instead of Time.parse;
- # use regexp instead of Date.parse
- unless defined?(XML_PARSING)
- XML_PARSING = {
- "symbol" => Proc.new { |symbol| symbol.to_sym },
- "date" => Proc.new { |date| ::Date.parse(date) },
- "datetime" => Proc.new { |time| ::Time.parse(time).utc rescue ::DateTime.parse(time).utc },
- "integer" => Proc.new { |integer| integer.to_i },
- "float" => Proc.new { |float| float.to_f },
- "decimal" => Proc.new { |number| BigDecimal(number) },
- "boolean" => Proc.new { |boolean| %w(1 true).include?(boolean.strip) },
- "string" => Proc.new { |string| string.to_s },
- "yaml" => Proc.new { |yaml| YAML::load(yaml) rescue yaml },
- "base64Binary" => Proc.new { |bin| ActiveSupport::Base64.decode64(bin) },
- "file" => Proc.new do |file, entity|
- f = StringIO.new(ActiveSupport::Base64.decode64(file))
- f.extend(FileLike)
- f.original_filename = entity['name']
- f.content_type = entity['content_type']
- f
- end
- }
+ def original_filename
+ @original_filename || 'untitled'
+ end
- XML_PARSING.update(
- "double" => XML_PARSING["float"],
- "dateTime" => XML_PARSING["datetime"]
- )
- end
+ def content_type
+ @content_type || 'application/octet-stream'
+ end
+ end
- def self.included(klass)
- klass.extend(ClassMethods)
- end
+ XML_TYPE_NAMES = {
+ "Symbol" => "symbol",
+ "Fixnum" => "integer",
+ "Bignum" => "integer",
+ "BigDecimal" => "decimal",
+ "Float" => "float",
+ "TrueClass" => "boolean",
+ "FalseClass" => "boolean",
+ "Date" => "date",
+ "DateTime" => "datetime",
+ "Time" => "datetime"
+ } unless defined?(XML_TYPE_NAMES)
+
+ XML_FORMATTING = {
+ "symbol" => Proc.new { |symbol| symbol.to_s },
+ "date" => Proc.new { |date| date.to_s(:db) },
+ "datetime" => Proc.new { |time| time.xmlschema },
+ "binary" => Proc.new { |binary| ActiveSupport::Base64.encode64(binary) },
+ "yaml" => Proc.new { |yaml| yaml.to_yaml }
+ } unless defined?(XML_FORMATTING)
+
+ # TODO: use Time.xmlschema instead of Time.parse;
+ # use regexp instead of Date.parse
+ unless defined?(XML_PARSING)
+ XML_PARSING = {
+ "symbol" => Proc.new { |symbol| symbol.to_sym },
+ "date" => Proc.new { |date| ::Date.parse(date) },
+ "datetime" => Proc.new { |time| ::Time.parse(time).utc rescue ::DateTime.parse(time).utc },
+ "integer" => Proc.new { |integer| integer.to_i },
+ "float" => Proc.new { |float| float.to_f },
+ "decimal" => Proc.new { |number| BigDecimal(number) },
+ "boolean" => Proc.new { |boolean| %w(1 true).include?(boolean.strip) },
+ "string" => Proc.new { |string| string.to_s },
+ "yaml" => Proc.new { |yaml| YAML::load(yaml) rescue yaml },
+ "base64Binary" => Proc.new { |bin| ActiveSupport::Base64.decode64(bin) },
+ "file" => Proc.new do |file, entity|
+ f = StringIO.new(ActiveSupport::Base64.decode64(file))
+ f.extend(FileLike)
+ f.original_filename = entity['name']
+ f.content_type = entity['content_type']
+ f
+ end
+ }
- # Converts a hash into a string suitable for use as a URL query string. An optional <tt>namespace</tt> can be
- # passed to enclose the param names (see example below).
- #
- # ==== Examples
- # { :name => 'David', :nationality => 'Danish' }.to_query # => "name=David&nationality=Danish"
- #
- # { :name => 'David', :nationality => 'Danish' }.to_query('user') # => "user%5Bname%5D=David&user%5Bnationality%5D=Danish"
- def to_query(namespace = nil)
- collect do |key, value|
- value.to_query(namespace ? "#{namespace}[#{key}]" : key)
- end.sort * '&'
- end
-
- alias_method :to_param, :to_query
-
- def to_xml(options = {})
- require 'builder' unless defined?(Builder)
-
- options[:indent] ||= 2
- options.reverse_merge!({ :builder => Builder::XmlMarkup.new(:indent => options[:indent]),
- :root => "hash" })
- options[:builder].instruct! unless options.delete(:skip_instruct)
- root = rename_key(options[:root].to_s, options)
-
- options[:builder].__send__(:method_missing, root) do
- each do |key, value|
- case value
- when ::Hash
- value.to_xml(options.merge({ :root => key, :skip_instruct => true }))
- when ::Array
- value.to_xml(options.merge({ :root => key, :children => key.to_s.singularize, :skip_instruct => true}))
- when ::Method, ::Proc
- # If the Method or Proc takes two arguments, then
- # pass the suggested child element name. This is
- # used if the Method or Proc will be operating over
- # multiple records and needs to create an containing
- # element that will contain the objects being
- # serialized.
- if 1 == value.arity
- value.call(options.merge({ :root => key, :skip_instruct => true }))
- else
- value.call(options.merge({ :root => key, :skip_instruct => true }), key.to_s.singularize)
- end
- else
- if value.respond_to?(:to_xml)
- value.to_xml(options.merge({ :root => key, :skip_instruct => true }))
- else
- type_name = XML_TYPE_NAMES[value.class.name]
-
- key = rename_key(key.to_s, options)
-
- attributes = options[:skip_types] || value.nil? || type_name.nil? ? { } : { :type => type_name }
- if value.nil?
- attributes[:nil] = true
- end
-
- options[:builder].tag!(key,
- XML_FORMATTING[type_name] ? XML_FORMATTING[type_name].call(value) : value,
- attributes
- )
- end
- end
- end
-
- yield options[:builder] if block_given?
- end
+ XML_PARSING.update(
+ "double" => XML_PARSING["float"],
+ "dateTime" => XML_PARSING["datetime"]
+ )
+ end
- end
+ # Converts a hash into a string suitable for use as a URL query string. An optional <tt>namespace</tt> can be
+ # passed to enclose the param names (see example below).
+ #
+ # ==== Examples
+ # { :name => 'David', :nationality => 'Danish' }.to_query # => "name=David&nationality=Danish"
+ #
+ # { :name => 'David', :nationality => 'Danish' }.to_query('user') # => "user%5Bname%5D=David&user%5Bnationality%5D=Danish"
+ def to_query(namespace = nil)
+ collect do |key, value|
+ value.to_query(namespace ? "#{namespace}[#{key}]" : key)
+ end.sort * '&'
+ end
+
+ alias_method :to_param, :to_query
+
+ def to_xml(options = {})
+ require 'builder' unless defined?(Builder)
+
+ options[:indent] ||= 2
+ options.reverse_merge!({ :builder => Builder::XmlMarkup.new(:indent => options[:indent]),
+ :root => "hash" })
+ options[:builder].instruct! unless options.delete(:skip_instruct)
+ root = rename_key(options[:root].to_s, options)
+
+ options[:builder].__send__(:method_missing, root) do
+ each do |key, value|
+ case value
+ when ::Hash
+ value.to_xml(options.merge({ :root => key, :skip_instruct => true }))
+ when ::Array
+ value.to_xml(options.merge({ :root => key, :children => key.to_s.singularize, :skip_instruct => true}))
+ when ::Method, ::Proc
+ # If the Method or Proc takes two arguments, then
+ # pass the suggested child element name. This is
+ # used if the Method or Proc will be operating over
+ # multiple records and needs to create an containing
+ # element that will contain the objects being
+ # serialized.
+ if 1 == value.arity
+ value.call(options.merge({ :root => key, :skip_instruct => true }))
+ else
+ value.call(options.merge({ :root => key, :skip_instruct => true }), key.to_s.singularize)
+ end
+ else
+ if value.respond_to?(:to_xml)
+ value.to_xml(options.merge({ :root => key, :skip_instruct => true }))
+ else
+ type_name = XML_TYPE_NAMES[value.class.name]
- def rename_key(key, options = {})
- camelize = options.has_key?(:camelize) && options[:camelize]
- dasherize = !options.has_key?(:dasherize) || options[:dasherize]
- key = key.camelize if camelize
- dasherize ? key.dasherize : key
- end
+ key = rename_key(key.to_s, options)
- module ClassMethods
- def from_xml(xml)
- typecast_xml_value(unrename_keys(XmlMini.parse(xml)))
- end
-
- private
- def typecast_xml_value(value)
- case value.class.to_s
- when 'Hash'
- if value['type'] == 'array'
- child_key, entries = value.detect { |k,v| k != 'type' } # child_key is throwaway
- if entries.nil? || (c = value['__content__'] && c.blank?)
- []
- else
- case entries.class.to_s # something weird with classes not matching here. maybe singleton methods breaking is_a?
- when "Array"
- entries.collect { |v| typecast_xml_value(v) }
- when "Hash"
- [typecast_xml_value(entries)]
- else
- raise "can't typecast #{entries.inspect}"
- end
- end
- elsif value.has_key?("__content__")
- content = value["__content__"]
- if parser = XML_PARSING[value["type"]]
- if parser.arity == 2
- XML_PARSING[value["type"]].call(content, value)
- else
- XML_PARSING[value["type"]].call(content)
- end
- else
- content
- end
- elsif value['type'] == 'string' && value['nil'] != 'true'
- ""
- # blank or nil parsed values are represented by nil
- elsif value.blank? || value['nil'] == 'true'
- nil
- # If the type is the only element which makes it then
- # this still makes the value nil, except if type is
- # a XML node(where type['value'] is a Hash)
- elsif value['type'] && value.size == 1 && !value['type'].is_a?(::Hash)
- nil
- else
- xml_value = value.inject({}) do |h,(k,v)|
- h[k] = typecast_xml_value(v)
- h
- end
-
- # Turn { :files => { :file => #<StringIO> } into { :files => #<StringIO> } so it is compatible with
- # how multipart uploaded files from HTML appear
- xml_value["file"].is_a?(StringIO) ? xml_value["file"] : xml_value
- end
- when 'Array'
- value.map! { |i| typecast_xml_value(i) }
- case value.length
- when 0 then nil
- when 1 then value.first
- else value
- end
- when 'String'
- value
- else
- raise "can't typecast #{value.class.name} - #{value.inspect}"
+ attributes = options[:skip_types] || value.nil? || type_name.nil? ? { } : { :type => type_name }
+ if value.nil?
+ attributes[:nil] = true
end
+
+ options[:builder].tag!(key,
+ XML_FORMATTING[type_name] ? XML_FORMATTING[type_name].call(value) : value,
+ attributes
+ )
end
+ end
+ end
+
+ yield options[:builder] if block_given?
+ end
- def unrename_keys(params)
- case params.class.to_s
- when "Hash"
- params.inject({}) do |h,(k,v)|
- h[k.to_s.underscore.tr("-", "_")] = unrename_keys(v)
- h
- end
+ end
+
+ def rename_key(key, options = {})
+ camelize = options.has_key?(:camelize) && options[:camelize]
+ dasherize = !options.has_key?(:dasherize) || options[:dasherize]
+ key = key.camelize if camelize
+ dasherize ? key.dasherize : key
+ end
+
+ class << self
+ def from_xml(xml)
+ typecast_xml_value(unrename_keys(ActiveSupport::XmlMini.parse(xml)))
+ end
+
+ private
+ def typecast_xml_value(value)
+ case value.class.to_s
+ when 'Hash'
+ if value['type'] == 'array'
+ child_key, entries = value.detect { |k,v| k != 'type' } # child_key is throwaway
+ if entries.nil? || (c = value['__content__'] && c.blank?)
+ []
+ else
+ case entries.class.to_s # something weird with classes not matching here. maybe singleton methods breaking is_a?
when "Array"
- params.map { |v| unrename_keys(v) }
+ entries.collect { |v| typecast_xml_value(v) }
+ when "Hash"
+ [typecast_xml_value(entries)]
else
- params
+ raise "can't typecast #{entries.inspect}"
+ end
end
+ elsif value.has_key?("__content__")
+ content = value["__content__"]
+ if parser = XML_PARSING[value["type"]]
+ if parser.arity == 2
+ XML_PARSING[value["type"]].call(content, value)
+ else
+ XML_PARSING[value["type"]].call(content)
+ end
+ else
+ content
+ end
+ elsif value['type'] == 'string' && value['nil'] != 'true'
+ ""
+ # blank or nil parsed values are represented by nil
+ elsif value.blank? || value['nil'] == 'true'
+ nil
+ # If the type is the only element which makes it then
+ # this still makes the value nil, except if type is
+ # a XML node(where type['value'] is a Hash)
+ elsif value['type'] && value.size == 1 && !value['type'].is_a?(::Hash)
+ nil
+ else
+ xml_value = value.inject({}) do |h,(k,v)|
+ h[k] = typecast_xml_value(v)
+ h
+ end
+
+ # Turn { :files => { :file => #<StringIO> } into { :files => #<StringIO> } so it is compatible with
+ # how multipart uploaded files from HTML appear
+ xml_value["file"].is_a?(StringIO) ? xml_value["file"] : xml_value
end
+ when 'Array'
+ value.map! { |i| typecast_xml_value(i) }
+ case value.length
+ when 0 then nil
+ when 1 then value.first
+ else value
+ end
+ when 'String'
+ value
+ else
+ raise "can't typecast #{value.class.name} - #{value.inspect}"
+ end
+ end
+
+ def unrename_keys(params)
+ case params.class.to_s
+ when "Hash"
+ params.inject({}) do |h,(k,v)|
+ h[k.to_s.underscore.tr("-", "_")] = unrename_keys(v)
+ h
+ end
+ when "Array"
+ params.map { |v| unrename_keys(v) }
+ else
+ params
end
end
- end
end
end
diff --git a/activesupport/lib/active_support/core_ext/hash/deep_merge.rb b/activesupport/lib/active_support/core_ext/hash/deep_merge.rb
index f8842ba57a..b009be3d84 100644
--- a/activesupport/lib/active_support/core_ext/hash/deep_merge.rb
+++ b/activesupport/lib/active_support/core_ext/hash/deep_merge.rb
@@ -1,23 +1,16 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Hash #:nodoc:
- # Allows for deep merging
- module DeepMerge
- # Returns a new hash with +self+ and +other_hash+ merged recursively.
- def deep_merge(other_hash)
- self.merge(other_hash) do |key, oldval, newval|
- oldval = oldval.to_hash if oldval.respond_to?(:to_hash)
- newval = newval.to_hash if newval.respond_to?(:to_hash)
- oldval.class.to_s == 'Hash' && newval.class.to_s == 'Hash' ? oldval.deep_merge(newval) : newval
- end
- end
-
- # Returns a new hash with +self+ and +other_hash+ merged recursively.
- # Modifies the receiver in place.
- def deep_merge!(other_hash)
- replace(deep_merge(other_hash))
- end
- end
+class Hash
+ # Returns a new hash with +self+ and +other_hash+ merged recursively.
+ def deep_merge(other_hash)
+ merge(other_hash) do |key, oldval, newval|
+ oldval = oldval.to_hash if oldval.respond_to?(:to_hash)
+ newval = newval.to_hash if newval.respond_to?(:to_hash)
+ oldval.class.to_s == 'Hash' && newval.class.to_s == 'Hash' ? oldval.deep_merge(newval) : newval
end
end
+
+ # Returns a new hash with +self+ and +other_hash+ merged recursively.
+ # Modifies the receiver in place.
+ def deep_merge!(other_hash)
+ replace(deep_merge(other_hash))
+ end
end
diff --git a/activesupport/lib/active_support/core_ext/hash/diff.rb b/activesupport/lib/active_support/core_ext/hash/diff.rb
index 6abd678822..da98593458 100644
--- a/activesupport/lib/active_support/core_ext/hash/diff.rb
+++ b/activesupport/lib/active_support/core_ext/hash/diff.rb
@@ -1,19 +1,13 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Hash #:nodoc:
- module Diff
- # Returns a hash that represents the difference between two hashes.
- #
- # Examples:
- #
- # {1 => 2}.diff(1 => 2) # => {}
- # {1 => 2}.diff(1 => 3) # => {1 => 2}
- # {}.diff(1 => 2) # => {1 => 2}
- # {1 => 2, 3 => 4}.diff(1 => 2) # => {3 => 4}
- def diff(h2)
- self.dup.delete_if { |k, v| h2[k] == v }.merge(h2.dup.delete_if { |k, v| self.has_key?(k) })
- end
- end
- end
+class Hash
+ # Returns a hash that represents the difference between two hashes.
+ #
+ # Examples:
+ #
+ # {1 => 2}.diff(1 => 2) # => {}
+ # {1 => 2}.diff(1 => 3) # => {1 => 2}
+ # {}.diff(1 => 2) # => {1 => 2}
+ # {1 => 2, 3 => 4}.diff(1 => 2) # => {3 => 4}
+ def diff(h2)
+ dup.delete_if { |k, v| h2[k] == v }.merge(h2.dup.delete_if { |k, v| has_key?(k) })
end
end
diff --git a/activesupport/lib/active_support/core_ext/hash/except.rb b/activesupport/lib/active_support/core_ext/hash/except.rb
index 949976d741..6d04cb5621 100644
--- a/activesupport/lib/active_support/core_ext/hash/except.rb
+++ b/activesupport/lib/active_support/core_ext/hash/except.rb
@@ -1,25 +1,16 @@
-require 'set'
-
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Hash #:nodoc:
- # Return a hash that includes everything but the given keys. This is useful for
- # limiting a set of parameters to everything but a few known toggles:
- #
- # @person.update_attributes(params[:person].except(:admin))
- module Except
- # Returns a new hash without the given keys.
- def except(*keys)
- dup.except!(*keys)
- end
+class Hash
+ # Return a hash that includes everything but the given keys. This is useful for
+ # limiting a set of parameters to everything but a few known toggles:
+ #
+ # @person.update_attributes(params[:person].except(:admin))
+ def except(*keys)
+ dup.except!(*keys)
+ end
- # Replaces the hash without the given keys.
- def except!(*keys)
- keys.map! { |key| convert_key(key) } if respond_to?(:convert_key)
- keys.each { |key| delete(key) }
- self
- end
- end
- end
+ # Replaces the hash without the given keys.
+ def except!(*keys)
+ keys.map! { |key| convert_key(key) } if respond_to?(:convert_key)
+ keys.each { |key| delete(key) }
+ self
end
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 34ba8a005d..b30e1602b6 100644
--- a/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb
+++ b/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb
@@ -1,143 +1,9 @@
-# This class has dubious semantics and we only have it so that
-# people can write params[:key] instead of params['key']
-# and they get the same value for both keys.
+require 'active_support/hash_with_indifferent_access'
-class HashWithIndifferentAccess < Hash
- def initialize(constructor = {})
- if constructor.is_a?(Hash)
- super()
- update(constructor)
- else
- super(constructor)
- end
- end
-
- def default(key = nil)
- if key.is_a?(Symbol) && include?(key = key.to_s)
- self[key]
- else
- super
- end
- end
-
- alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
- alias_method :regular_update, :update unless method_defined?(:regular_update)
-
- # Assigns a new value to the hash:
- #
- # hash = HashWithIndifferentAccess.new
- # hash[:key] = "value"
- #
- def []=(key, value)
- regular_writer(convert_key(key), convert_value(value))
- end
-
- # Updates the instantized hash with values from the second:
- #
- # hash_1 = HashWithIndifferentAccess.new
- # hash_1[:key] = "value"
- #
- # hash_2 = HashWithIndifferentAccess.new
- # hash_2[:key] = "New Value!"
- #
- # 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
- end
-
- alias_method :merge!, :update
-
- # Checks the hash for a key matching the argument passed in:
- #
- # hash = HashWithIndifferentAccess.new
- # hash["key"] = "value"
- # hash.key? :key # => true
- # hash.key? "key" # => true
- #
- def key?(key)
- super(convert_key(key))
- end
-
- alias_method :include?, :key?
- alias_method :has_key?, :key?
- alias_method :member?, :key?
-
- # Fetches the value for the specified key, same as doing hash[key]
- def fetch(key, *extras)
- super(convert_key(key), *extras)
- end
-
- # Returns an array of the values at the specified indices:
- #
- # hash = HashWithIndifferentAccess.new
- # hash[:a] = "x"
- # hash[:b] = "y"
- # hash.values_at("a", "b") # => ["x", "y"]
- #
- def values_at(*indices)
- indices.collect {|key| self[convert_key(key)]}
- end
-
- # Returns an exact copy of the hash.
- def dup
- HashWithIndifferentAccess.new(self)
- end
-
- # Merges the instantized and the specified hashes together, giving precedence to the values from the second hash
- # Does not overwrite the existing hash.
- def merge(hash)
- self.dup.update(hash)
- end
-
- # Performs the opposite of merge, with the keys and values from the first hash taking precedence over the second.
- # This overloaded definition prevents returning a regular hash, if reverse_merge is called on a HashWithDifferentAccess.
- def reverse_merge(other_hash)
- super other_hash.with_indifferent_access
- end
-
- # Removes a specified key from the hash.
- def delete(key)
- super(convert_key(key))
- end
-
- def stringify_keys!; self end
- def symbolize_keys!; self end
- def to_options!; self end
-
- # Convert to a Hash with String keys.
- def to_hash
- Hash.new(default).merge(self)
- end
-
- protected
- def convert_key(key)
- key.kind_of?(Symbol) ? key.to_s : key
- end
-
- def convert_value(value)
- case value
- when Hash
- value.with_indifferent_access
- when Array
- value.collect { |e| e.is_a?(Hash) ? e.with_indifferent_access : e }
- else
- value
- end
- end
-end
-
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Hash #:nodoc:
- module IndifferentAccess #:nodoc:
- def with_indifferent_access
- hash = HashWithIndifferentAccess.new(self)
- hash.default = self.default
- hash
- end
- end
- end
+class Hash
+ def with_indifferent_access
+ hash = ActiveSupport::HashWithIndifferentAccess.new(self)
+ hash.default = self.default
+ hash
end
end
diff --git a/activesupport/lib/active_support/core_ext/hash/keys.rb b/activesupport/lib/active_support/core_ext/hash/keys.rb
index af9d372d76..ffaa69570f 100644
--- a/activesupport/lib/active_support/core_ext/hash/keys.rb
+++ b/activesupport/lib/active_support/core_ext/hash/keys.rb
@@ -1,52 +1,46 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Hash #:nodoc:
- module Keys
- # Return a new hash with all keys converted to strings.
- def stringify_keys
- inject({}) do |options, (key, value)|
- options[key.to_s] = value
- options
- end
- end
+class Hash
+ # Return a new hash with all keys converted to strings.
+ def stringify_keys
+ inject({}) do |options, (key, value)|
+ options[key.to_s] = value
+ options
+ end
+ end
- # Destructively convert all keys to strings.
- def stringify_keys!
- keys.each do |key|
- self[key.to_s] = delete(key)
- end
- self
- end
+ # Destructively convert all keys to strings.
+ def stringify_keys!
+ keys.each do |key|
+ self[key.to_s] = delete(key)
+ end
+ self
+ end
- # Return a new hash with all keys converted to symbols.
- def symbolize_keys
- inject({}) do |options, (key, value)|
- options[(key.to_sym rescue key) || key] = value
- options
- end
- end
+ # Return a new hash with all keys converted to symbols.
+ def symbolize_keys
+ inject({}) do |options, (key, value)|
+ options[(key.to_sym rescue key) || key] = value
+ options
+ end
+ end
- # Destructively convert all keys to symbols.
- def symbolize_keys!
- self.replace(self.symbolize_keys)
- end
+ # Destructively convert all keys to symbols.
+ def symbolize_keys!
+ self.replace(self.symbolize_keys)
+ end
- alias_method :to_options, :symbolize_keys
- alias_method :to_options!, :symbolize_keys!
+ alias_method :to_options, :symbolize_keys
+ alias_method :to_options!, :symbolize_keys!
- # Validate all keys in a hash match *valid keys, raising ArgumentError on a mismatch.
- # Note that keys are NOT treated indifferently, meaning if you use strings for keys but assert symbols
- # as keys, this will fail.
- #
- # ==== Examples
- # { :name => "Rob", :years => "28" }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key(s): years"
- # { :name => "Rob", :age => "28" }.assert_valid_keys("name", "age") # => raises "ArgumentError: Unknown key(s): name, age"
- # { :name => "Rob", :age => "28" }.assert_valid_keys(:name, :age) # => passes, raises nothing
- def assert_valid_keys(*valid_keys)
- unknown_keys = keys - [valid_keys].flatten
- raise(ArgumentError, "Unknown key(s): #{unknown_keys.join(", ")}") unless unknown_keys.empty?
- end
- end
- end
+ # Validate all keys in a hash match *valid keys, raising ArgumentError on a mismatch.
+ # Note that keys are NOT treated indifferently, meaning if you use strings for keys but assert symbols
+ # as keys, this will fail.
+ #
+ # ==== Examples
+ # { :name => "Rob", :years => "28" }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key(s): years"
+ # { :name => "Rob", :age => "28" }.assert_valid_keys("name", "age") # => raises "ArgumentError: Unknown key(s): name, age"
+ # { :name => "Rob", :age => "28" }.assert_valid_keys(:name, :age) # => passes, raises nothing
+ def assert_valid_keys(*valid_keys)
+ unknown_keys = keys - [valid_keys].flatten
+ raise(ArgumentError, "Unknown key(s): #{unknown_keys.join(", ")}") unless unknown_keys.empty?
end
end
diff --git a/activesupport/lib/active_support/core_ext/hash/reverse_merge.rb b/activesupport/lib/active_support/core_ext/hash/reverse_merge.rb
index 546e261cc9..ebfdcb2cf0 100644
--- a/activesupport/lib/active_support/core_ext/hash/reverse_merge.rb
+++ b/activesupport/lib/active_support/core_ext/hash/reverse_merge.rb
@@ -1,35 +1,28 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Hash #:nodoc:
- # Allows for reverse merging two hashes where the keys in the calling hash take precedence over those
- # in the <tt>other_hash</tt>. This is particularly useful for initializing an option hash with default values:
- #
- # def setup(options = {})
- # options.reverse_merge! :size => 25, :velocity => 10
- # end
- #
- # Using <tt>merge</tt>, the above example would look as follows:
- #
- # def setup(options = {})
- # { :size => 25, :velocity => 10 }.merge(options)
- # end
- #
- # The default <tt>:size</tt> and <tt>:velocity</tt> are only set if the +options+ hash passed in doesn't already
- # have the respective key.
- module ReverseMerge
- # Performs the opposite of <tt>merge</tt>, with the keys and values from the first hash taking precedence over the second.
- def reverse_merge(other_hash)
- other_hash.merge(self)
- end
-
- # Performs the opposite of <tt>merge</tt>, with the keys and values from the first hash taking precedence over the second.
- # Modifies the receiver in place.
- def reverse_merge!(other_hash)
- replace(reverse_merge(other_hash))
- end
+class Hash
+ # Allows for reverse merging two hashes where the keys in the calling hash take precedence over those
+ # in the <tt>other_hash</tt>. This is particularly useful for initializing an option hash with default values:
+ #
+ # def setup(options = {})
+ # options.reverse_merge! :size => 25, :velocity => 10
+ # end
+ #
+ # Using <tt>merge</tt>, the above example would look as follows:
+ #
+ # def setup(options = {})
+ # { :size => 25, :velocity => 10 }.merge(options)
+ # end
+ #
+ # The default <tt>:size</tt> and <tt>:velocity</tt> are only set if the +options+ hash passed in doesn't already
+ # have the respective key.
+ def reverse_merge(other_hash)
+ other_hash.merge(self)
+ end
- alias_method :reverse_update, :reverse_merge!
- end
- end
+ # Performs the opposite of <tt>merge</tt>, with the keys and values from the first hash taking precedence over the second.
+ # Modifies the receiver in place.
+ def reverse_merge!(other_hash)
+ replace(reverse_merge(other_hash))
end
+
+ alias_method :reverse_update, :reverse_merge!
end
diff --git a/activesupport/lib/active_support/core_ext/hash/slice.rb b/activesupport/lib/active_support/core_ext/hash/slice.rb
index d845a6d8ca..7aa394d7bf 100644
--- a/activesupport/lib/active_support/core_ext/hash/slice.rb
+++ b/activesupport/lib/active_support/core_ext/hash/slice.rb
@@ -1,40 +1,32 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Hash #:nodoc:
- # Slice a hash to include only the given keys. This is useful for
- # limiting an options hash to valid keys before passing to a method:
- #
- # def search(criteria = {})
- # assert_valid_keys(:mass, :velocity, :time)
- # end
- #
- # search(options.slice(:mass, :velocity, :time))
- #
- # If you have an array of keys you want to limit to, you should splat them:
- #
- # valid_keys = [:mass, :velocity, :time]
- # search(options.slice(*valid_keys))
- module Slice
- # Returns a new hash with only the given keys.
- def slice(*keys)
- keys = keys.map! { |key| convert_key(key) } if respond_to?(:convert_key)
- hash = self.class.new
- keys.each { |k| hash[k] = self[k] if has_key?(k) }
- hash
- end
+class Hash
+ # Slice a hash to include only the given keys. This is useful for
+ # limiting an options hash to valid keys before passing to a method:
+ #
+ # def search(criteria = {})
+ # assert_valid_keys(:mass, :velocity, :time)
+ # end
+ #
+ # search(options.slice(:mass, :velocity, :time))
+ #
+ # If you have an array of keys you want to limit to, you should splat them:
+ #
+ # valid_keys = [:mass, :velocity, :time]
+ # search(options.slice(*valid_keys))
+ def slice(*keys)
+ keys = keys.map! { |key| convert_key(key) } if respond_to?(:convert_key)
+ hash = self.class.new
+ keys.each { |k| hash[k] = self[k] if has_key?(k) }
+ hash
+ end
- # 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}
- def slice!(*keys)
- keys = keys.map! { |key| convert_key(key) } if respond_to?(:convert_key)
- omit = slice(*self.keys - keys)
- hash = slice(*keys)
- replace(hash)
- omit
- end
- end
- end
+ # 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}
+ def slice!(*keys)
+ keys = keys.map! { |key| convert_key(key) } if respond_to?(:convert_key)
+ omit = slice(*self.keys - keys)
+ hash = slice(*keys)
+ replace(hash)
+ omit
end
end
-
diff --git a/activesupport/lib/active_support/core_ext/integer.rb b/activesupport/lib/active_support/core_ext/integer.rb
index 18a7a402db..7ba018ed7f 100644
--- a/activesupport/lib/active_support/core_ext/integer.rb
+++ b/activesupport/lib/active_support/core_ext/integer.rb
@@ -1,9 +1,3 @@
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
diff --git a/activesupport/lib/active_support/core_ext/integer/even_odd.rb b/activesupport/lib/active_support/core_ext/integer/even_odd.rb
index b1d1e28062..6d005268a3 100644
--- a/activesupport/lib/active_support/core_ext/integer/even_odd.rb
+++ b/activesupport/lib/active_support/core_ext/integer/even_odd.rb
@@ -1,29 +1,16 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Integer #:nodoc:
- # For checking if a fixnum is even or odd.
- #
- # 2.even? # => true
- # 2.odd? # => false
- # 1.even? # => false
- # 1.odd? # => true
- # 0.even? # => true
- # 0.odd? # => false
- # -1.even? # => false
- # -1.odd? # => true
- module EvenOdd
- def multiple_of?(number)
- self % number == 0
- end
+class Integer
+ # Check whether the integer is evenly divisible by the argument.
+ def multiple_of?(number)
+ self % number == 0
+ end
- def even?
- multiple_of? 2
- end if RUBY_VERSION < '1.9'
+ # Is the integer a multiple of 2?
+ def even?
+ multiple_of? 2
+ end if RUBY_VERSION < '1.9'
- def odd?
- !even?
- end if RUBY_VERSION < '1.9'
- end
- end
- end
+ # Is the integer not a multiple of 2?
+ def odd?
+ !even?
+ end if RUBY_VERSION < '1.9'
end
diff --git a/activesupport/lib/active_support/core_ext/integer/inflections.rb b/activesupport/lib/active_support/core_ext/integer/inflections.rb
index 804702beb2..e81e7af436 100644
--- a/activesupport/lib/active_support/core_ext/integer/inflections.rb
+++ b/activesupport/lib/active_support/core_ext/integer/inflections.rb
@@ -1,20 +1,14 @@
require 'active_support/inflector'
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Integer #:nodoc:
- module Inflections
- # 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"
- def ordinalize
- Inflector.ordinalize(self)
- end
- end
- end
+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"
+ def ordinalize
+ ActiveSupport::Inflector.ordinalize(self)
end
end
diff --git a/activesupport/lib/active_support/core_ext/integer/time.rb b/activesupport/lib/active_support/core_ext/integer/time.rb
index 356e145b90..a0ccf0e971 100644
--- a/activesupport/lib/active_support/core_ext/integer/time.rb
+++ b/activesupport/lib/active_support/core_ext/integer/time.rb
@@ -1,45 +1,39 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Integer #:nodoc:
- # Enables the use of time calculations and declarations, like 45.minutes + 2.hours + 4.years.
- #
- # These methods use Time#advance for precise date calculations when using from_now, ago, etc.
- # as well as adding or subtracting their results from a Time object. For example:
- #
- # # equivalent to Time.now.advance(:months => 1)
- # 1.month.from_now
- #
- # # equivalent to Time.now.advance(:years => 2)
- # 2.years.from_now
- #
- # # equivalent to Time.now.advance(:months => 4, :years => 5)
- # (4.months + 5.years).from_now
- #
- # While these methods provide precise calculation when used as in the examples above, care
- # should be taken to note that this is not true if the result of `months', `years', etc is
- # converted before use:
- #
- # # equivalent to 30.days.to_i.from_now
- # 1.month.to_i.from_now
- #
- # # equivalent to 365.25.days.to_f.from_now
- # 1.year.to_f.from_now
- #
- # In such cases, Ruby's core
- # Date[http://stdlib.rubyonrails.org/libdoc/date/rdoc/index.html] and
- # Time[http://stdlib.rubyonrails.org/libdoc/time/rdoc/index.html] should be used for precision
- # date and time arithmetic
- module Time
- def months
- ActiveSupport::Duration.new(self * 30.days, [[:months, self]])
- end
- alias :month :months
+class Integer
+ # Enables the use of time calculations and declarations, like 45.minutes + 2.hours + 4.years.
+ #
+ # These methods use Time#advance for precise date calculations when using from_now, ago, etc.
+ # as well as adding or subtracting their results from a Time object. For example:
+ #
+ # # equivalent to Time.now.advance(:months => 1)
+ # 1.month.from_now
+ #
+ # # equivalent to Time.now.advance(:years => 2)
+ # 2.years.from_now
+ #
+ # # equivalent to Time.now.advance(:months => 4, :years => 5)
+ # (4.months + 5.years).from_now
+ #
+ # While these methods provide precise calculation when used as in the examples above, care
+ # should be taken to note that this is not true if the result of `months', `years', etc is
+ # converted before use:
+ #
+ # # equivalent to 30.days.to_i.from_now
+ # 1.month.to_i.from_now
+ #
+ # # equivalent to 365.25.days.to_f.from_now
+ # 1.year.to_f.from_now
+ #
+ # In such cases, Ruby's core
+ # Date[http://stdlib.rubyonrails.org/libdoc/date/rdoc/index.html] and
+ # Time[http://stdlib.rubyonrails.org/libdoc/time/rdoc/index.html] should be used for precision
+ # date and time arithmetic
+ def months
+ ActiveSupport::Duration.new(self * 30.days, [[:months, self]])
+ end
+ alias :month :months
- def years
- ActiveSupport::Duration.new(self * 365.25.days, [[:years, self]])
- end
- alias :year :years
- end
- end
+ def years
+ ActiveSupport::Duration.new(self * 365.25.days, [[:years, self]])
end
+ alias :year :years
end
diff --git a/activesupport/lib/active_support/core_ext/kernel/reporting.rb b/activesupport/lib/active_support/core_ext/kernel/reporting.rb
index 0f101e8fa4..d9b84e6543 100644
--- a/activesupport/lib/active_support/core_ext/kernel/reporting.rb
+++ b/activesupport/lib/active_support/core_ext/kernel/reporting.rb
@@ -7,15 +7,17 @@ module Kernel
#
# noisy_call # warning voiced
def silence_warnings
- old_verbose, $VERBOSE = $VERBOSE, nil
- yield
- ensure
- $VERBOSE = old_verbose
+ with_warnings(nil) { yield }
end
# Sets $VERBOSE to true for the duration of the block and back to its original value afterwards.
def enable_warnings
- old_verbose, $VERBOSE = $VERBOSE, true
+ with_warnings(true) { yield }
+ end
+
+ # Sets $VERBOSE for the duration of the block and back to its original value afterwards.
+ def with_warnings(flag)
+ old_verbose, $VERBOSE = $VERBOSE, flag
yield
ensure
$VERBOSE = old_verbose
@@ -56,4 +58,4 @@ module Kernel
raise unless exception_classes.any? { |cls| e.kind_of?(cls) }
end
end
-end \ No newline at end of file
+end
diff --git a/activesupport/lib/active_support/core_ext/load_error.rb b/activesupport/lib/active_support/core_ext/load_error.rb
index 6165e95443..f36a21818f 100644
--- a/activesupport/lib/active_support/core_ext/load_error.rb
+++ b/activesupport/lib/active_support/core_ext/load_error.rb
@@ -24,15 +24,12 @@ class MissingSourceFile < LoadError #:nodoc:
] unless defined?(REGEXPS)
end
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module LoadErrorExtensions #:nodoc:
- module LoadErrorClassMethods #:nodoc:
- def new(*args)
- (self == LoadError && MissingSourceFile.from_message(args.first)) || super
- end
- end
- ::LoadError.extend(LoadErrorClassMethods)
+class LoadError
+ def self.new(*args)
+ if self == LoadError
+ MissingSourceFile.from_message(args.first)
+ else
+ super
end
end
end
diff --git a/activesupport/lib/active_support/core_ext/module.rb b/activesupport/lib/active_support/core_ext/module.rb
index cb31437094..c37c9badca 100644
--- a/activesupport/lib/active_support/core_ext/module.rb
+++ b/activesupport/lib/active_support/core_ext/module.rb
@@ -1,11 +1,12 @@
+require 'active_support/core_ext/module/aliasing'
+require 'active_support/core_ext/module/introspection'
+
require 'active_support/core_ext/module/inclusion'
require 'active_support/core_ext/module/attribute_accessors'
require 'active_support/core_ext/module/attr_internal'
require 'active_support/core_ext/module/attr_accessor_with_default'
require 'active_support/core_ext/module/delegation'
-require 'active_support/core_ext/module/introspection'
require 'active_support/core_ext/module/loading'
-require 'active_support/core_ext/module/aliasing'
require 'active_support/core_ext/module/model_naming'
require 'active_support/core_ext/module/synchronization'
require 'active_support/core_ext/module/setup'
diff --git a/activesupport/lib/active_support/core_ext/module/aliasing.rb b/activesupport/lib/active_support/core_ext/module/aliasing.rb
index 10fa520ba1..3cad164148 100644
--- a/activesupport/lib/active_support/core_ext/module/aliasing.rb
+++ b/activesupport/lib/active_support/core_ext/module/aliasing.rb
@@ -1,74 +1,70 @@
-module ActiveSupport
- module CoreExtensions
- module Module
- # Encapsulates the common pattern of:
- #
- # alias_method :foo_without_feature, :foo
- # alias_method :foo, :foo_with_feature
- #
- # With this, you simply do:
- #
- # alias_method_chain :foo, :feature
- #
- # And both aliases are set up for you.
- #
- # Query and bang methods (foo?, foo!) keep the same punctuation:
- #
- # alias_method_chain :foo?, :feature
- #
- # is equivalent to
- #
- # alias_method :foo_without_feature?, :foo?
- # alias_method :foo?, :foo_with_feature?
- #
- # so you can safely chain foo, foo?, and foo! with the same feature.
- def alias_method_chain(target, feature)
- # Strip out punctuation on predicates or bang methods since
- # e.g. target?_without_feature is not a valid method name.
- aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
- yield(aliased_target, punctuation) if block_given?
+class Module
+ # Encapsulates the common pattern of:
+ #
+ # alias_method :foo_without_feature, :foo
+ # alias_method :foo, :foo_with_feature
+ #
+ # With this, you simply do:
+ #
+ # alias_method_chain :foo, :feature
+ #
+ # And both aliases are set up for you.
+ #
+ # Query and bang methods (foo?, foo!) keep the same punctuation:
+ #
+ # alias_method_chain :foo?, :feature
+ #
+ # is equivalent to
+ #
+ # alias_method :foo_without_feature?, :foo?
+ # alias_method :foo?, :foo_with_feature?
+ #
+ # so you can safely chain foo, foo?, and foo! with the same feature.
+ def alias_method_chain(target, feature)
+ # Strip out punctuation on predicates or bang methods since
+ # e.g. target?_without_feature is not a valid method name.
+ aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
+ yield(aliased_target, punctuation) if block_given?
- with_method, without_method = "#{aliased_target}_with_#{feature}#{punctuation}", "#{aliased_target}_without_#{feature}#{punctuation}"
+ with_method, without_method = "#{aliased_target}_with_#{feature}#{punctuation}", "#{aliased_target}_without_#{feature}#{punctuation}"
- alias_method without_method, target
- alias_method target, with_method
+ alias_method without_method, target
+ alias_method target, with_method
- case
- when public_method_defined?(without_method)
- public target
- when protected_method_defined?(without_method)
- protected target
- when private_method_defined?(without_method)
- private target
- end
- end
-
- # Allows you to make aliases for attributes, which includes
- # getter, setter, and query methods.
- #
- # Example:
- #
- # class Content < ActiveRecord::Base
- # # has a title attribute
- # end
- #
- # class Email < Content
- # alias_attribute :subject, :title
- # end
- #
- # e = Email.find(1)
- # e.title # => "Superstars"
- # e.subject # => "Superstars"
- # e.subject? # => true
- # e.subject = "Megastars"
- # e.title # => "Megastars"
- def alias_attribute(new_name, old_name)
- module_eval <<-STR, __FILE__, __LINE__+1
- def #{new_name}; self.#{old_name}; end # def subject; self.title; end
- def #{new_name}?; self.#{old_name}?; end # def subject?; self.title?; end
- def #{new_name}=(v); self.#{old_name} = v; end # def subject=(v); self.title = v; end
- STR
- end
+ case
+ when public_method_defined?(without_method)
+ public target
+ when protected_method_defined?(without_method)
+ protected target
+ when private_method_defined?(without_method)
+ private target
end
end
+
+ # Allows you to make aliases for attributes, which includes
+ # getter, setter, and query methods.
+ #
+ # Example:
+ #
+ # class Content < ActiveRecord::Base
+ # # has a title attribute
+ # end
+ #
+ # class Email < Content
+ # alias_attribute :subject, :title
+ # end
+ #
+ # e = Email.find(1)
+ # e.title # => "Superstars"
+ # e.subject # => "Superstars"
+ # e.subject? # => true
+ # e.subject = "Megastars"
+ # e.title # => "Megastars"
+ def alias_attribute(new_name, old_name)
+ module_eval <<-STR, __FILE__, __LINE__+1
+ def #{new_name}; self.#{old_name}; end # def subject; self.title; end
+ def #{new_name}?; self.#{old_name}?; end # def subject?; self.title?; end
+ def #{new_name}=(v); self.#{old_name} = v; end # def subject=(v); self.title = v; end
+ STR
+ end
end
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 137590d286..131b512944 100644
--- a/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb
+++ b/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb
@@ -1,35 +1,25 @@
-# Extends the module object with module and instance accessors for class attributes,
-# just like the native attr* accessors for instance attributes.
-#
-# module AppConfiguration
-# mattr_accessor :google_api_key
-# self.google_api_key = "123456789"
-#
-# mattr_accessor :paypal_url
-# self.paypal_url = "www.sandbox.paypal.com"
-# end
-#
-# AppConfiguration.google_api_key = "overriding the api key!"
+require 'active_support/core_ext/array/extract_options'
+
class Module
def mattr_reader(*syms)
+ syms.extract_options!
syms.each do |sym|
- next if sym.is_a?(Hash)
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
unless defined? @@#{sym} # unless defined? @@pagination_options
@@#{sym} = nil # @@pagination_options = nil
end # end
- #
+
def self.#{sym} # def self.pagination_options
@@#{sym} # @@pagination_options
end # end
- #
+
def #{sym} # def pagination_options
@@#{sym} # @@pagination_options
end # end
EOS
end
end
-
+
def mattr_writer(*syms)
options = syms.extract_options!
syms.each do |sym|
@@ -37,20 +27,34 @@ class Module
unless defined? @@#{sym} # unless defined? @@pagination_options
@@#{sym} = nil # @@pagination_options = nil
end # end
- #
+
def self.#{sym}=(obj) # def self.pagination_options=(obj)
@@#{sym} = obj # @@pagination_options = obj
end # end
- #
- #{" #
- def #{sym}=(obj) # def pagination_options=(obj)
- @@#{sym} = obj # @@pagination_options = obj
- end # end
- " unless options[:instance_writer] == false } # # instance writer above is generated unless options[:instance_writer] == false
EOS
+
+ unless options[:instance_writer] == false
+ class_eval(<<-EOS, __FILE__, __LINE__)
+ def #{sym}=(obj) # def pagination_options=(obj)
+ @@#{sym} = obj # @@pagination_options = obj
+ end # end
+ EOS
+ end
end
end
-
+
+ # Extends the module object with module and instance accessors for class attributes,
+ # just like the native attr* accessors for instance attributes.
+ #
+ # module AppConfiguration
+ # mattr_accessor :google_api_key
+ # self.google_api_key = "123456789"
+ #
+ # mattr_accessor :paypal_url
+ # self.paypal_url = "www.sandbox.paypal.com"
+ # end
+ #
+ # AppConfiguration.google_api_key = "overriding the api key!"
def mattr_accessor(*syms)
mattr_reader(*syms)
mattr_writer(*syms)
diff --git a/activesupport/lib/active_support/core_ext/module/deprecation.rb b/activesupport/lib/active_support/core_ext/module/deprecation.rb
new file mode 100644
index 0000000000..5a5b4e3f80
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/module/deprecation.rb
@@ -0,0 +1,9 @@
+class Module
+ # Declare that a method has been deprecated.
+ # deprecate :foo
+ # deprecate :bar => 'message'
+ # deprecate :foo, :bar, :baz => 'warning!', :qux => 'gone!'
+ def deprecate(*method_names)
+ ActiveSupport::Deprecation.deprecate_methods(self, *method_names)
+ end
+end
diff --git a/activesupport/lib/active_support/core_ext/module/introspection.rb b/activesupport/lib/active_support/core_ext/module/introspection.rb
index 8beaff4b82..7708d573fa 100644
--- a/activesupport/lib/active_support/core_ext/module/introspection.rb
+++ b/activesupport/lib/active_support/core_ext/module/introspection.rb
@@ -1,90 +1,86 @@
-module ActiveSupport
- module CoreExtensions
- module Module
- # Returns the name of the module containing this one.
- #
- # p M::N.parent_name # => "M"
- def parent_name
- unless defined? @parent_name
- @parent_name = name =~ /::[^:]+\Z/ ? $`.freeze : nil
- end
- @parent_name
- end
+class Module
+ # Returns the name of the module containing this one.
+ #
+ # p M::N.parent_name # => "M"
+ def parent_name
+ unless defined? @parent_name
+ @parent_name = name =~ /::[^:]+\Z/ ? $`.freeze : nil
+ end
+ @parent_name
+ end
- # Returns the module which contains this one according to its name.
- #
- # module M
- # module N
- # end
- # end
- # X = M::N
- #
- # p M::N.parent # => M
- # p X.parent # => M
- #
- # The parent of top-level and anonymous modules is Object.
- #
- # p M.parent # => Object
- # p Module.new.parent # => Object
- #
- def parent
- parent_name ? parent_name.constantize : Object
- end
+ # Returns the module which contains this one according to its name.
+ #
+ # module M
+ # module N
+ # end
+ # end
+ # X = M::N
+ #
+ # p M::N.parent # => M
+ # p X.parent # => M
+ #
+ # The parent of top-level and anonymous modules is Object.
+ #
+ # p M.parent # => Object
+ # p Module.new.parent # => Object
+ #
+ def parent
+ parent_name ? parent_name.constantize : Object
+ end
- # Returns all the parents of this module according to its name, ordered from
- # nested outwards. The receiver is not contained within the result.
- #
- # module M
- # module N
- # end
- # end
- # X = M::N
- #
- # p M.parents # => [Object]
- # p M::N.parents # => [M, Object]
- # p X.parents # => [M, Object]
- #
- def parents
- parents = []
- if parent_name
- parts = parent_name.split('::')
- until parts.empty?
- parents << (parts * '::').constantize
- parts.pop
- end
- end
- parents << Object unless parents.include? Object
- parents
+ # Returns all the parents of this module according to its name, ordered from
+ # nested outwards. The receiver is not contained within the result.
+ #
+ # module M
+ # module N
+ # end
+ # end
+ # X = M::N
+ #
+ # p M.parents # => [Object]
+ # p M::N.parents # => [M, Object]
+ # p X.parents # => [M, Object]
+ #
+ def parents
+ parents = []
+ if parent_name
+ parts = parent_name.split('::')
+ until parts.empty?
+ parents << (parts * '::').constantize
+ parts.pop
end
+ end
+ parents << Object unless parents.include? Object
+ parents
+ end
- if RUBY_VERSION < '1.9'
- # Returns the constants that have been defined locally by this object and
- # not in an ancestor. This method is exact if running under Ruby 1.9. In
- # previous versions it may miss some constants if their definition in some
- # ancestor is identical to their definition in the receiver.
- def local_constants
- inherited = {}
-
- ancestors.each do |anc|
- next if anc == self
- anc.constants.each { |const| inherited[const] = anc.const_get(const) }
- end
+ if RUBY_VERSION < '1.9'
+ # Returns the constants that have been defined locally by this object and
+ # not in an ancestor. This method is exact if running under Ruby 1.9. In
+ # previous versions it may miss some constants if their definition in some
+ # ancestor is identical to their definition in the receiver.
+ def local_constants
+ inherited = {}
- constants.select do |const|
- !inherited.key?(const) || inherited[const].object_id != const_get(const).object_id
- end
- end
- else
- def local_constants #:nodoc:
- constants(false)
- end
+ ancestors.each do |anc|
+ next if anc == self
+ anc.constants.each { |const| inherited[const] = anc.const_get(const) }
end
- # Returns the names of the constants defined locally rather than the
- # constants themselves. See <tt>local_constants</tt>.
- def local_constant_names
- local_constants.map { |c| c.to_s }
+ constants.select do |const|
+ !inherited.key?(const) || inherited[const].object_id != const_get(const).object_id
end
end
+ else
+ def local_constants #:nodoc:
+ constants(false)
+ end
+ end
+
+ # Returns the names of the constants defined locally rather than the
+ # constants themselves. See <tt>local_constants</tt>.
+ def local_constant_names
+ local_constants.map { |c| c.to_s }
end
end
diff --git a/activesupport/lib/active_support/core_ext/name_error.rb b/activesupport/lib/active_support/core_ext/name_error.rb
index 49176c12d9..cd165626c8 100644
--- a/activesupport/lib/active_support/core_ext/name_error.rb
+++ b/activesupport/lib/active_support/core_ext/name_error.rb
@@ -1,10 +1,9 @@
-# Add a +missing_name+ method to NameError instances.
-class NameError #:nodoc:
- # Add a method to obtain the missing name from a NameError.
+class NameError
+ # Extract the name of the missing constant from the exception message.
def missing_name
$1 if /((::)?([A-Z]\w*)(::[A-Z]\w*)*)$/ =~ message
end
-
+
# Was this exception raised because the given name was missing?
def missing_name?(name)
if name.is_a? Symbol
diff --git a/activesupport/lib/active_support/core_ext/numeric.rb b/activesupport/lib/active_support/core_ext/numeric.rb
index 759b86b81d..3805cf7990 100644
--- a/activesupport/lib/active_support/core_ext/numeric.rb
+++ b/activesupport/lib/active_support/core_ext/numeric.rb
@@ -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/numeric/time'
diff --git a/activesupport/lib/active_support/core_ext/numeric/bytes.rb b/activesupport/lib/active_support/core_ext/numeric/bytes.rb
index 56477673a3..507d651261 100644
--- a/activesupport/lib/active_support/core_ext/numeric/bytes.rb
+++ b/activesupport/lib/active_support/core_ext/numeric/bytes.rb
@@ -1,44 +1,37 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Numeric #:nodoc:
- # Enables the use of byte calculations and declarations, like 45.bytes + 2.6.megabytes
- module Bytes
- def bytes
- self
- end
- alias :byte :bytes
+class Numeric
+ # Enables the use of byte calculations and declarations, like 45.bytes + 2.6.megabytes
+ def bytes
+ self
+ end
+ alias :byte :bytes
- def kilobytes
- self * 1024
- end
- alias :kilobyte :kilobytes
+ def kilobytes
+ self * 1024
+ end
+ alias :kilobyte :kilobytes
- def megabytes
- self * 1024.kilobytes
- end
- alias :megabyte :megabytes
+ def megabytes
+ self * 1024.kilobytes
+ end
+ alias :megabyte :megabytes
- def gigabytes
- self * 1024.megabytes
- end
- alias :gigabyte :gigabytes
+ def gigabytes
+ self * 1024.megabytes
+ end
+ alias :gigabyte :gigabytes
- def terabytes
- self * 1024.gigabytes
- end
- alias :terabyte :terabytes
-
- def petabytes
- self * 1024.terabytes
- end
- alias :petabyte :petabytes
-
- def exabytes
- self * 1024.petabytes
- end
- alias :exabyte :exabytes
-
- end
- end
+ def terabytes
+ self * 1024.gigabytes
+ end
+ alias :terabyte :terabytes
+
+ def petabytes
+ self * 1024.terabytes
+ end
+ alias :petabyte :petabytes
+
+ def exabytes
+ self * 1024.petabytes
end
+ alias :exabyte :exabytes
end
diff --git a/activesupport/lib/active_support/core_ext/numeric/conversions.rb b/activesupport/lib/active_support/core_ext/numeric/conversions.rb
deleted file mode 100644
index e652ae5ca8..0000000000
--- a/activesupport/lib/active_support/core_ext/numeric/conversions.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Numeric #:nodoc:
- module Conversions
- # Assumes self represents an offset from UTC in seconds (as returned from Time#utc_offset)
- # and turns this into an +HH:MM formatted string. Example:
- #
- # -21_600.to_utc_offset_s # => "-06:00"
- def to_utc_offset_s(colon=true)
- seconds = self
- sign = (seconds < 0 ? -1 : 1)
- hours = seconds.abs / 3600
- minutes = (seconds.abs % 3600) / 60
- "%+03d%s%02d" % [ hours * sign, colon ? ":" : "", minutes ]
- end
- end
- end
- end
-end
diff --git a/activesupport/lib/active_support/core_ext/numeric/time.rb b/activesupport/lib/active_support/core_ext/numeric/time.rb
index bc7f180cd1..2955e8ff1d 100644
--- a/activesupport/lib/active_support/core_ext/numeric/time.rb
+++ b/activesupport/lib/active_support/core_ext/numeric/time.rb
@@ -1,81 +1,75 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Numeric #:nodoc:
- # Enables the use of time calculations and declarations, like 45.minutes + 2.hours + 4.years.
- #
- # These methods use Time#advance for precise date calculations when using from_now, ago, etc.
- # as well as adding or subtracting their results from a Time object. For example:
- #
- # # equivalent to Time.now.advance(:months => 1)
- # 1.month.from_now
- #
- # # equivalent to Time.now.advance(:years => 2)
- # 2.years.from_now
- #
- # # equivalent to Time.now.advance(:months => 4, :years => 5)
- # (4.months + 5.years).from_now
- #
- # While these methods provide precise calculation when used as in the examples above, care
- # should be taken to note that this is not true if the result of `months', `years', etc is
- # converted before use:
- #
- # # equivalent to 30.days.to_i.from_now
- # 1.month.to_i.from_now
- #
- # # equivalent to 365.25.days.to_f.from_now
- # 1.year.to_f.from_now
- #
- # In such cases, Ruby's core
- # Date[http://stdlib.rubyonrails.org/libdoc/date/rdoc/index.html] and
- # Time[http://stdlib.rubyonrails.org/libdoc/time/rdoc/index.html] should be used for precision
- # date and time arithmetic
- module Time
- def seconds
- ActiveSupport::Duration.new(self, [[:seconds, self]])
- end
- alias :second :seconds
-
- def minutes
- ActiveSupport::Duration.new(self * 60, [[:seconds, self * 60]])
- end
- alias :minute :minutes
-
- def hours
- ActiveSupport::Duration.new(self * 3600, [[:seconds, self * 3600]])
- end
- alias :hour :hours
-
- def days
- ActiveSupport::Duration.new(self * 24.hours, [[:days, self]])
- end
- alias :day :days
+class Numeric
+ # Enables the use of time calculations and declarations, like 45.minutes + 2.hours + 4.years.
+ #
+ # These methods use Time#advance for precise date calculations when using from_now, ago, etc.
+ # as well as adding or subtracting their results from a Time object. For example:
+ #
+ # # equivalent to Time.now.advance(:months => 1)
+ # 1.month.from_now
+ #
+ # # equivalent to Time.now.advance(:years => 2)
+ # 2.years.from_now
+ #
+ # # equivalent to Time.now.advance(:months => 4, :years => 5)
+ # (4.months + 5.years).from_now
+ #
+ # While these methods provide precise calculation when used as in the examples above, care
+ # should be taken to note that this is not true if the result of `months', `years', etc is
+ # converted before use:
+ #
+ # # equivalent to 30.days.to_i.from_now
+ # 1.month.to_i.from_now
+ #
+ # # equivalent to 365.25.days.to_f.from_now
+ # 1.year.to_f.from_now
+ #
+ # In such cases, Ruby's core
+ # Date[http://stdlib.rubyonrails.org/libdoc/date/rdoc/index.html] and
+ # Time[http://stdlib.rubyonrails.org/libdoc/time/rdoc/index.html] should be used for precision
+ # date and time arithmetic
+ def seconds
+ ActiveSupport::Duration.new(self, [[:seconds, self]])
+ end
+ alias :second :seconds
- def weeks
- ActiveSupport::Duration.new(self * 7.days, [[:days, self * 7]])
- end
- alias :week :weeks
-
- def fortnights
- ActiveSupport::Duration.new(self * 2.weeks, [[:days, self * 14]])
- end
- alias :fortnight :fortnights
-
- # Reads best without arguments: 10.minutes.ago
- def ago(time = ::Time.now)
- time - self
- end
+ def minutes
+ ActiveSupport::Duration.new(self * 60, [[:seconds, self * 60]])
+ end
+ alias :minute :minutes
+
+ def hours
+ ActiveSupport::Duration.new(self * 3600, [[:seconds, self * 3600]])
+ end
+ alias :hour :hours
+
+ def days
+ ActiveSupport::Duration.new(self * 24.hours, [[:days, self]])
+ end
+ alias :day :days
- # Reads best with argument: 10.minutes.until(time)
- alias :until :ago
+ def weeks
+ ActiveSupport::Duration.new(self * 7.days, [[:days, self * 7]])
+ end
+ alias :week :weeks
+
+ def fortnights
+ ActiveSupport::Duration.new(self * 2.weeks, [[:days, self * 14]])
+ end
+ alias :fortnight :fortnights
+
+ # Reads best without arguments: 10.minutes.ago
+ def ago(time = ::Time.now)
+ time - self
+ end
- # Reads best with argument: 10.minutes.since(time)
- def since(time = ::Time.now)
- time + self
- end
+ # Reads best with argument: 10.minutes.until(time)
+ alias :until :ago
- # Reads best without arguments: 10.minutes.from_now
- alias :from_now :since
- end
- end
+ # Reads best with argument: 10.minutes.since(time)
+ def since(time = ::Time.now)
+ time + self
end
+
+ # Reads best without arguments: 10.minutes.from_now
+ alias :from_now :since
end
diff --git a/activesupport/lib/active_support/core_ext/object.rb b/activesupport/lib/active_support/core_ext/object.rb
index 0796a7b710..96385d2b87 100644
--- a/activesupport/lib/active_support/core_ext/object.rb
+++ b/activesupport/lib/active_support/core_ext/object.rb
@@ -1,3 +1,7 @@
+require 'active_support/core_ext/object/blank'
+require 'active_support/core_ext/object/duplicable'
+require 'active_support/core_ext/object/try'
+
require 'active_support/core_ext/object/conversions'
require 'active_support/core_ext/object/extending'
require 'active_support/core_ext/object/instance_variables'
diff --git a/activesupport/lib/active_support/core_ext/object/acts_like.rb b/activesupport/lib/active_support/core_ext/object/acts_like.rb
new file mode 100644
index 0000000000..fcc8e50f06
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/object/acts_like.rb
@@ -0,0 +1,10 @@
+class Object
+ # A duck-type assistant method. For example, Active Support extends Date
+ # to define an acts_like_date? method, and extends Time to define
+ # acts_like_time?. As a result, we can do "x.acts_like?(:time)" and
+ # "x.acts_like?(:date)" to do duck-type-safe comparisons, since classes that
+ # we want to act like Time simply need to define an acts_like_time? method.
+ def acts_like?(duck)
+ respond_to? :"acts_like_#{duck}?"
+ end
+end
diff --git a/activesupport/lib/active_support/core_ext/blank.rb b/activesupport/lib/active_support/core_ext/object/blank.rb
index 4f8dc4e281..9a1f663bf3 100644
--- a/activesupport/lib/active_support/core_ext/blank.rb
+++ b/activesupport/lib/active_support/core_ext/object/blank.rb
@@ -12,7 +12,7 @@ class Object
def blank?
respond_to?(:empty?) ? empty? : !self
end
-
+
# An object is present if it's not blank.
def present?
!blank?
diff --git a/activesupport/lib/active_support/core_ext/duplicable.rb b/activesupport/lib/active_support/core_ext/object/duplicable.rb
index 8f49ddfd9e..8f49ddfd9e 100644
--- a/activesupport/lib/active_support/core_ext/duplicable.rb
+++ b/activesupport/lib/active_support/core_ext/object/duplicable.rb
diff --git a/activesupport/lib/active_support/core_ext/object/misc.rb b/activesupport/lib/active_support/core_ext/object/misc.rb
index 4acdfa3d6c..fb1bcdb98f 100644
--- a/activesupport/lib/active_support/core_ext/object/misc.rb
+++ b/activesupport/lib/active_support/core_ext/object/misc.rb
@@ -77,14 +77,4 @@ class Object
def with_options(options)
yield ActiveSupport::OptionMerger.new(self, options)
end
-
- # A duck-type assistant method. For example, Active Support extends Date
- # to define an acts_like_date? method, and extends Time to define
- # acts_like_time?. As a result, we can do "x.acts_like?(:time)" and
- # "x.acts_like?(:date)" to do duck-type-safe comparisons, since classes that
- # we want to act like Time simply need to define an acts_like_time? method.
- def acts_like?(duck)
- respond_to? "acts_like_#{duck}?"
- end
-
end
diff --git a/activesupport/lib/active_support/core_ext/try.rb b/activesupport/lib/active_support/core_ext/object/try.rb
index 3de198d198..a1c63a0e54 100644
--- a/activesupport/lib/active_support/core_ext/try.rb
+++ b/activesupport/lib/active_support/core_ext/object/try.rb
@@ -1,8 +1,8 @@
class Object
- # Invokes the method identified by the symbol +method+, passing it any arguments
+ # Invokes the method identified by the symbol +method+, passing it any arguments
# and/or the block specified, just like the regular Ruby <tt>Object#send</tt> does.
#
- # *Unlike* that method however, a +NoMethodError+ exception will *not* be raised
+ # *Unlike* that method however, a +NoMethodError+ exception will *not* be raised
# and +nil+ will be returned instead, if the receiving object is a +nil+ object or NilClass.
#
# ==== Examples
@@ -19,7 +19,7 @@ class Object
# Person.try(:find, 1)
# @people.try(:collect) {|p| p.name}
#--
- # This method definition below is for rdoc purposes only. The alias_method call
+ # This method definition below is for rdoc purposes only. The alias_method call
# below overrides it as an optimization since +try+ behaves like +Object#send+,
# unless called on +NilClass+.
def try(method, *args, &block)
@@ -29,7 +29,7 @@ class Object
alias_method :try, :__send__
end
-class NilClass
+class NilClass #:nodoc:
def try(*args)
nil
end
diff --git a/activesupport/lib/active_support/core_ext/pathname.rb b/activesupport/lib/active_support/core_ext/pathname.rb
deleted file mode 100644
index 4c5318ee63..0000000000
--- a/activesupport/lib/active_support/core_ext/pathname.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-require 'pathname'
-require 'active_support/core_ext/pathname/clean_within'
-
-class Pathname#:nodoc:
- extend ActiveSupport::CoreExtensions::Pathname::CleanWithin
-end
-
diff --git a/activesupport/lib/active_support/core_ext/pathname/clean_within.rb b/activesupport/lib/active_support/core_ext/pathname/clean_within.rb
deleted file mode 100644
index ae03e1bc5a..0000000000
--- a/activesupport/lib/active_support/core_ext/pathname/clean_within.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-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
- end
- end
-end
diff --git a/activesupport/lib/active_support/core_ext/process/daemon.rb b/activesupport/lib/active_support/core_ext/process/daemon.rb
index 95ad5f8a5d..f5202ddee4 100644
--- a/activesupport/lib/active_support/core_ext/process/daemon.rb
+++ b/activesupport/lib/active_support/core_ext/process/daemon.rb
@@ -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
+ unless nochdir
+ Dir.chdir "/" # Release old working directory.
+ end
- File.umask 0000 # Ensure sensible umask. Adjust as needed.
+ 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
+ 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 }
+ trap("TERM") { exit }
- return 0
- end
- end
+ return 0
+ end unless respond_to?(:daemon)
end
diff --git a/activesupport/lib/active_support/core_ext/range.rb b/activesupport/lib/active_support/core_ext/range.rb
index 0d2b169e3f..c0736f3a44 100644
--- a/activesupport/lib/active_support/core_ext/range.rb
+++ b/activesupport/lib/active_support/core_ext/range.rb
@@ -1,11 +1,4 @@
+require 'active_support/core_ext/range/blockless_step'
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/range/overlaps'
diff --git a/activesupport/lib/active_support/core_ext/range/blockless_step.rb b/activesupport/lib/active_support/core_ext/range/blockless_step.rb
index 6fa1eb5bee..f4792d03b7 100644
--- a/activesupport/lib/active_support/core_ext/range/blockless_step.rb
+++ b/activesupport/lib/active_support/core_ext/range/blockless_step.rb
@@ -1,32 +1,27 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Range #:nodoc:
- # Return an array when step is called without a block.
- module BlocklessStep
- def self.included(base) #:nodoc:
- base.alias_method_chain :step, :blockless
- end
-
- if RUBY_VERSION < '1.9'
- def step_with_blockless(value = 1, &block)
- if block_given?
- step_without_blockless(value, &block)
- else
- returning [] do |array|
- step_without_blockless(value) { |step| array << step }
- end
- end
- end
- else
- def step_with_blockless(value = 1, &block)
- if block_given?
- step_without_blockless(value, &block)
- else
- step_without_blockless(value).to_a
- end
- end
- end
+class Range
+ begin
+ (1..2).step
+ # Range#step doesn't return an Enumerator
+ rescue LocalJumpError
+ # Return an array when step is called without a block.
+ def step_with_blockless(*args, &block)
+ if block_given?
+ step_without_blockless(*args, &block)
+ else
+ array = []
+ step_without_blockless(*args) { |step| array << step }
+ array
+ end
+ end
+ else
+ def step_with_blockless(*args, &block) #:nodoc:
+ if block_given?
+ step_without_blockless(*args, &block)
+ else
+ step_without_blockless(*args).to_a
end
end
end
+
+ alias_method_chain :step, :blockless
end
diff --git a/activesupport/lib/active_support/core_ext/range/conversions.rb b/activesupport/lib/active_support/core_ext/range/conversions.rb
index 45b0826b62..11a7ff66de 100644
--- a/activesupport/lib/active_support/core_ext/range/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/range/conversions.rb
@@ -1,27 +1,21 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Range #:nodoc:
- # Getting ranges in different convenient string representations and other objects
- module Conversions
- RANGE_FORMATS = {
- :db => Proc.new { |start, stop| "BETWEEN '#{start.to_s(:db)}' AND '#{stop.to_s(:db)}'" }
- }
+class Range
+ RANGE_FORMATS = {
+ :db => Proc.new { |start, stop| "BETWEEN '#{start.to_s(:db)}' AND '#{stop.to_s(:db)}'" }
+ }
- def self.included(base) #:nodoc:
- base.class_eval do
- alias_method :to_default_s, :to_s
- alias_method :to_s, :to_formatted_s
- end
- end
- # Gives a human readable format of the range.
- #
- # ==== Example
- #
- # [1..100].to_formatted_s # => "1..100"
- def to_formatted_s(format = :default)
- RANGE_FORMATS[format] ? RANGE_FORMATS[format].call(first, last) : to_default_s
- end
- end
+ # Gives a human readable format of the range.
+ #
+ # ==== Example
+ #
+ # [1..100].to_formatted_s # => "1..100"
+ def to_formatted_s(format = :default)
+ if formatter = RANGE_FORMATS[format]
+ formatter.call(first, last)
+ else
+ to_default_s
end
end
+
+ alias_method :to_default_s, :to_s
+ alias_method :to_s, :to_formatted_s
end
diff --git a/activesupport/lib/active_support/core_ext/range/include_range.rb b/activesupport/lib/active_support/core_ext/range/include_range.rb
index 9a7d235695..0246627467 100644
--- a/activesupport/lib/active_support/core_ext/range/include_range.rb
+++ b/activesupport/lib/active_support/core_ext/range/include_range.rb
@@ -1,30 +1,21 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Range #:nodoc:
- # Check if a Range includes another Range.
- module IncludeRange
- def self.included(base) #:nodoc:
- base.alias_method_chain :include?, :range
- end
-
- # Extends the default Range#include? to support range comparisons.
- # (1..5).include?(1..5) # => true
- # (1..5).include?(2..3) # => true
- # (1..5).include?(2..6) # => false
- #
- # The native Range#include? behavior is untouched.
- # ("a".."f").include?("c") # => true
- # (5..9).include?(11) # => false
- def include_with_range?(value)
- if value.is_a?(::Range)
- operator = exclude_end? ? :< : :<=
- end_value = value.exclude_end? ? last.succ : last
- include?(value.first) && (value.last <=> end_value).send(operator, 0)
- else
- include_without_range?(value)
- end
- end
- end
+class Range
+ # Extends the default Range#include? to support range comparisons.
+ # (1..5).include?(1..5) # => true
+ # (1..5).include?(2..3) # => true
+ # (1..5).include?(2..6) # => false
+ #
+ # The native Range#include? behavior is untouched.
+ # ("a".."f").include?("c") # => true
+ # (5..9).include?(11) # => false
+ def include_with_range?(value)
+ if value.is_a?(::Range)
+ operator = exclude_end? ? :< : :<=
+ end_value = value.exclude_end? ? last.succ : last
+ include_without_range?(value.first) && (value.last <=> end_value).send(operator, 0)
+ else
+ include_without_range?(value)
end
end
+
+ alias_method_chain :include?, :range
end
diff --git a/activesupport/lib/active_support/core_ext/range/overlaps.rb b/activesupport/lib/active_support/core_ext/range/overlaps.rb
index 43c69453e7..0dec6e0ac4 100644
--- a/activesupport/lib/active_support/core_ext/range/overlaps.rb
+++ b/activesupport/lib/active_support/core_ext/range/overlaps.rb
@@ -1,15 +1,8 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Range #:nodoc:
- # Check if Ranges overlap.
- module Overlaps
- # Compare two ranges and see if they overlap eachother
- # (1..5).overlaps?(4..6) # => true
- # (1..5).overlaps?(7..9) # => false
- def overlaps?(other)
- include?(other.first) || other.include?(first)
- end
- end
- end
+class Range
+ # Compare two ranges and see if they overlap eachother
+ # (1..5).overlaps?(4..6) # => true
+ # (1..5).overlaps?(7..9) # => false
+ def overlaps?(other)
+ include?(other.first) || other.include?(first)
end
end
diff --git a/activesupport/lib/active_support/core_ext/rexml.rb b/activesupport/lib/active_support/core_ext/rexml.rb
index b4891a9153..decc4f6d9c 100644
--- a/activesupport/lib/active_support/core_ext/rexml.rb
+++ b/activesupport/lib/active_support/core_ext/rexml.rb
@@ -7,12 +7,12 @@ 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'
- module REXML
- class Entity < Child
+ module REXML #:nodoc:
+ class Entity < Child #:nodoc:
undef_method :unnormalized
def unnormalized
document.record_entity_expansion! if document
@@ -22,7 +22,7 @@ unless (defined?(REXML::VERSION) ? REXML::VERSION : REXML::Version) > "3.1.7.2"
@unnormalized
end
end
- class Document < Element
+ class Document < Element #:nodoc:
@@entity_expansion_limit = 10_000
def self.entity_expansion_limit= val
@@entity_expansion_limit = val
diff --git a/activesupport/lib/active_support/core_ext/string.rb b/activesupport/lib/active_support/core_ext/string.rb
index 16c544a577..222199a9a4 100644
--- a/activesupport/lib/active_support/core_ext/string.rb
+++ b/activesupport/lib/active_support/core_ext/string.rb
@@ -1,22 +1,19 @@
# encoding: utf-8
-require 'active_support/core_ext/string/inflections'
require 'active_support/core_ext/string/conversions'
-require 'active_support/core_ext/string/access'
+require 'active_support/core_ext/string/filters'
+require 'active_support/core_ext/string/multibyte'
require 'active_support/core_ext/string/starts_ends_with'
+
+require 'active_support/core_ext/string/inflections'
+require 'active_support/core_ext/string/access'
require 'active_support/core_ext/string/iterators'
-require 'active_support/core_ext/string/multibyte'
require 'active_support/core_ext/string/xchar'
-require 'active_support/core_ext/string/filters'
require 'active_support/core_ext/string/behavior'
class String #:nodoc:
include ActiveSupport::CoreExtensions::String::Access
- include ActiveSupport::CoreExtensions::String::Conversions
- include ActiveSupport::CoreExtensions::String::Filters
include ActiveSupport::CoreExtensions::String::Inflections
- include ActiveSupport::CoreExtensions::String::StartsEndsWith
include ActiveSupport::CoreExtensions::String::Iterators
include ActiveSupport::CoreExtensions::String::Behavior
- include ActiveSupport::CoreExtensions::String::Multibyte
end
diff --git a/activesupport/lib/active_support/core_ext/string/conversions.rb b/activesupport/lib/active_support/core_ext/string/conversions.rb
index d4334dcefe..39c2b1b8ed 100644
--- a/activesupport/lib/active_support/core_ext/string/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/string/conversions.rb
@@ -1,28 +1,21 @@
require 'date'
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module String #:nodoc:
- # Converting strings to other objects
- module Conversions
- # 'a'.ord == 'a'[0] for Ruby 1.9 forward compatibility.
- def ord
- self[0]
- end if RUBY_VERSION < '1.9'
+class String
+ # 'a'.ord == 'a'[0] for Ruby 1.9 forward compatibility.
+ def ord
+ self[0]
+ end if RUBY_VERSION < '1.9'
- # Form can be either :utc (default) or :local.
- def to_time(form = :utc)
- ::Time.send("#{form}_time", *::Date._parse(self, false).values_at(:year, :mon, :mday, :hour, :min, :sec).map { |arg| arg || 0 })
- end
+ # Form can be either :utc (default) or :local.
+ def to_time(form = :utc)
+ ::Time.send("#{form}_time", *::Date._parse(self, false).values_at(:year, :mon, :mday, :hour, :min, :sec).map { |arg| arg || 0 })
+ end
- def to_date
- ::Date.new(*::Date._parse(self, false).values_at(:year, :mon, :mday))
- end
+ def to_date
+ ::Date.new(*::Date._parse(self, false).values_at(:year, :mon, :mday))
+ end
- def to_datetime
- ::DateTime.civil(*::Date._parse(self, false).values_at(:year, :mon, :mday, :hour, :min, :sec).map { |arg| arg || 0 })
- end
- end
- end
+ def to_datetime
+ ::DateTime.civil(*::Date._parse(self, false).values_at(:year, :mon, :mday, :hour, :min, :sec).map { |arg| arg || 0 })
end
end
diff --git a/activesupport/lib/active_support/core_ext/string/filters.rb b/activesupport/lib/active_support/core_ext/string/filters.rb
index 0329fbb8d4..6fda7efef5 100644
--- a/activesupport/lib/active_support/core_ext/string/filters.rb
+++ b/activesupport/lib/active_support/core_ext/string/filters.rb
@@ -1,26 +1,20 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module String #:nodoc:
- module Filters
- # Returns the string, first removing all whitespace on both ends of
- # the string, and then changing remaining consecutive whitespace
- # groups into one space each.
- #
- # Examples:
- # %{ Multi-line
- # string }.squish # => "Multi-line string"
- # " foo bar \n \t boo".squish # => "foo bar boo"
- def squish
- dup.squish!
- end
+class String
+ # Returns the string, first removing all whitespace on both ends of
+ # the string, and then changing remaining consecutive whitespace
+ # groups into one space each.
+ #
+ # Examples:
+ # %{ Multi-line
+ # string }.squish # => "Multi-line string"
+ # " foo bar \n \t boo".squish # => "foo bar boo"
+ def squish
+ dup.squish!
+ end
- # Performs a destructive squish. See String#squish.
- def squish!
- strip!
- gsub!(/\s+/, ' ')
- self
- end
- end
- end
+ # Performs a destructive squish. See String#squish.
+ def squish!
+ strip!
+ gsub!(/\s+/, ' ')
+ self
end
end
diff --git a/activesupport/lib/active_support/core_ext/string/iterators.rb b/activesupport/lib/active_support/core_ext/string/iterators.rb
index fe17d140ca..6ca6375fda 100644
--- a/activesupport/lib/active_support/core_ext/string/iterators.rb
+++ b/activesupport/lib/active_support/core_ext/string/iterators.rb
@@ -1,4 +1,4 @@
-require 'strscan'
+autoload :StringScanner, 'strscan' unless defined? :StringScanner
module ActiveSupport #:nodoc:
module CoreExtensions #:nodoc:
diff --git a/activesupport/lib/active_support/core_ext/string/multibyte.rb b/activesupport/lib/active_support/core_ext/string/multibyte.rb
index 8f8f0968fd..0f0dfb2443 100644
--- a/activesupport/lib/active_support/core_ext/string/multibyte.rb
+++ b/activesupport/lib/active_support/core_ext/string/multibyte.rb
@@ -1,84 +1,73 @@
# encoding: utf-8
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module String #:nodoc:
- # Implements multibyte methods for easier access to multibyte characters in a String instance.
- module Multibyte
- unless '1.9'.respond_to?(:force_encoding)
- # == Multibyte proxy
- #
- # +mb_chars+ is a multibyte safe proxy for string methods.
- #
- # In Ruby 1.8 and older it creates and returns an instance of the ActiveSupport::Multibyte::Chars class which
- # encapsulates the original string. A Unicode safe version of all the String methods are defined on this proxy
- # class. If the proxy class doesn't respond to a certain method, it's forwarded to the encapsuled string.
- #
- # name = 'Claus Müller'
- # name.reverse #=> "rell??M sualC"
- # name.length #=> 13
- #
- # name.mb_chars.reverse.to_s #=> "rellüM sualC"
- # name.mb_chars.length #=> 12
- #
- # In Ruby 1.9 and newer +mb_chars+ returns +self+ because String is (mostly) encoding aware. This means that
- # it becomes easy to run one version of your code on multiple Ruby versions.
- #
- # == Method chaining
- #
- # All the methods on the Chars proxy which normally return a string will return a Chars object. This allows
- # method chaining on the result of any of these methods.
- #
- # name.mb_chars.reverse.length #=> 12
- #
- # == Interoperability and configuration
- #
- # The Chars object tries to be as interchangeable with String objects as possible: sorting and comparing between
- # String and Char work like expected. The bang! methods change the internal string representation in the Chars
- # object. Interoperability problems can be resolved easily with a +to_s+ call.
- #
- # For more information about the methods defined on the Chars proxy see ActiveSupport::Multibyte::Chars. For
- # information about how to change the default Multibyte behaviour see ActiveSupport::Multibyte.
- def mb_chars
- if ActiveSupport::Multibyte.proxy_class.wants?(self)
- ActiveSupport::Multibyte.proxy_class.new(self)
- else
- self
- end
- end
-
- # Returns true if the string has UTF-8 semantics (a String used for purely byte resources is unlikely to have
- # them), returns false otherwise.
- def is_utf8?
- ActiveSupport::Multibyte::Chars.consumes?(self)
- end
+class String
+ unless '1.9'.respond_to?(:force_encoding)
+ # == Multibyte proxy
+ #
+ # +mb_chars+ is a multibyte safe proxy for string methods.
+ #
+ # In Ruby 1.8 and older it creates and returns an instance of the ActiveSupport::Multibyte::Chars class which
+ # encapsulates the original string. A Unicode safe version of all the String methods are defined on this proxy
+ # class. If the proxy class doesn't respond to a certain method, it's forwarded to the encapsuled string.
+ #
+ # name = 'Claus Müller'
+ # name.reverse #=> "rell??M sualC"
+ # name.length #=> 13
+ #
+ # name.mb_chars.reverse.to_s #=> "rellüM sualC"
+ # name.mb_chars.length #=> 12
+ #
+ # In Ruby 1.9 and newer +mb_chars+ returns +self+ because String is (mostly) encoding aware. This means that
+ # it becomes easy to run one version of your code on multiple Ruby versions.
+ #
+ # == Method chaining
+ #
+ # All the methods on the Chars proxy which normally return a string will return a Chars object. This allows
+ # method chaining on the result of any of these methods.
+ #
+ # name.mb_chars.reverse.length #=> 12
+ #
+ # == Interoperability and configuration
+ #
+ # The Chars object tries to be as interchangeable with String objects as possible: sorting and comparing between
+ # String and Char work like expected. The bang! methods change the internal string representation in the Chars
+ # object. Interoperability problems can be resolved easily with a +to_s+ call.
+ #
+ # For more information about the methods defined on the Chars proxy see ActiveSupport::Multibyte::Chars. For
+ # information about how to change the default Multibyte behaviour see ActiveSupport::Multibyte.
+ def mb_chars
+ if ActiveSupport::Multibyte.proxy_class.wants?(self)
+ ActiveSupport::Multibyte.proxy_class.new(self)
+ else
+ self
+ end
+ end
+
+ # Returns true if the string has UTF-8 semantics (a String used for purely byte resources is unlikely to have
+ # them), returns false otherwise.
+ def is_utf8?
+ ActiveSupport::Multibyte::Chars.consumes?(self)
+ end
- unless '1.8.7 and later'.respond_to?(:chars)
- def chars
- # FIXME:
- # ActiveSupport::Deprecation refers to RAILS_ENV
- # and is a show stopper for 3rd party applications
- # that only want ActiveSupport
- ActiveSupport::Deprecation.warn('String#chars has been deprecated in favor of String#mb_chars.', caller) if defined?(ActiveSupport::Deprecation)
- mb_chars
- end
- end
- else
- def mb_chars #:nodoc
- self
- end
-
- def is_utf8? #:nodoc
- case encoding
- when Encoding::UTF_8
- valid_encoding?
- when Encoding::ASCII_8BIT, Encoding::US_ASCII
- dup.force_encoding(Encoding::UTF_8).valid_encoding?
- else
- false
- end
- end
- end
+ unless '1.8.7 and later'.respond_to?(:chars)
+ def chars
+ ActiveSupport::Deprecation.warn('String#chars has been deprecated in favor of String#mb_chars.', caller)
+ mb_chars
+ end
+ end
+ else
+ def mb_chars #:nodoc
+ self
+ end
+
+ def is_utf8? #:nodoc
+ case encoding
+ when Encoding::UTF_8
+ valid_encoding?
+ when Encoding::ASCII_8BIT, Encoding::US_ASCII
+ dup.force_encoding(Encoding::UTF_8).valid_encoding?
+ else
+ false
end
end
end
diff --git a/activesupport/lib/active_support/core_ext/string/starts_ends_with.rb b/activesupport/lib/active_support/core_ext/string/starts_ends_with.rb
index 09f9a188b5..f65bb8f75b 100644
--- a/activesupport/lib/active_support/core_ext/string/starts_ends_with.rb
+++ b/activesupport/lib/active_support/core_ext/string/starts_ends_with.rb
@@ -1,35 +1,18 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module String #:nodoc:
- # Additional string tests.
- module StartsEndsWith
- def self.append_features(base)
- if '1.8.7 and up'.respond_to?(:start_with?)
- base.class_eval do
- alias_method :starts_with?, :start_with?
- alias_method :ends_with?, :end_with?
- end
- else
- super
- base.class_eval do
- alias_method :start_with?, :starts_with?
- alias_method :end_with?, :ends_with?
- end
- end
- end
-
- # Does the string start with the specified +prefix+?
- def starts_with?(prefix)
- prefix = prefix.to_s
- self[0, prefix.length] == prefix
- end
+class String
+ unless '1.8.7 and up'.respond_to?(:start_with?)
+ # Does the string start with the specified +prefix+?
+ def start_with?(prefix)
+ prefix = prefix.to_s
+ self[0, prefix.length] == prefix
+ end
- # Does the string end with the specified +suffix+?
- def ends_with?(suffix)
- suffix = suffix.to_s
- self[-suffix.length, suffix.length] == suffix
- end
- end
+ # Does the string end with the specified +suffix+?
+ def end_with?(suffix)
+ suffix = suffix.to_s
+ self[-suffix.length, suffix.length] == suffix
end
end
+
+ alias_method :starts_with?, :start_with?
+ alias_method :ends_with?, :end_with?
end
diff --git a/activesupport/lib/active_support/core_ext/string/xchar.rb b/activesupport/lib/active_support/core_ext/string/xchar.rb
index df186e42d7..7183218634 100644
--- a/activesupport/lib/active_support/core_ext/string/xchar.rb
+++ b/activesupport/lib/active_support/core_ext/string/xchar.rb
@@ -1,11 +1,18 @@
begin
- # See http://bogomips.org/fast_xs/ by Eric Wong
+ # See http://bogomips.org/fast_xs/ by Eric Wong.
+ # Also included with hpricot.
require 'fast_xs'
+rescue LoadError
+ # fast_xs extension unavailable
+else
+ begin
+ require 'builder'
+ rescue LoadError
+ # builder demands the first shot at defining String#to_xs
+ end
class String
alias_method :original_xs, :to_xs if method_defined?(:to_xs)
alias_method :to_xs, :fast_xs
end
-rescue LoadError
- # fast_xs extension unavailable.
end
diff --git a/activesupport/lib/active_support/core_ext/symbol.rb b/activesupport/lib/active_support/core_ext/symbol.rb
index e4ac443809..520369452b 100644
--- a/activesupport/lib/active_support/core_ext/symbol.rb
+++ b/activesupport/lib/active_support/core_ext/symbol.rb
@@ -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
diff --git a/activesupport/lib/active_support/core_ext/time.rb b/activesupport/lib/active_support/core_ext/time.rb
index 78bbfc917c..b28f7f1a32 100644
--- a/activesupport/lib/active_support/core_ext/time.rb
+++ b/activesupport/lib/active_support/core_ext/time.rb
@@ -1,42 +1,10 @@
require 'date'
require 'time'
-class Time
- # Ruby 1.8-cvs and 1.9 define private Time#to_date
- %w(to_date to_datetime).each do |method|
- public method if private_instance_methods.include?(method)
- end
+require 'active_support/core_ext/time/publicize_conversion_methods'
+require 'active_support/core_ext/time/marshal_with_utc_flag'
- # Pre-1.9 versions of Ruby have a bug with marshaling Time instances, where utc instances are
- # unmarshaled in the local zone, instead of utc. We're layering behavior on the _dump and _load
- # methods so that utc instances can be flagged on dump, and coerced back to utc on load.
- if RUBY_VERSION < '1.9'
- class << self
- alias_method :_original_load, :_load
- def _load(marshaled_time)
- time = _original_load(marshaled_time)
- utc = time.instance_variable_get('@marshal_with_utc_coercion')
- utc ? time.utc : time
- end
- end
-
- alias_method :_original_dump, :_dump
- def _dump(*args)
- obj = self.frozen? ? self.dup : self
- obj.instance_variable_set('@marshal_with_utc_coercion', utc?)
- obj._original_dump(*args)
- end
- end
-end
-
-require 'active_support/core_ext/time/behavior'
+require 'active_support/core_ext/time/acts_like'
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
diff --git a/activesupport/lib/active_support/core_ext/time/acts_like.rb b/activesupport/lib/active_support/core_ext/time/acts_like.rb
new file mode 100644
index 0000000000..3f853b7893
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/time/acts_like.rb
@@ -0,0 +1,8 @@
+require 'active_support/core_ext/object/acts_like'
+
+class Time
+ # Duck-types as a Time-like class. See Object#acts_like?.
+ def acts_like_time?
+ true
+ end
+end
diff --git a/activesupport/lib/active_support/core_ext/time/behavior.rb b/activesupport/lib/active_support/core_ext/time/behavior.rb
deleted file mode 100644
index a5c0baacdf..0000000000
--- a/activesupport/lib/active_support/core_ext/time/behavior.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Time #:nodoc:
- module Behavior
- # Enable more predictable duck-typing on Time-like classes. See
- # Object#acts_like?.
- def acts_like_time?
- true
- end
- end
- end
- end
-end
diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb
index d13d0e01a7..b73c3b2c9b 100644
--- a/activesupport/lib/active_support/core_ext/time/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/time/calculations.rb
@@ -1,295 +1,279 @@
require 'active_support/duration'
+require 'active_support/core_ext/date/calculations'
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Time #:nodoc:
- # Enables the use of time calculations within Time itself
- module Calculations
- def self.included(base) #:nodoc:
- base.extend ClassMethods
-
- base.class_eval do
- alias_method :plus_without_duration, :+
- alias_method :+, :plus_with_duration
-
- alias_method :minus_without_duration, :-
- alias_method :-, :minus_with_duration
-
- alias_method :minus_without_coercion, :-
- alias_method :-, :minus_with_coercion
-
- alias_method :compare_without_coercion, :<=>
- alias_method :<=>, :compare_with_coercion
- end
- end
-
- COMMON_YEAR_DAYS_IN_MONTH = [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
-
- module ClassMethods
- # Overriding case equality method so that it returns true for ActiveSupport::TimeWithZone instances
- def ===(other)
- other.is_a?(::Time)
- end
-
- # Return the number of days in the given month.
- # If no year is specified, it will use the current year.
- def days_in_month(month, year = now.year)
- return 29 if month == 2 && ::Date.gregorian_leap?(year)
- COMMON_YEAR_DAYS_IN_MONTH[month]
- end
-
- # Returns a new Time if requested year can be accommodated by Ruby's Time class
- # (i.e., if year is within either 1970..2038 or 1902..2038, depending on system architecture);
- # otherwise returns a DateTime
- def time_with_datetime_fallback(utc_or_local, year, month=1, day=1, hour=0, min=0, sec=0, usec=0)
- ::Time.send(utc_or_local, year, month, day, hour, min, sec, usec)
- rescue
- offset = utc_or_local.to_sym == :local ? ::DateTime.local_offset : 0
- ::DateTime.civil(year, month, day, hour, min, sec, offset)
- end
-
- # Wraps class method +time_with_datetime_fallback+ with +utc_or_local+ set to <tt>:utc</tt>.
- def utc_time(*args)
- time_with_datetime_fallback(:utc, *args)
- end
-
- # Wraps class method +time_with_datetime_fallback+ with +utc_or_local+ set to <tt>:local</tt>.
- def local_time(*args)
- time_with_datetime_fallback(:local, *args)
- end
- end
-
- # Tells whether the Time object's time lies in the past
- def past?
- self < ::Time.current
- end
-
- # Tells whether the Time object's time is today
- def today?
- self.to_date == ::Date.current
- end
-
- # Tells whether the Time object's time lies in the future
- def future?
- self > ::Time.current
- end
-
- # Seconds since midnight: Time.now.seconds_since_midnight
- def seconds_since_midnight
- self.to_i - self.change(:hour => 0).to_i + (self.usec/1.0e+6)
- end
-
- # Returns a new Time where one or more of the elements have been changed according to the +options+ parameter. The time options
- # (hour, minute, sec, usec) reset cascadingly, so if only the hour is passed, then minute, sec, and usec is set to 0. If the hour and
- # minute is passed, then sec and usec is set to 0.
- def change(options)
- ::Time.send(
- self.utc? ? :utc_time : :local_time,
- options[:year] || self.year,
- options[:month] || self.month,
- options[:day] || self.day,
- options[:hour] || self.hour,
- options[:min] || (options[:hour] ? 0 : self.min),
- options[:sec] || ((options[:hour] || options[:min]) ? 0 : self.sec),
- options[:usec] || ((options[:hour] || options[:min] || options[:sec]) ? 0 : self.usec)
- )
- end
-
- # Uses Date to provide precise Time calculations for years, months, and days.
- # The +options+ parameter takes a hash with any of these keys: <tt>:years</tt>,
- # <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>, <tt>:hours</tt>,
- # <tt>:minutes</tt>, <tt>:seconds</tt>.
- def advance(options)
- unless options[:weeks].nil?
- options[:weeks], partial_weeks = options[:weeks].divmod(1)
- options[:days] = (options[:days] || 0) + 7 * partial_weeks
- end
-
- unless options[:days].nil?
- options[:days], partial_days = options[:days].divmod(1)
- options[:hours] = (options[:hours] || 0) + 24 * partial_days
- end
-
- d = to_date.advance(options)
- time_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day)
- seconds_to_advance = (options[:seconds] || 0) + (options[:minutes] || 0) * 60 + (options[:hours] || 0) * 3600
- seconds_to_advance == 0 ? time_advanced_by_date : time_advanced_by_date.since(seconds_to_advance)
- end
-
- # Returns a new Time representing the time a number of seconds ago
- def ago(seconds)
- self.since(-seconds)
- end
-
- # Returns a new Time representing the time a number of seconds since the instance time
- def since(seconds)
- self + seconds
- rescue
- self.to_datetime.since(seconds)
- end
- alias :in :since
-
- # Returns a new Time representing the time a number of specified months ago
- def months_ago(months)
- advance(:months => -months)
- end
-
- # Returns a new Time representing the time a number of specified months in the future
- def months_since(months)
- advance(:months => months)
- end
-
- # Returns a new Time representing the time a number of specified years ago
- def years_ago(years)
- advance(:years => -years)
- end
-
- # Returns a new Time representing the time a number of specified years in the future
- def years_since(years)
- advance(:years => years)
- end
-
- # Short-hand for years_ago(1)
- def last_year
- years_ago(1)
- end
-
- # Short-hand for years_since(1)
- def next_year
- years_since(1)
- end
-
-
- # Short-hand for months_ago(1)
- def last_month
- months_ago(1)
- end
-
- # Short-hand for months_since(1)
- def next_month
- months_since(1)
- end
-
- # Returns a new Time representing the "start" of this week (Monday, 0:00)
- def beginning_of_week
- days_to_monday = self.wday!=0 ? self.wday-1 : 6
- (self - days_to_monday.days).midnight
- end
- alias :monday :beginning_of_week
- alias :at_beginning_of_week :beginning_of_week
-
- # Returns a new Time representing the end of this week (Sunday, 23:59:59)
- def end_of_week
- days_to_sunday = self.wday!=0 ? 7-self.wday : 0
- (self + days_to_sunday.days).end_of_day
- end
- alias :at_end_of_week :end_of_week
-
- # Returns a new Time representing the start of the given day in next week (default is Monday).
- def next_week(day = :monday)
- days_into_week = { :monday => 0, :tuesday => 1, :wednesday => 2, :thursday => 3, :friday => 4, :saturday => 5, :sunday => 6}
- since(1.week).beginning_of_week.since(days_into_week[day].day).change(:hour => 0)
- end
-
- # Returns a new Time representing the start of the day (0:00)
- def beginning_of_day
- (self - self.seconds_since_midnight).change(:usec => 0)
- end
- alias :midnight :beginning_of_day
- alias :at_midnight :beginning_of_day
- alias :at_beginning_of_day :beginning_of_day
-
- # Returns a new Time representing the end of the day (23:59:59)
- def end_of_day
- change(:hour => 23, :min => 59, :sec => 59)
- end
-
- # 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)
- end
- alias :at_beginning_of_month :beginning_of_month
-
- # Returns a new Time representing the end of the month (last day of the month, 0:00)
- def end_of_month
- #self - ((self.mday-1).days + self.seconds_since_midnight)
- last_day = ::Time.days_in_month( self.month, self.year )
- change(:day => last_day, :hour => 23, :min => 59, :sec => 59, :usec => 0)
- end
- alias :at_end_of_month :end_of_month
-
- # Returns a new Time representing the start of the quarter (1st of january, april, july, october, 0:00)
- def beginning_of_quarter
- beginning_of_month.change(:month => [10, 7, 4, 1].detect { |m| m <= self.month })
- end
- alias :at_beginning_of_quarter :beginning_of_quarter
-
- # Returns a new Time representing the end of the quarter (last day of march, june, september, december, 23:59:59)
- def end_of_quarter
- beginning_of_month.change(:month => [3, 6, 9, 12].detect { |m| m >= self.month }).end_of_month
- end
- alias :at_end_of_quarter :end_of_quarter
-
- # 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)
- end
- alias :at_beginning_of_year :beginning_of_year
-
- # Returns a new Time representing the end of the year (31st of december, 23:59:59)
- def end_of_year
- change(:month => 12,:day => 31,:hour => 23, :min => 59, :sec => 59)
- end
- alias :at_end_of_year :end_of_year
-
- # Convenience method which returns a new Time representing the time 1 day ago
- def yesterday
- advance(:days => -1)
- end
-
- # Convenience method which returns a new Time representing the time 1 day since the instance time
- def tomorrow
- advance(:days => 1)
- end
-
- def plus_with_duration(other) #:nodoc:
- if ActiveSupport::Duration === other
- other.since(self)
- else
- plus_without_duration(other)
- end
- end
-
- def minus_with_duration(other) #:nodoc:
- if ActiveSupport::Duration === other
- other.until(self)
- else
- minus_without_duration(other)
- end
- end
-
- # Time#- can also be used to determine the number of seconds between two Time instances.
- # We're layering on additional behavior so that ActiveSupport::TimeWithZone instances
- # are coerced into values that Time#- will recognize
- def minus_with_coercion(other)
- other = other.comparable_time if other.respond_to?(:comparable_time)
- minus_without_coercion(other)
- end
-
- # Layers additional behavior on Time#<=> so that DateTime and ActiveSupport::TimeWithZone instances
- # can be chronologically compared with a Time
- def compare_with_coercion(other)
- # if other is an ActiveSupport::TimeWithZone, coerce a Time instance from it so we can do <=> comparison
- other = other.comparable_time if other.respond_to?(:comparable_time)
- if other.acts_like?(:date)
- # other is a Date/DateTime, so coerce self #to_datetime and hand off to DateTime#<=>
- to_datetime.compare_without_coercion(other)
- else
- compare_without_coercion(other)
- end
- end
- end
+class Time
+ COMMON_YEAR_DAYS_IN_MONTH = [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+ DAYS_INTO_WEEK = { :monday => 0, :tuesday => 1, :wednesday => 2, :thursday => 3, :friday => 4, :saturday => 5, :sunday => 6 }
+
+ class << self
+ # Overriding case equality method so that it returns true for ActiveSupport::TimeWithZone instances
+ def ===(other)
+ other.is_a?(::Time)
+ end
+
+ # Return the number of days in the given month.
+ # If no year is specified, it will use the current year.
+ def days_in_month(month, year = now.year)
+ return 29 if month == 2 && ::Date.gregorian_leap?(year)
+ COMMON_YEAR_DAYS_IN_MONTH[month]
+ end
+
+ # Returns a new Time if requested year can be accommodated by Ruby's Time class
+ # (i.e., if year is within either 1970..2038 or 1902..2038, depending on system architecture);
+ # otherwise returns a DateTime
+ def time_with_datetime_fallback(utc_or_local, year, month=1, day=1, hour=0, min=0, sec=0, usec=0)
+ ::Time.send(utc_or_local, year, month, day, hour, min, sec, usec)
+ rescue
+ offset = utc_or_local.to_sym == :local ? ::DateTime.local_offset : 0
+ ::DateTime.civil(year, month, day, hour, min, sec, offset)
+ end
+
+ # Wraps class method +time_with_datetime_fallback+ with +utc_or_local+ set to <tt>:utc</tt>.
+ def utc_time(*args)
+ time_with_datetime_fallback(:utc, *args)
+ end
+
+ # Wraps class method +time_with_datetime_fallback+ with +utc_or_local+ set to <tt>:local</tt>.
+ def local_time(*args)
+ time_with_datetime_fallback(:local, *args)
+ end
+ end
+
+ # Tells whether the Time object's time lies in the past
+ def past?
+ self < ::Time.current
+ end
+
+ # Tells whether the Time object's time is today
+ def today?
+ to_date == ::Date.current
+ end
+
+ # Tells whether the Time object's time lies in the future
+ def future?
+ self > ::Time.current
+ end
+
+ # Seconds since midnight: Time.now.seconds_since_midnight
+ def seconds_since_midnight
+ to_i - change(:hour => 0).to_i + (usec / 1.0e+6)
+ end
+
+ # Returns a new Time where one or more of the elements have been changed according to the +options+ parameter. The time options
+ # (hour, minute, sec, usec) reset cascadingly, so if only the hour is passed, then minute, sec, and usec is set to 0. If the hour and
+ # minute is passed, then sec and usec is set to 0.
+ def change(options)
+ ::Time.send(
+ utc? ? :utc_time : :local_time,
+ options[:year] || year,
+ options[:month] || month,
+ options[:day] || day,
+ options[:hour] || hour,
+ options[:min] || (options[:hour] ? 0 : min),
+ options[:sec] || ((options[:hour] || options[:min]) ? 0 : sec),
+ options[:usec] || ((options[:hour] || options[:min] || options[:sec]) ? 0 : usec)
+ )
+ end
+
+ # Uses Date to provide precise Time calculations for years, months, and days.
+ # The +options+ parameter takes a hash with any of these keys: <tt>:years</tt>,
+ # <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>, <tt>:hours</tt>,
+ # <tt>:minutes</tt>, <tt>:seconds</tt>.
+ def advance(options)
+ unless options[:weeks].nil?
+ options[:weeks], partial_weeks = options[:weeks].divmod(1)
+ options[:days] = (options[:days] || 0) + 7 * partial_weeks
+ end
+
+ unless options[:days].nil?
+ options[:days], partial_days = options[:days].divmod(1)
+ options[:hours] = (options[:hours] || 0) + 24 * partial_days
+ end
+
+ d = to_date.advance(options)
+ time_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day)
+ seconds_to_advance = (options[:seconds] || 0) + (options[:minutes] || 0) * 60 + (options[:hours] || 0) * 3600
+ seconds_to_advance == 0 ? time_advanced_by_date : time_advanced_by_date.since(seconds_to_advance)
+ end
+
+ # Returns a new Time representing the time a number of seconds ago, this is basically a wrapper around the Numeric extension
+ def ago(seconds)
+ since(-seconds)
+ end
+
+ # Returns a new Time representing the time a number of seconds since the instance time
+ def since(seconds)
+ self + seconds
+ rescue
+ to_datetime.since(seconds)
+ end
+ alias :in :since
+
+ # Returns a new Time representing the time a number of specified months ago
+ def months_ago(months)
+ advance(:months => -months)
+ end
+
+ # Returns a new Time representing the time a number of specified months in the future
+ def months_since(months)
+ advance(:months => months)
+ end
+
+ # Returns a new Time representing the time a number of specified years ago
+ def years_ago(years)
+ advance(:years => -years)
+ end
+
+ # Returns a new Time representing the time a number of specified years in the future
+ def years_since(years)
+ advance(:years => years)
+ end
+
+ # Short-hand for years_ago(1)
+ def last_year
+ years_ago(1)
+ end
+
+ # Short-hand for years_since(1)
+ def next_year
+ years_since(1)
+ end
+
+
+ # Short-hand for months_ago(1)
+ def last_month
+ months_ago(1)
+ end
+
+ # Short-hand for months_since(1)
+ def next_month
+ months_since(1)
+ end
+
+ # Returns a new Time representing the "start" of this week (Monday, 0:00)
+ def beginning_of_week
+ days_to_monday = wday!=0 ? wday-1 : 6
+ (self - days_to_monday.days).midnight
+ end
+ alias :monday :beginning_of_week
+ alias :at_beginning_of_week :beginning_of_week
+
+ # Returns a new Time representing the end of this week (Sunday, 23:59:59)
+ def end_of_week
+ days_to_sunday = wday!=0 ? 7-wday : 0
+ (self + days_to_sunday.days).end_of_day
+ end
+ alias :at_end_of_week :end_of_week
+
+ # Returns a new Time representing the start of the given day in next week (default is Monday).
+ def next_week(day = :monday)
+ since(1.week).beginning_of_week.since(DAYS_INTO_WEEK[day].day).change(:hour => 0)
+ end
+
+ # Returns a new Time representing the start of the day (0:00)
+ def beginning_of_day
+ (self - seconds_since_midnight).change(:usec => 0)
+ end
+ alias :midnight :beginning_of_day
+ alias :at_midnight :beginning_of_day
+ alias :at_beginning_of_day :beginning_of_day
+
+ # Returns a new Time representing the end of the day (23:59:59)
+ def end_of_day
+ change(:hour => 23, :min => 59, :sec => 59)
+ end
+
+ # 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)
+ end
+ alias :at_beginning_of_month :beginning_of_month
+
+ # Returns a new Time representing the end of the month (last day of the month, 0:00)
+ def end_of_month
+ #self - ((self.mday-1).days + self.seconds_since_midnight)
+ last_day = ::Time.days_in_month(month, year)
+ change(:day => last_day, :hour => 23, :min => 59, :sec => 59, :usec => 0)
+ end
+ alias :at_end_of_month :end_of_month
+
+ # Returns a new Time representing the start of the quarter (1st of january, april, july, october, 0:00)
+ def beginning_of_quarter
+ beginning_of_month.change(:month => [10, 7, 4, 1].detect { |m| m <= month })
+ end
+ alias :at_beginning_of_quarter :beginning_of_quarter
+
+ # Returns a new Time representing the end of the quarter (last day of march, june, september, december, 23:59:59)
+ def end_of_quarter
+ beginning_of_month.change(:month => [3, 6, 9, 12].detect { |m| m >= month }).end_of_month
+ end
+ alias :at_end_of_quarter :end_of_quarter
+
+ # 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)
+ end
+ alias :at_beginning_of_year :beginning_of_year
+
+ # Returns a new Time representing the end of the year (31st of december, 23:59:59)
+ def end_of_year
+ change(:month => 12, :day => 31, :hour => 23, :min => 59, :sec => 59)
+ end
+ alias :at_end_of_year :end_of_year
+
+ # Convenience method which returns a new Time representing the time 1 day ago
+ def yesterday
+ advance(:days => -1)
+ end
+
+ # Convenience method which returns a new Time representing the time 1 day since the instance time
+ def tomorrow
+ advance(:days => 1)
+ end
+
+ def plus_with_duration(other) #:nodoc:
+ if ActiveSupport::Duration === other
+ other.since(self)
+ else
+ plus_without_duration(other)
+ end
+ end
+ alias_method :plus_without_duration, :+
+ alias_method :+, :plus_with_duration
+
+ def minus_with_duration(other) #:nodoc:
+ if ActiveSupport::Duration === other
+ other.until(self)
+ else
+ minus_without_duration(other)
+ end
+ end
+ alias_method :minus_without_duration, :-
+ alias_method :-, :minus_with_duration
+
+ # Time#- can also be used to determine the number of seconds between two Time instances.
+ # We're layering on additional behavior so that ActiveSupport::TimeWithZone instances
+ # are coerced into values that Time#- will recognize
+ def minus_with_coercion(other)
+ other = other.comparable_time if other.respond_to?(:comparable_time)
+ minus_without_coercion(other)
+ end
+ alias_method :minus_without_coercion, :-
+ alias_method :-, :minus_with_coercion
+
+ # Layers additional behavior on Time#<=> so that DateTime and ActiveSupport::TimeWithZone instances
+ # can be chronologically compared with a Time
+ def compare_with_coercion(other)
+ # if other is an ActiveSupport::TimeWithZone, coerce a Time instance from it so we can do <=> comparison
+ other = other.comparable_time if other.respond_to?(:comparable_time)
+ if other.acts_like?(:date)
+ # other is a Date/DateTime, so coerce self #to_datetime and hand off to DateTime#<=>
+ to_datetime.compare_without_coercion(other)
+ else
+ compare_without_coercion(other)
end
end
+ alias_method :compare_without_coercion, :<=>
+ alias_method :<=>, :compare_with_coercion
end
diff --git a/activesupport/lib/active_support/core_ext/time/conversions.rb b/activesupport/lib/active_support/core_ext/time/conversions.rb
index e6f9134661..18261e139f 100644
--- a/activesupport/lib/active_support/core_ext/time/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/time/conversions.rb
@@ -1,90 +1,84 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Time #:nodoc:
- # Converting times to formatted strings, dates, and datetimes.
- module Conversions
- DATE_FORMATS = {
- :db => "%Y-%m-%d %H:%M:%S",
- :number => "%Y%m%d%H%M%S",
- :time => "%H:%M",
- :short => "%d %b %H:%M",
- :long => "%B %d, %Y %H:%M",
- :long_ordinal => lambda { |time| time.strftime("%B #{time.day.ordinalize}, %Y %H:%M") },
- :rfc822 => lambda { |time| time.strftime("%a, %d %b %Y %H:%M:%S #{time.formatted_offset(false)}") }
- }
+require 'active_support/inflector'
+require 'active_support/values/time_zone'
- def self.included(base) #:nodoc:
- base.class_eval do
- alias_method :to_default_s, :to_s
- alias_method :to_s, :to_formatted_s
- end
- end
+class Time
+ DATE_FORMATS = {
+ :db => "%Y-%m-%d %H:%M:%S",
+ :number => "%Y%m%d%H%M%S",
+ :time => "%H:%M",
+ :short => "%d %b %H:%M",
+ :long => "%B %d, %Y %H:%M",
+ :long_ordinal => lambda { |time| time.strftime("%B #{ActiveSupport::Inflector.ordinalize(time.day)}, %Y %H:%M") },
+ :rfc822 => lambda { |time| time.strftime("%a, %d %b %Y %H:%M:%S #{time.formatted_offset(false)}") }
+ }
- # Converts to a formatted string. See DATE_FORMATS for builtin formats.
- #
- # This method is aliased to <tt>to_s</tt>.
- #
- # time = Time.now # => Thu Jan 18 06:10:17 CST 2007
- #
- # time.to_formatted_s(:time) # => "06:10:17"
- # time.to_s(:time) # => "06:10:17"
- #
- # time.to_formatted_s(:db) # => "2007-01-18 06:10:17"
- # time.to_formatted_s(:number) # => "20070118061017"
- # time.to_formatted_s(:short) # => "18 Jan 06:10"
- # time.to_formatted_s(:long) # => "January 18, 2007 06:10"
- # time.to_formatted_s(:long_ordinal) # => "January 18th, 2007 06:10"
- # time.to_formatted_s(:rfc822) # => "Thu, 18 Jan 2007 06:10:17 -0600"
- #
- # == Adding your own time formats to +to_formatted_s+
- # You can add your own formats to the Time::DATE_FORMATS hash.
- # Use the format name as the hash key and either a strftime string
- # or Proc instance that takes a time argument as the value.
- #
- # # config/initializers/time_formats.rb
- # Time::DATE_FORMATS[:month_and_year] = "%B %Y"
- # Time::DATE_FORMATS[:short_ordinal] = lambda { |time| time.strftime("%B #{time.day.ordinalize}") }
- def to_formatted_s(format = :default)
- return to_default_s unless formatter = DATE_FORMATS[format]
- formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
- end
-
- # Returns the UTC offset as an +HH:MM formatted string.
- #
- # Time.local(2000).formatted_offset # => "-06:00"
- # Time.local(2000).formatted_offset(false) # => "-0600"
- def formatted_offset(colon = true, alternate_utc_string = nil)
- utc? && alternate_utc_string || utc_offset.to_utc_offset_s(colon)
- end
+ # Converts to a formatted string. See DATE_FORMATS for builtin formats.
+ #
+ # This method is aliased to <tt>to_s</tt>.
+ #
+ # time = Time.now # => Thu Jan 18 06:10:17 CST 2007
+ #
+ # time.to_formatted_s(:time) # => "06:10:17"
+ # time.to_s(:time) # => "06:10:17"
+ #
+ # time.to_formatted_s(:db) # => "2007-01-18 06:10:17"
+ # time.to_formatted_s(:number) # => "20070118061017"
+ # time.to_formatted_s(:short) # => "18 Jan 06:10"
+ # time.to_formatted_s(:long) # => "January 18, 2007 06:10"
+ # time.to_formatted_s(:long_ordinal) # => "January 18th, 2007 06:10"
+ # time.to_formatted_s(:rfc822) # => "Thu, 18 Jan 2007 06:10:17 -0600"
+ #
+ # == Adding your own time formats to +to_formatted_s+
+ # You can add your own formats to the Time::DATE_FORMATS hash.
+ # Use the format name as the hash key and either a strftime string
+ # or Proc instance that takes a time argument as the value.
+ #
+ # # config/initializers/time_formats.rb
+ # Time::DATE_FORMATS[:month_and_year] = "%B %Y"
+ # Time::DATE_FORMATS[:short_ordinal] = lambda { |time| time.strftime("%B #{time.day.ordinalize}") }
+ def to_formatted_s(format = :default)
+ if formatter = DATE_FORMATS[format]
+ formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
+ else
+ to_default_s
+ end
+ end
+ alias_method :to_default_s, :to_s
+ alias_method :to_s, :to_formatted_s
+
+ # Returns the UTC offset as an +HH:MM formatted string.
+ #
+ # Time.local(2000).formatted_offset # => "-06:00"
+ # Time.local(2000).formatted_offset(false) # => "-0600"
+ def formatted_offset(colon = true, alternate_utc_string = nil)
+ utc? && alternate_utc_string || ActiveSupport::TimeZone.seconds_to_utc_offset(utc_offset, colon)
+ end
- # Converts a Time object to a Date, dropping hour, minute, and second precision.
- #
- # my_time = Time.now # => Mon Nov 12 22:59:51 -0500 2007
- # my_time.to_date # => Mon, 12 Nov 2007
- #
- # your_time = Time.parse("1/13/2009 1:13:03 P.M.") # => Tue Jan 13 13:13:03 -0500 2009
- # your_time.to_date # => Tue, 13 Jan 2009
- def to_date
- ::Date.new(year, month, day)
- end
+ # Converts a Time object to a Date, dropping hour, minute, and second precision.
+ #
+ # my_time = Time.now # => Mon Nov 12 22:59:51 -0500 2007
+ # my_time.to_date # => Mon, 12 Nov 2007
+ #
+ # your_time = Time.parse("1/13/2009 1:13:03 P.M.") # => Tue Jan 13 13:13:03 -0500 2009
+ # your_time.to_date # => Tue, 13 Jan 2009
+ def to_date
+ ::Date.new(year, month, day)
+ end
- # A method to keep Time, Date and DateTime instances interchangeable on conversions.
- # In this case, it simply returns +self+.
- def to_time
- self
- end
+ # A method to keep Time, Date and DateTime instances interchangeable on conversions.
+ # In this case, it simply returns +self+.
+ def to_time
+ self
+ end
- # Converts a Time instance to a Ruby DateTime instance, preserving UTC offset.
- #
- # my_time = Time.now # => Mon Nov 12 23:04:21 -0500 2007
- # my_time.to_datetime # => Mon, 12 Nov 2007 23:04:21 -0500
- #
- # your_time = Time.parse("1/13/2009 1:13:03 P.M.") # => Tue Jan 13 13:13:03 -0500 2009
- # your_time.to_datetime # => Tue, 13 Jan 2009 13:13:03 -0500
- def to_datetime
- ::DateTime.civil(year, month, day, hour, min, sec, Rational(utc_offset, 86400))
- end
- end
- end
+ # Converts a Time instance to a Ruby DateTime instance, preserving UTC offset.
+ #
+ # my_time = Time.now # => Mon Nov 12 23:04:21 -0500 2007
+ # my_time.to_datetime # => Mon, 12 Nov 2007 23:04:21 -0500
+ #
+ # your_time = Time.parse("1/13/2009 1:13:03 P.M.") # => Tue Jan 13 13:13:03 -0500 2009
+ # your_time.to_datetime # => Tue, 13 Jan 2009 13:13:03 -0500
+ def to_datetime
+ ::DateTime.civil(year, month, day, hour, min, sec, Rational(utc_offset, 86400))
end
end
diff --git a/activesupport/lib/active_support/core_ext/time/marshal_with_utc_flag.rb b/activesupport/lib/active_support/core_ext/time/marshal_with_utc_flag.rb
new file mode 100644
index 0000000000..a1c8ece1d7
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/time/marshal_with_utc_flag.rb
@@ -0,0 +1,22 @@
+# Pre-1.9 versions of Ruby have a bug with marshaling Time instances, where utc instances are
+# unmarshaled in the local zone, instead of utc. We're layering behavior on the _dump and _load
+# methods so that utc instances can be flagged on dump, and coerced back to utc on load.
+if RUBY_VERSION < '1.9'
+ class Time
+ class << self
+ alias_method :_original_load, :_load
+ def _load(marshaled_time)
+ time = _original_load(marshaled_time)
+ utc = time.instance_variable_get('@marshal_with_utc_coercion')
+ utc ? time.utc : time
+ end
+ end
+
+ alias_method :_original_dump, :_dump
+ def _dump(*args)
+ obj = frozen? ? dup : self
+ obj.instance_variable_set('@marshal_with_utc_coercion', utc?)
+ obj._original_dump(*args)
+ end
+ end
+end
diff --git a/activesupport/lib/active_support/core_ext/time/publicize_conversion_methods.rb b/activesupport/lib/active_support/core_ext/time/publicize_conversion_methods.rb
new file mode 100644
index 0000000000..e1878d3c20
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/time/publicize_conversion_methods.rb
@@ -0,0 +1,10 @@
+require 'date'
+
+class Time
+ # Ruby 1.8-cvs and early 1.9 series define private Time#to_date
+ %w(to_date to_datetime).each do |method|
+ if private_instance_methods.include?(method) || private_instance_methods.include?(method.to_sym)
+ public method
+ end
+ end
+end
diff --git a/activesupport/lib/active_support/core_ext/time/zones.rb b/activesupport/lib/active_support/core_ext/time/zones.rb
index 9d8eb73908..adc9fe3824 100644
--- a/activesupport/lib/active_support/core_ext/time/zones.rb
+++ b/activesupport/lib/active_support/core_ext/time/zones.rb
@@ -1,86 +1,78 @@
-module ActiveSupport #:nodoc:
- module CoreExtensions #:nodoc:
- module Time #:nodoc:
- module Zones
- def self.included(base) #:nodoc:
- base.extend(ClassMethods) if base == ::Time # i.e., don't include class methods in DateTime
- end
-
- module ClassMethods
- attr_accessor :zone_default
-
- # Returns the TimeZone for the current request, if this has been set (via Time.zone=).
- # If <tt>Time.zone</tt> has not been set for the current request, returns the TimeZone specified in <tt>config.time_zone</tt>.
- def zone
- Thread.current[:time_zone] || zone_default
- end
+require 'active_support/time_with_zone'
+
+class Time
+ class << self
+ attr_accessor :zone_default
+
+ # Returns the TimeZone for the current request, if this has been set (via Time.zone=).
+ # If <tt>Time.zone</tt> has not been set for the current request, returns the TimeZone specified in <tt>config.time_zone</tt>.
+ def zone
+ Thread.current[:time_zone] || zone_default
+ end
- # Sets <tt>Time.zone</tt> to a TimeZone object for the current request/thread.
- #
- # This method accepts any of the following:
- #
- # * A Rails TimeZone object.
- # * An identifier for a Rails TimeZone object (e.g., "Eastern Time (US & Canada)", <tt>-5.hours</tt>).
- # * A TZInfo::Timezone object.
- # * An identifier for a TZInfo::Timezone object (e.g., "America/New_York").
- #
- # Here's an example of how you might set <tt>Time.zone</tt> on a per request basis -- <tt>current_user.time_zone</tt>
- # just needs to return a string identifying the user's preferred TimeZone:
- #
- # class ApplicationController < ActionController::Base
- # before_filter :set_time_zone
- #
- # def set_time_zone
- # Time.zone = current_user.time_zone
- # end
- # end
- def zone=(time_zone)
- Thread.current[:time_zone] = get_zone(time_zone)
- end
-
- # Allows override of <tt>Time.zone</tt> locally inside supplied block; resets <tt>Time.zone</tt> to existing value when done.
- def use_zone(time_zone)
- old_zone, ::Time.zone = ::Time.zone, get_zone(time_zone)
- yield
- ensure
- ::Time.zone = old_zone
- end
-
- # Returns <tt>Time.zone.now</tt> when <tt>config.time_zone</tt> is set, otherwise just returns <tt>Time.now</tt>.
- def current
- ::Time.zone_default ? ::Time.zone.now : ::Time.now
- end
-
- private
- def get_zone(time_zone)
- return time_zone if time_zone.nil? || time_zone.is_a?(TimeZone)
- # lookup timezone based on identifier (unless we've been passed a TZInfo::Timezone)
- unless time_zone.respond_to?(:period_for_local)
- time_zone = TimeZone[time_zone] || TZInfo::Timezone.get(time_zone) rescue nil
- end
- # Return if a TimeZone instance, or wrap in a TimeZone instance if a TZInfo::Timezone
- if time_zone
- time_zone.is_a?(TimeZone) ? time_zone : TimeZone.create(time_zone.name, nil, time_zone)
- end
- end
+ # Sets <tt>Time.zone</tt> to a TimeZone object for the current request/thread.
+ #
+ # This method accepts any of the following:
+ #
+ # * A Rails TimeZone object.
+ # * An identifier for a Rails TimeZone object (e.g., "Eastern Time (US & Canada)", <tt>-5.hours</tt>).
+ # * A TZInfo::Timezone object.
+ # * An identifier for a TZInfo::Timezone object (e.g., "America/New_York").
+ #
+ # Here's an example of how you might set <tt>Time.zone</tt> on a per request basis -- <tt>current_user.time_zone</tt>
+ # just needs to return a string identifying the user's preferred TimeZone:
+ #
+ # class ApplicationController < ActionController::Base
+ # before_filter :set_time_zone
+ #
+ # def set_time_zone
+ # Time.zone = current_user.time_zone
+ # end
+ # end
+ def zone=(time_zone)
+ Thread.current[:time_zone] = get_zone(time_zone)
+ end
+
+ # Allows override of <tt>Time.zone</tt> locally inside supplied block; resets <tt>Time.zone</tt> to existing value when done.
+ def use_zone(time_zone)
+ old_zone, ::Time.zone = ::Time.zone, get_zone(time_zone)
+ yield
+ ensure
+ ::Time.zone = old_zone
+ end
+
+ # Returns <tt>Time.zone.now</tt> when <tt>config.time_zone</tt> is set, otherwise just returns <tt>Time.now</tt>.
+ def current
+ ::Time.zone_default ? ::Time.zone.now : ::Time.now
+ end
+
+ private
+ def get_zone(time_zone)
+ return time_zone if time_zone.nil? || time_zone.is_a?(ActiveSupport::TimeZone)
+ # lookup timezone based on identifier (unless we've been passed a TZInfo::Timezone)
+ unless time_zone.respond_to?(:period_for_local)
+ time_zone = ActiveSupport::TimeZone[time_zone] || TZInfo::Timezone.get(time_zone) rescue nil
end
-
- # Returns the simultaneous time in <tt>Time.zone</tt>.
- #
- # Time.zone = 'Hawaii' # => 'Hawaii'
- # Time.utc(2000).in_time_zone # => Fri, 31 Dec 1999 14:00:00 HST -10:00
- #
- # This method is similar to Time#localtime, except that it uses <tt>Time.zone</tt> as the local zone
- # instead of the operating system's time zone.
- #
- # You can also pass in a TimeZone instance or string that identifies a TimeZone as an argument,
- # and the conversion will be based on that zone instead of <tt>Time.zone</tt>.
- #
- # Time.utc(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00
- def in_time_zone(zone = ::Time.zone)
- ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.__send__(:get_zone, zone))
+ # Return if a TimeZone instance, or wrap in a TimeZone instance if a TZInfo::Timezone
+ if time_zone
+ time_zone.is_a?(ActiveSupport::TimeZone) ? time_zone : ActiveSupport::TimeZone.create(time_zone.name, nil, time_zone)
end
end
- end
end
-end \ No newline at end of file
+
+ # Returns the simultaneous time in <tt>Time.zone</tt>.
+ #
+ # Time.zone = 'Hawaii' # => 'Hawaii'
+ # Time.utc(2000).in_time_zone # => Fri, 31 Dec 1999 14:00:00 HST -10:00
+ #
+ # This method is similar to Time#localtime, except that it uses <tt>Time.zone</tt> as the local zone
+ # instead of the operating system's time zone.
+ #
+ # You can also pass in a TimeZone instance or string that identifies a TimeZone as an argument,
+ # and the conversion will be based on that zone instead of <tt>Time.zone</tt>.
+ #
+ # Time.utc(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00
+ def in_time_zone(zone = ::Time.zone)
+ ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.__send__(:get_zone, zone))
+ end
+end
diff --git a/activesupport/lib/active_support/core_ext/util.rb b/activesupport/lib/active_support/core_ext/util.rb
new file mode 100644
index 0000000000..fc4666638c
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/util.rb
@@ -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
diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb
index 2badad5f5f..41b7e00c0c 100644
--- a/activesupport/lib/active_support/dependencies.rb
+++ b/activesupport/lib/active_support/dependencies.rb
@@ -1,3 +1,11 @@
+require 'set'
+require 'active_support/inflector'
+require 'active_support/core_ext/name_error'
+require 'active_support/core_ext/object/blank'
+require 'active_support/core_ext/module/aliasing'
+require 'active_support/core_ext/module/attribute_accessors'
+require 'active_support/core_ext/module/introspection'
+
module ActiveSupport #:nodoc:
module Dependencies #:nodoc:
extend self
@@ -16,7 +24,7 @@ module ActiveSupport #:nodoc:
# Should we load files or require them?
mattr_accessor :mechanism
- self.mechanism = :load
+ self.mechanism = ENV['NO_RELOAD'] ? :require : :load
# The set of directories from which we may automatically load files. Files
# under these directories will be reloaded on each request in development mode,
@@ -328,7 +336,7 @@ module ActiveSupport #:nodoc:
# Search for a file in load_paths matching the provided suffix.
def search_for_file(path_suffix)
- path_suffix = path_suffix + '.rb' unless path_suffix.ends_with? '.rb'
+ path_suffix = "#{path_suffix}.rb" unless path_suffix =~ /\.rb\Z/
load_paths.each do |root|
path = File.join(root, path_suffix)
return path if File.file? path
@@ -410,7 +418,7 @@ module ActiveSupport #:nodoc:
# If we have an anonymous module, all we can do is attempt to load from Object.
from_mod = Object if from_mod.name.blank?
- unless qualified_const_defined?(from_mod.name) && from_mod.name.constantize.object_id == from_mod.object_id
+ unless qualified_const_defined?(from_mod.name) && Inflector.constantize(from_mod.name).object_id == from_mod.object_id
raise ArgumentError, "A copy of #{from_mod} has been removed from the module tree but is still active!"
end
@@ -501,7 +509,7 @@ module ActiveSupport #:nodoc:
# Handle the case where the module has yet to be defined.
initial_constants = if qualified_const_defined?(mod_name)
- mod_name.constantize.local_constant_names
+ Inflector.constantize(mod_name).local_constant_names
else
[]
end
@@ -526,7 +534,7 @@ module ActiveSupport #:nodoc:
# Module still doesn't exist? Treat it as if it has no constants.
next [] unless qualified_const_defined?(mod_name)
- mod = mod_name.constantize
+ mod = Inflector.constantize(mod_name)
next [] unless mod.is_a? Module
new_constants = mod.local_constant_names - prior_constants
@@ -596,7 +604,7 @@ module ActiveSupport #:nodoc:
if names.size == 1 # It's under Object
parent = Object
else
- parent = (names[0..-2] * '::').constantize
+ parent = Inflector.constantize(names[0..-2] * '::')
end
log "removing constant #{const}"
diff --git a/activesupport/lib/active_support/deprecation.rb b/activesupport/lib/active_support/deprecation.rb
index 202b46ce7a..e1b8211d68 100644
--- a/activesupport/lib/active_support/deprecation.rb
+++ b/activesupport/lib/active_support/deprecation.rb
@@ -1,196 +1,18 @@
-require 'yaml'
+require 'active_support/deprecation/behaviors'
+require 'active_support/deprecation/reporting'
+require 'active_support/deprecation/method_wrappers'
+require 'active_support/deprecation/proxy_wrappers'
module ActiveSupport
module Deprecation #:nodoc:
- mattr_accessor :debug
- self.debug = false
-
- # Choose the default warn behavior according to RAILS_ENV.
- # Ignore deprecation warnings in production.
- DEFAULT_BEHAVIORS = {
- 'test' => Proc.new { |message, callstack|
- $stderr.puts(message)
- $stderr.puts callstack.join("\n ") if debug
- },
- 'development' => Proc.new { |message, callstack|
- logger = defined?(Rails) ? Rails.logger : Logger.new($stderr)
- logger.warn message
- logger.debug callstack.join("\n ") if debug
- }
- }
-
class << self
- def warn(message = nil, callstack = caller)
- behavior.call(deprecation_message(callstack, message), callstack) if behavior && !silenced?
- end
-
- def default_behavior
- if defined?(RAILS_ENV)
- DEFAULT_BEHAVIORS[RAILS_ENV.to_s]
- else
- DEFAULT_BEHAVIORS['test']
- end
- end
-
- # Have deprecations been silenced?
- def silenced?
- @silenced = false unless defined?(@silenced)
- @silenced
- end
-
- # Silence deprecation warnings within the block.
- def silence
- old_silenced, @silenced = @silenced, true
- yield
- ensure
- @silenced = old_silenced
- end
-
- attr_writer :silenced
-
-
- private
- def deprecation_message(callstack, message = nil)
- message ||= "You are using deprecated behavior which will be removed from the next major or minor release."
- "DEPRECATION WARNING: #{message}. #{deprecation_caller_message(callstack)}"
- end
-
- def deprecation_caller_message(callstack)
- file, line, method = extract_callstack(callstack)
- if file
- if line && method
- "(called from #{method} at #{file}:#{line})"
- else
- "(called from #{file}:#{line})"
- end
- end
- end
-
- def extract_callstack(callstack)
- if md = callstack.first.match(/^(.+?):(\d+)(?::in `(.*?)')?/)
- md.captures
- else
- callstack.first
- end
- end
+ # The version the deprecated behavior will be removed, by default.
+ attr_accessor :deprecation_horizon
end
+ self.deprecation_horizon = '3.0'
- # Behavior is a block that takes a message argument.
- mattr_accessor :behavior
- self.behavior = default_behavior
-
- # Warnings are not silenced by default.
+ # By default, warnings are not silenced and debugging is off.
self.silenced = false
-
- module ClassMethods #:nodoc:
- # Declare that a method has been deprecated.
- def deprecate(*method_names)
- options = method_names.extract_options!
- method_names = method_names + options.keys
- method_names.each do |method_name|
- alias_method_chain(method_name, :deprecation) do |target, punctuation|
- class_eval(<<-EOS, __FILE__, __LINE__ + 1)
- def #{target}_with_deprecation#{punctuation}(*args, &block) # def generate_secret_with_deprecation(*args, &block)
- ::ActiveSupport::Deprecation.warn( # ::ActiveSupport::Deprecation.warn(
- self.class.deprecated_method_warning( # self.class.deprecated_method_warning(
- :#{method_name}, # :generate_secret,
- #{options[method_name].inspect}), # "You should use ActiveSupport::SecureRandom.hex(64)"),
- caller # caller
- ) # )
- #{target}_without_deprecation#{punctuation}(*args, &block) # generate_secret_without_deprecation(*args, &block)
- end # end
- EOS
- end
- end
- end
-
- def deprecated_method_warning(method_name, message=nil)
- warning = "#{method_name} is deprecated and will be removed from Rails #{deprecation_horizon}"
- case message
- when Symbol then "#{warning} (use #{message} instead)"
- when String then "#{warning} (#{message})"
- else warning
- end
- end
-
- def deprecation_horizon
- '2.3'
- end
- end
-
- class DeprecationProxy #:nodoc:
- silence_warnings do
- instance_methods.each { |m| undef_method m unless m =~ /^__/ }
- end
-
- # Don't give a deprecation warning on inspect since test/unit and error
- # logs rely on it for diagnostics.
- def inspect
- target.inspect
- end
-
- private
- def method_missing(called, *args, &block)
- warn caller, called, args
- target.__send__(called, *args, &block)
- end
- end
-
- class DeprecatedObjectProxy < DeprecationProxy
- def initialize(object, message)
- @object = object
- @message = message
- end
-
- private
- def target
- @object
- end
-
- def warn(callstack, called, args)
- ActiveSupport::Deprecation.warn(@message, callstack)
- end
- end
-
- # Stand-in for <tt>@request</tt>, <tt>@attributes</tt>, <tt>@params</tt>, etc.
- # which emits deprecation warnings on any method call (except +inspect+).
- class DeprecatedInstanceVariableProxy < DeprecationProxy #:nodoc:
- def initialize(instance, method, var = "@#{method}")
- @instance, @method, @var = instance, method, var
- end
-
- private
- def target
- @instance.__send__(@method)
- end
-
- def warn(callstack, called, args)
- ActiveSupport::Deprecation.warn("#{@var} is deprecated! Call #{@method}.#{called} instead of #{@var}.#{called}. Args: #{args.inspect}", callstack)
- end
- end
-
- class DeprecatedConstantProxy < DeprecationProxy #:nodoc:
- def initialize(old_const, new_const)
- @old_const = old_const
- @new_const = new_const
- end
-
- def class
- target.class
- end
-
- private
- def target
- @new_const.to_s.constantize
- end
-
- def warn(callstack, called, args)
- ActiveSupport::Deprecation.warn("#{@old_const} is deprecated! Use #{@new_const} instead.", callstack)
- end
- end
+ self.debug = false
end
end
-
-class Module
- include ActiveSupport::Deprecation::ClassMethods
-end
diff --git a/activesupport/lib/active_support/deprecation/behaviors.rb b/activesupport/lib/active_support/deprecation/behaviors.rb
new file mode 100644
index 0000000000..c531a1aa58
--- /dev/null
+++ b/activesupport/lib/active_support/deprecation/behaviors.rb
@@ -0,0 +1,32 @@
+module ActiveSupport
+ module Deprecation
+ class << self
+ # Behavior is a block that takes a message argument.
+ attr_writer :behavior
+
+ # Whether to print a backtrace along with the warning.
+ attr_accessor :debug
+
+ def behavior
+ @behavior ||= default_behavior
+ end
+
+ def default_behavior
+ Deprecation::DEFAULT_BEHAVIORS[defined?(Rails) ? Rails.env.to_s : 'test']
+ end
+ end
+
+ # Default warning behaviors per Rails.env. Ignored in production.
+ DEFAULT_BEHAVIORS = {
+ 'test' => Proc.new { |message, callstack|
+ $stderr.puts(message)
+ $stderr.puts callstack.join("\n ") if debug
+ },
+ 'development' => Proc.new { |message, callstack|
+ logger = defined?(Rails) ? Rails.logger : Logger.new($stderr)
+ logger.warn message
+ logger.debug callstack.join("\n ") if debug
+ }
+ }
+ end
+end
diff --git a/activesupport/lib/active_support/deprecation/method_wrappers.rb b/activesupport/lib/active_support/deprecation/method_wrappers.rb
new file mode 100644
index 0000000000..b35d4daf9a
--- /dev/null
+++ b/activesupport/lib/active_support/deprecation/method_wrappers.rb
@@ -0,0 +1,27 @@
+require 'active_support/core_ext/module/deprecation'
+
+module ActiveSupport
+ class << Deprecation
+ # Declare that a method has been deprecated.
+ def deprecate_methods(target_module, *method_names)
+ options = method_names.extract_options!
+ method_names += options.keys
+
+ method_names.each do |method_name|
+ target_module.alias_method_chain(method_name, :deprecation) do |target, punctuation|
+ target_module.module_eval(<<-end_eval, __FILE__, __LINE__ + 1)
+ def #{target}_with_deprecation#{punctuation}(*args, &block) # def generate_secret_with_deprecation(*args, &block)
+ ::ActiveSupport::Deprecation.warn( # ::ActiveSupport::Deprecation.warn(
+ ::ActiveSupport::Deprecation.deprecated_method_warning( # ::ActiveSupport::Deprecation.deprecated_method_warning(
+ :#{method_name}, # :generate_secret,
+ #{options[method_name].inspect}), # "You should use ActiveSupport::SecureRandom.hex(64)"),
+ caller # caller
+ ) # )
+ #{target}_without_deprecation#{punctuation}(*args, &block) # generate_secret_without_deprecation(*args, &block)
+ end # end
+ end_eval
+ end
+ end
+ end
+ end
+end
diff --git a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
new file mode 100644
index 0000000000..1c268d0d9c
--- /dev/null
+++ b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
@@ -0,0 +1,72 @@
+module ActiveSupport
+ module Deprecation
+ class DeprecationProxy #:nodoc:
+ instance_methods.each { |m| undef_method m unless m =~ /^__/ }
+
+ # Don't give a deprecation warning on inspect since test/unit and error
+ # logs rely on it for diagnostics.
+ def inspect
+ target.inspect
+ end
+
+ private
+ def method_missing(called, *args, &block)
+ warn caller, called, args
+ target.__send__(called, *args, &block)
+ end
+ end
+
+ class DeprecatedObjectProxy < DeprecationProxy #:nodoc:
+ def initialize(object, message)
+ @object = object
+ @message = message
+ end
+
+ private
+ def target
+ @object
+ end
+
+ def warn(callstack, called, args)
+ ActiveSupport::Deprecation.warn(@message, callstack)
+ end
+ end
+
+ # Stand-in for <tt>@request</tt>, <tt>@attributes</tt>, <tt>@params</tt>, etc.
+ # which emits deprecation warnings on any method call (except +inspect+).
+ class DeprecatedInstanceVariableProxy < DeprecationProxy #:nodoc:
+ def initialize(instance, method, var = "@#{method}")
+ @instance, @method, @var = instance, method, var
+ end
+
+ private
+ def target
+ @instance.__send__(@method)
+ end
+
+ def warn(callstack, called, args)
+ ActiveSupport::Deprecation.warn("#{@var} is deprecated! Call #{@method}.#{called} instead of #{@var}.#{called}. Args: #{args.inspect}", callstack)
+ end
+ end
+
+ class DeprecatedConstantProxy < DeprecationProxy #:nodoc:
+ def initialize(old_const, new_const)
+ @old_const = old_const
+ @new_const = new_const
+ end
+
+ def class
+ target.class
+ end
+
+ private
+ def target
+ @new_const.to_s.constantize
+ end
+
+ def warn(callstack, called, args)
+ ActiveSupport::Deprecation.warn("#{@old_const} is deprecated! Use #{@new_const} instead.", callstack)
+ end
+ end
+ end
+end
diff --git a/activesupport/lib/active_support/deprecation/reporting.rb b/activesupport/lib/active_support/deprecation/reporting.rb
new file mode 100644
index 0000000000..fcb05ad8d9
--- /dev/null
+++ b/activesupport/lib/active_support/deprecation/reporting.rb
@@ -0,0 +1,55 @@
+module ActiveSupport
+ module Deprecation
+ class << self
+ attr_accessor :silenced
+
+ def warn(message = nil, callstack = caller)
+ if behavior && !silenced
+ behavior.call(deprecation_message(callstack, message), callstack)
+ end
+ end
+
+ # Silence deprecation warnings within the block.
+ def silence
+ old_silenced, @silenced = @silenced, true
+ yield
+ ensure
+ @silenced = old_silenced
+ end
+
+ def deprecated_method_warning(method_name, message = nil)
+ warning = "#{method_name} is deprecated and will be removed from Rails #{deprecation_horizon}"
+ case message
+ when Symbol then "#{warning} (use #{message} instead)"
+ when String then "#{warning} (#{message})"
+ else warning
+ end
+ end
+
+ private
+ def deprecation_message(callstack, message = nil)
+ message ||= "You are using deprecated behavior which will be removed from the next major or minor release."
+ "DEPRECATION WARNING: #{message}. #{deprecation_caller_message(callstack)}"
+ end
+
+ def deprecation_caller_message(callstack)
+ file, line, method = extract_callstack(callstack)
+ if file
+ if line && method
+ "(called from #{method} at #{file}:#{line})"
+ else
+ "(called from #{file}:#{line})"
+ end
+ end
+ end
+
+ def extract_callstack(callstack)
+ if md = callstack.first.match(/^(.+?):(\d+)(?::in `(.*?)')?/)
+ md.captures
+ else
+ callstack.first
+ end
+ end
+ end
+ end
+end
diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb
new file mode 100644
index 0000000000..61fc6475a0
--- /dev/null
+++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb
@@ -0,0 +1,133 @@
+# This class has dubious semantics and we only have it so that
+# people can write params[:key] instead of params['key']
+# and they get the same value for both keys.
+
+module ActiveSupport
+ class HashWithIndifferentAccess < Hash
+ def initialize(constructor = {})
+ if constructor.is_a?(Hash)
+ super()
+ update(constructor)
+ else
+ super(constructor)
+ end
+ end
+
+ def default(key = nil)
+ if key.is_a?(Symbol) && include?(key = key.to_s)
+ self[key]
+ else
+ super
+ end
+ end
+
+ alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
+ alias_method :regular_update, :update unless method_defined?(:regular_update)
+
+ # Assigns a new value to the hash:
+ #
+ # hash = HashWithIndifferentAccess.new
+ # hash[:key] = "value"
+ #
+ def []=(key, value)
+ regular_writer(convert_key(key), convert_value(value))
+ end
+
+ # Updates the instantized hash with values from the second:
+ #
+ # hash_1 = HashWithIndifferentAccess.new
+ # hash_1[:key] = "value"
+ #
+ # hash_2 = HashWithIndifferentAccess.new
+ # hash_2[:key] = "New Value!"
+ #
+ # 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
+ end
+
+ alias_method :merge!, :update
+
+ # Checks the hash for a key matching the argument passed in:
+ #
+ # hash = HashWithIndifferentAccess.new
+ # hash["key"] = "value"
+ # hash.key? :key # => true
+ # hash.key? "key" # => true
+ #
+ def key?(key)
+ super(convert_key(key))
+ end
+
+ alias_method :include?, :key?
+ alias_method :has_key?, :key?
+ alias_method :member?, :key?
+
+ # Fetches the value for the specified key, same as doing hash[key]
+ def fetch(key, *extras)
+ super(convert_key(key), *extras)
+ end
+
+ # Returns an array of the values at the specified indices:
+ #
+ # hash = HashWithIndifferentAccess.new
+ # hash[:a] = "x"
+ # hash[:b] = "y"
+ # hash.values_at("a", "b") # => ["x", "y"]
+ #
+ def values_at(*indices)
+ indices.collect {|key| self[convert_key(key)]}
+ end
+
+ # Returns an exact copy of the hash.
+ def dup
+ HashWithIndifferentAccess.new(self)
+ end
+
+ # Merges the instantized and the specified hashes together, giving precedence to the values from the second hash
+ # Does not overwrite the existing hash.
+ def merge(hash)
+ self.dup.update(hash)
+ end
+
+ # Performs the opposite of merge, with the keys and values from the first hash taking precedence over the second.
+ # This overloaded definition prevents returning a regular hash, if reverse_merge is called on a HashWithDifferentAccess.
+ def reverse_merge(other_hash)
+ super other_hash.with_indifferent_access
+ end
+
+ # Removes a specified key from the hash.
+ def delete(key)
+ super(convert_key(key))
+ end
+
+ def stringify_keys!; self end
+ def symbolize_keys!; self end
+ def to_options!; self end
+
+ # Convert to a Hash with String keys.
+ def to_hash
+ Hash.new(default).merge(self)
+ end
+
+ protected
+ def convert_key(key)
+ key.kind_of?(Symbol) ? key.to_s : key
+ end
+
+ def convert_value(value)
+ case value
+ when Hash
+ value.with_indifferent_access
+ when Array
+ value.collect { |e| e.is_a?(Hash) ? e.with_indifferent_access : e }
+ else
+ value
+ end
+ end
+ end
+end
+
+HashWithIndifferentAccess = ActiveSupport::HashWithIndifferentAccess
diff --git a/activesupport/lib/active_support/inflector.rb b/activesupport/lib/active_support/inflector.rb
index 3ed30bdf56..f14f6a6490 100644
--- a/activesupport/lib/active_support/inflector.rb
+++ b/activesupport/lib/active_support/inflector.rb
@@ -1,7 +1,8 @@
# encoding: utf-8
-require 'singleton'
require 'iconv'
+require 'active_support/core_ext/string/multibyte'
+
module ActiveSupport
# The Inflector transforms words from singular to plural, class names to table names, modularized class names to ones without,
# and class names to foreign keys. The default inflections for pluralization, singularization, and uncountable words are kept
@@ -30,7 +31,9 @@ module ActiveSupport
# pluralization and singularization rules that is runs. This guarantees that your rules run before any of the rules that may
# already have been loaded.
class Inflections
- include Singleton
+ def self.instance
+ @__instance__ ||= new
+ end
attr_reader :plurals, :singulars, :uncountables, :humans
diff --git a/activesupport/lib/active_support/json/decoding.rb b/activesupport/lib/active_support/json/decoding.rb
index 0e079341ff..c66500aa9c 100644
--- a/activesupport/lib/active_support/json/decoding.rb
+++ b/activesupport/lib/active_support/json/decoding.rb
@@ -1,5 +1,7 @@
-require 'yaml'
-require 'strscan'
+autoload :YAML, 'yaml' unless defined? YAML
+autoload :StringScanner, 'strscan' unless defined? StringScanner
+
+require 'active_support/core_ext/string/starts_ends_with'
module ActiveSupport
module JSON
@@ -45,7 +47,7 @@ module ActiveSupport
if marks.empty?
json.gsub(/\\([\\\/]|u[[:xdigit:]]{4})/) do
ustr = $1
- if ustr.starts_with?('u')
+ if ustr.start_with?('u')
[ustr[1..-1].to_i(16)].pack("U")
elsif ustr == '\\'
'\\\\'
@@ -61,10 +63,10 @@ module ActiveSupport
scanner.pos = left.succ
output << scanner.peek(right_pos[i] - scanner.pos + 1).gsub(/\\([\\\/]|u[[:xdigit:]]{4})/) do
ustr = $1
- if ustr.starts_with?('u')
+ if ustr.start_with?('u')
[ustr[1..-1].to_i(16)].pack("U")
elsif ustr == '\\'
- '\\\\'
+ '\\\\'
else
ustr
end
diff --git a/activesupport/lib/active_support/json/encoders/hash.rb b/activesupport/lib/active_support/json/encoders/hash.rb
index e38b4f3e16..d87b880743 100644
--- a/activesupport/lib/active_support/json/encoders/hash.rb
+++ b/activesupport/lib/active_support/json/encoders/hash.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/array/wrap'
+
class Hash
# Returns a JSON string representing the hash.
#
diff --git a/activesupport/lib/active_support/json/encoders/object.rb b/activesupport/lib/active_support/json/encoders/object.rb
index ca215d4964..0475967aee 100644
--- a/activesupport/lib/active_support/json/encoders/object.rb
+++ b/activesupport/lib/active_support/json/encoders/object.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/object/instance_variables'
+
class Object
# Dumps object in JSON (JavaScript Object Notation). See www.json.org for more info.
def to_json(options = {})
diff --git a/activesupport/lib/active_support/option_merger.rb b/activesupport/lib/active_support/option_merger.rb
index 63662b75c7..e55ffd12c3 100644
--- a/activesupport/lib/active_support/option_merger.rb
+++ b/activesupport/lib/active_support/option_merger.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/hash/deep_merge'
+
module ActiveSupport
class OptionMerger #:nodoc:
instance_methods.each do |method|
diff --git a/activesupport/lib/active_support/ordered_options.rb b/activesupport/lib/active_support/ordered_options.rb
index 642045186f..596a7b757d 100644
--- a/activesupport/lib/active_support/ordered_options.rb
+++ b/activesupport/lib/active_support/ordered_options.rb
@@ -1,5 +1,7 @@
+require 'active_support/ordered_hash'
+
module ActiveSupport #:nodoc:
- class OrderedOptions < OrderedHash #:nodoc:
+ class OrderedOptions < OrderedHash
def []=(key, value)
super(key.to_sym, value)
end
diff --git a/activesupport/lib/active_support/rescuable.rb b/activesupport/lib/active_support/rescuable.rb
index c27c4ddb1a..a7258c870a 100644
--- a/activesupport/lib/active_support/rescuable.rb
+++ b/activesupport/lib/active_support/rescuable.rb
@@ -1,3 +1,6 @@
+require 'active_support/core_ext/class/inheritable_attributes'
+require 'active_support/core_ext/proc'
+
module ActiveSupport
# Rescuable module adds support for easier exception handling.
module Rescuable
diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb
index 9068afef2e..69abb80721 100644
--- a/activesupport/lib/active_support/time_with_zone.rb
+++ b/activesupport/lib/active_support/time_with_zone.rb
@@ -1,4 +1,9 @@
-require 'tzinfo'
+require 'active_support/duration'
+require 'active_support/core_ext/numeric/time'
+require 'active_support/core_ext/integer/time'
+require 'active_support/core_ext/time/conversions'
+require 'active_support/core_ext/date/conversions'
+require 'active_support/core_ext/date_time/conversions'
module ActiveSupport
# A Time-like class that can represent a time in any time zone. Necessary because standard Ruby Time instances are
@@ -92,7 +97,7 @@ module ActiveSupport
alias_method :gmtoff, :utc_offset
def formatted_offset(colon = true, alternate_utc_string = nil)
- utc? && alternate_utc_string || utc_offset.to_utc_offset_s(colon)
+ utc? && alternate_utc_string || TimeZone.seconds_to_utc_offset(utc_offset, colon)
end
# Time uses +zone+ to display the time zone abbreviation, so we're duck-typing it.
@@ -153,8 +158,9 @@ module ActiveSupport
# <tt>:db</tt> format outputs time in UTC; all others output time in local.
# Uses TimeWithZone's +strftime+, so <tt>%Z</tt> and <tt>%z</tt> work correctly.
def to_s(format = :default)
- return utc.to_s(format) if format == :db
- if formatter = ::Time::DATE_FORMATS[format]
+ if format == :db
+ utc.to_s(format)
+ elsif formatter = ::Time::DATE_FORMATS[format]
formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
else
"#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}" # mimicking Ruby 1.9 Time#to_s format
diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb
index 836f469df7..e2d759aa50 100644
--- a/activesupport/lib/active_support/values/time_zone.rb
+++ b/activesupport/lib/active_support/values/time_zone.rb
@@ -1,3 +1,7 @@
+require 'active_support/core_ext/time'
+require 'active_support/core_ext/date'
+require 'active_support/core_ext/date_time'
+
# The TimeZone class serves as a wrapper around TZInfo::Timezone instances. It allows us to do the following:
#
# * Limit the set of zones provided by TZInfo to a meaningful subset of 142 zones.
@@ -170,6 +174,20 @@ module ActiveSupport
MAPPING.freeze
end
+ UTC_OFFSET_WITH_COLON = '%+03d:%02d'
+ UTC_OFFSET_WITHOUT_COLON = UTC_OFFSET_WITH_COLON.sub(':', '')
+
+ # Assumes self represents an offset from UTC in seconds (as returned from Time#utc_offset)
+ # and turns this into an +HH:MM formatted string. Example:
+ #
+ # TimeZone.seconds_to_utc_offset(-21_600) # => "-06:00"
+ def self.seconds_to_utc_offset(seconds, colon = true)
+ format = colon ? UTC_OFFSET_WITH_COLON : UTC_OFFSET_WITHOUT_COLON
+ hours = seconds / 3600
+ minutes = (seconds.abs % 3600) / 60
+ format % [hours, minutes]
+ end
+
include Comparable
attr_reader :name
@@ -190,7 +208,7 @@ module ActiveSupport
# Returns the offset of this time zone as a formatted string, of the
# format "+HH:MM".
def formatted_offset(colon=true, alternate_utc_string = nil)
- utc_offset == 0 && alternate_utc_string || utc_offset.to_utc_offset_s(colon)
+ utc_offset == 0 && alternate_utc_string || self.class.seconds_to_utc_offset(utc_offset, colon)
end
# Compare this time zone to the parameter. The two are comapred first on
@@ -345,14 +363,13 @@ module ActiveSupport
"Wellington" ],
[ 46_800, "Nuku'alofa" ]].
each do |offset, *places|
- places.each do |place|
+ places.sort.each do |place|
place.freeze
zone = new(place, offset)
ZONES << zone
ZONES_MAP[place] = zone
end
end
- ZONES.sort!
ZONES.freeze
ZONES_MAP.freeze
diff --git a/activesupport/lib/active_support/vendor.rb b/activesupport/lib/active_support/vendor.rb
index 28852e65c8..2be9b85c89 100644
--- a/activesupport/lib/active_support/vendor.rb
+++ b/activesupport/lib/active_support/vendor.rb
@@ -6,7 +6,6 @@ begin
rescue Gem::LoadError
$:.unshift "#{File.dirname(__FILE__)}/vendor/builder-2.1.2"
end
-require 'builder'
begin
gem 'memcache-client', '>= 1.6.5'
diff --git a/activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n.rb b/activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n.rb
index 76361bed90..1b49debc05 100755
--- a/activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n.rb
+++ b/activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n.rb
@@ -1,3 +1,4 @@
+#--
# Authors:: Matt Aimonetti (http://railsontherun.com/),
# Sven Fuchs (http://www.artweb-design.de),
# Joshua Harvey (http://www.workingwithrails.com/person/759-joshua-harvey),
@@ -5,10 +6,14 @@
# Stephan Soller (http://www.arkanis-development.de/)
# Copyright:: Copyright (c) 2008 The Ruby i18n Team
# License:: MIT
-require 'i18n/backend/simple'
-require 'i18n/exceptions'
+#++
module I18n
+ autoload :ArgumentError, 'i18n/exceptions'
+ module Backend
+ autoload :Simple, 'i18n/backend/simple'
+ end
+
@@backend = nil
@@load_path = nil
@@default_locale = :'en'
diff --git a/activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n/backend/simple.rb b/activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n/backend/simple.rb
index c09acd7d2d..c32cc76f34 100644
--- a/activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n/backend/simple.rb
+++ b/activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n/backend/simple.rb
@@ -1,4 +1,4 @@
-require 'yaml'
+require 'i18n/exceptions'
module I18n
module Backend
@@ -186,6 +186,7 @@ module I18n
# Loads a YAML translations file. The data must have locales as
# toplevel keys.
def load_yml(filename)
+ require 'yaml' unless defined? :YAML
YAML::load(IO.read(filename))
end
@@ -211,4 +212,4 @@ module I18n
end
end
end
-end \ No newline at end of file
+end
diff --git a/activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n/exceptions.rb b/activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n/exceptions.rb
index b5cea7acb4..6897055d6d 100644
--- a/activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n/exceptions.rb
+++ b/activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n/exceptions.rb
@@ -50,4 +50,4 @@ module I18n
super "can not load translations from #{filename}, the file type #{type} is not known"
end
end
-end \ No newline at end of file
+end
diff --git a/activesupport/lib/active_support/xml_mini/libxml.rb b/activesupport/lib/active_support/xml_mini/libxml.rb
index 3586b24a6b..370205409a 100644
--- a/activesupport/lib/active_support/xml_mini/libxml.rb
+++ b/activesupport/lib/active_support/xml_mini/libxml.rb
@@ -21,15 +21,15 @@ module ActiveSupport
end
end
-module LibXML
- module Conversions
- module Document
+module LibXML #:nodoc:
+ module Conversions #:nodoc:
+ module Document #:nodoc:
def to_hash
root.to_hash
end
end
- module Node
+ module Node #:nodoc:
CONTENT_ROOT = '__content__'
LIB_XML_LIMIT = 30000000 # Hardcoded LibXML limit
diff --git a/activesupport/lib/active_support/xml_mini/nokogiri.rb b/activesupport/lib/active_support/xml_mini/nokogiri.rb
index 10281584fc..8f9676e4f6 100644
--- a/activesupport/lib/active_support/xml_mini/nokogiri.rb
+++ b/activesupport/lib/active_support/xml_mini/nokogiri.rb
@@ -18,14 +18,14 @@ module ActiveSupport
end
end
- module Conversions
- module Document
+ module Conversions #:nodoc:
+ module Document #:nodoc:
def to_hash
root.to_hash
end
end
- module Node
+ module Node #:nodoc:
CONTENT_ROOT = '__content__'
# Convert XML document to hash
diff --git a/activesupport/lib/active_support/xml_mini/rexml.rb b/activesupport/lib/active_support/xml_mini/rexml.rb
index a8fdeca967..771109514c 100644
--- a/activesupport/lib/active_support/xml_mini/rexml.rb
+++ b/activesupport/lib/active_support/xml_mini/rexml.rb
@@ -56,7 +56,9 @@ module ActiveSupport
hash
else
# must use value to prevent double-escaping
- merge!(hash, CONTENT_KEY, element.texts.sum(&:value))
+ texts = ''
+ element.texts.each { |t| texts << t.value }
+ merge!(hash, CONTENT_KEY, texts)
end
end