activesupport 1.2.5 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- data/CHANGELOG +163 -4
- data/lib/active_support.rb +8 -3
- data/lib/active_support/breakpoint.rb +1 -1
- data/lib/active_support/caching_tools.rb +62 -0
- data/lib/active_support/clean_logger.rb +3 -1
- data/lib/active_support/core_ext/array.rb +16 -0
- data/lib/active_support/core_ext/array/conversions.rb +18 -2
- data/lib/active_support/core_ext/blank.rb +14 -2
- data/lib/active_support/core_ext/class.rb +3 -0
- data/lib/active_support/core_ext/class/attribute_accessors.rb +44 -0
- data/lib/active_support/{class_inheritable_attributes.rb → core_ext/class/inheritable_attributes.rb} +2 -4
- data/lib/active_support/core_ext/class/removal.rb +24 -0
- data/lib/active_support/core_ext/date/conversions.rb +2 -0
- data/lib/active_support/core_ext/enumerable.rb +23 -1
- data/lib/active_support/core_ext/exception.rb +0 -1
- data/lib/active_support/core_ext/hash.rb +4 -0
- data/lib/active_support/core_ext/hash/conversions.rb +44 -0
- data/lib/active_support/core_ext/hash/diff.rb +11 -0
- data/lib/active_support/core_ext/hash/indifferent_access.rb +23 -4
- data/lib/active_support/core_ext/integer/inflections.rb +1 -1
- data/lib/active_support/core_ext/kernel.rb +4 -79
- data/lib/active_support/core_ext/kernel/agnostics.rb +11 -0
- data/lib/active_support/core_ext/kernel/daemonizing.rb +15 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +51 -0
- data/lib/active_support/core_ext/kernel/requires.rb +24 -0
- data/lib/active_support/core_ext/logger.rb +16 -0
- data/lib/active_support/core_ext/module.rb +5 -0
- data/lib/active_support/core_ext/module/attribute_accessors.rb +44 -0
- data/lib/active_support/core_ext/module/delegation.rb +16 -0
- data/lib/active_support/core_ext/module/inclusion.rb +11 -0
- data/lib/active_support/core_ext/module/introspection.rb +21 -0
- data/lib/active_support/core_ext/module/loading.rb +13 -0
- data/lib/active_support/core_ext/numeric/time.rb +14 -1
- data/lib/active_support/core_ext/object.rb +2 -0
- data/lib/active_support/core_ext/object/extending.rb +47 -0
- data/lib/active_support/core_ext/object/misc.rb +34 -0
- data/lib/active_support/core_ext/proc.rb +12 -0
- data/lib/active_support/core_ext/string.rb +2 -0
- data/lib/active_support/core_ext/string/access.rb +2 -2
- data/lib/active_support/core_ext/string/inflections.rb +10 -3
- data/lib/active_support/core_ext/string/iterators.rb +17 -0
- data/lib/active_support/core_ext/symbol.rb +5 -0
- data/lib/active_support/core_ext/time/calculations.rb +15 -0
- data/lib/active_support/core_ext/time/conversions.rb +1 -0
- data/lib/active_support/dependencies.rb +81 -159
- data/lib/active_support/inflections.rb +48 -48
- data/lib/active_support/inflector.rb +17 -5
- data/lib/active_support/json.rb +37 -0
- data/lib/active_support/json/encoders.rb +25 -0
- data/lib/active_support/json/encoders/core.rb +65 -0
- data/lib/active_support/option_merger.rb +25 -0
- data/lib/active_support/ordered_options.rb +23 -11
- data/lib/active_support/reloadable.rb +30 -0
- data/lib/active_support/vendor/builder.rb +13 -0
- data/lib/active_support/vendor/builder/blankslate.rb +53 -0
- data/lib/active_support/vendor/builder/xmlbase.rb +143 -0
- data/lib/active_support/vendor/builder/xmlevents.rb +63 -0
- data/lib/active_support/vendor/builder/xmlmarkup.rb +308 -0
- data/lib/active_support/version.rb +2 -2
- metadata +113 -69
- data/lib/active_support/class_attribute_accessors.rb +0 -57
- data/lib/active_support/core_ext/object_and_class.rb +0 -44
- data/lib/active_support/module_attribute_accessors.rb +0 -57
@@ -6,4 +6,26 @@ module Enumerable #:nodoc:
|
|
6
6
|
end
|
7
7
|
match
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
|
+
# Collect an enumerable into sets, grouped by the result of a block. Useful,
|
11
|
+
# for example, for grouping records by date.
|
12
|
+
#
|
13
|
+
# e.g.
|
14
|
+
#
|
15
|
+
# latest_transcripts.group_by(&:day).each do |day, transcripts|
|
16
|
+
# p "#{day} -> #{transcripts.map(&:class) * ', '}"
|
17
|
+
# end
|
18
|
+
# "2006-03-01 -> Transcript"
|
19
|
+
# "2006-02-28 -> Transcript"
|
20
|
+
# "2006-02-27 -> Transcript, Transcript"
|
21
|
+
# "2006-02-26 -> Transcript, Transcript"
|
22
|
+
# "2006-02-25 -> Transcript"
|
23
|
+
# "2006-02-24 -> Transcript, Transcript"
|
24
|
+
# "2006-02-23 -> Transcript"
|
25
|
+
def group_by
|
26
|
+
inject({}) do |groups, element|
|
27
|
+
(groups[yield(element)] ||= []) << element
|
28
|
+
groups
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -1,9 +1,13 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/hash/keys'
|
2
2
|
require File.dirname(__FILE__) + '/hash/indifferent_access'
|
3
3
|
require File.dirname(__FILE__) + '/hash/reverse_merge'
|
4
|
+
require File.dirname(__FILE__) + '/hash/conversions'
|
5
|
+
require File.dirname(__FILE__) + '/hash/diff'
|
4
6
|
|
5
7
|
class Hash #:nodoc:
|
6
8
|
include ActiveSupport::CoreExtensions::Hash::Keys
|
7
9
|
include ActiveSupport::CoreExtensions::Hash::IndifferentAccess
|
8
10
|
include ActiveSupport::CoreExtensions::Hash::ReverseMerge
|
11
|
+
include ActiveSupport::CoreExtensions::Hash::Conversions
|
12
|
+
include ActiveSupport::CoreExtensions::Hash::Diff
|
9
13
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module ActiveSupport #:nodoc:
|
2
|
+
module CoreExtensions #:nodoc:
|
3
|
+
module Hash #:nodoc:
|
4
|
+
module Conversions
|
5
|
+
XML_TYPE_NAMES = {
|
6
|
+
"Fixnum" => "integer",
|
7
|
+
"Date" => "date",
|
8
|
+
"Time" => "datetime",
|
9
|
+
"TrueClass" => "boolean",
|
10
|
+
"FalseClass" => "boolean"
|
11
|
+
}
|
12
|
+
|
13
|
+
XML_FORMATTING = {
|
14
|
+
"date" => Proc.new { |date| date.to_s(:db) },
|
15
|
+
"datetime" => Proc.new { |time| time.xmlschema }
|
16
|
+
}
|
17
|
+
|
18
|
+
def to_xml(options = {})
|
19
|
+
options[:indent] ||= 2
|
20
|
+
options.reverse_merge!({ :builder => Builder::XmlMarkup.new(:indent => options[:indent]), :root => "hash" })
|
21
|
+
options[:builder].instruct! unless options.delete(:skip_instruct)
|
22
|
+
|
23
|
+
options[:builder].__send__(options[:root].to_s.dasherize) do
|
24
|
+
each do |key, value|
|
25
|
+
case value
|
26
|
+
when ::Hash
|
27
|
+
value.to_xml(options.merge({ :root => key, :skip_instruct => true }))
|
28
|
+
when ::Array
|
29
|
+
value.to_xml(options.merge({ :root => key, :children => key.to_s.singularize, :skip_instruct => true}))
|
30
|
+
else
|
31
|
+
type_name = XML_TYPE_NAMES[value.class.to_s]
|
32
|
+
|
33
|
+
options[:builder].tag!(key.to_s.dasherize,
|
34
|
+
XML_FORMATTING[type_name] ? XML_FORMATTING[type_name].call(value) : value,
|
35
|
+
options[:skip_types] || value.nil? || type_name.nil? ? { } : { :type => type_name }
|
36
|
+
)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# this class has dubious semantics and we only have it so that
|
2
|
+
# people can write params[:key] instead of params['key']
|
3
|
+
|
2
4
|
class HashWithIndifferentAccess < Hash
|
3
5
|
def initialize(constructor = {})
|
4
6
|
if constructor.is_a?(Hash)
|
@@ -14,13 +16,18 @@ class HashWithIndifferentAccess < Hash
|
|
14
16
|
end
|
15
17
|
|
16
18
|
alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
|
19
|
+
alias_method :regular_update, :update unless method_defined?(:regular_update)
|
17
20
|
|
18
21
|
def []=(key, value)
|
19
22
|
regular_writer(convert_key(key), convert_value(value))
|
20
23
|
end
|
21
|
-
|
22
|
-
|
24
|
+
|
25
|
+
def update(other_hash)
|
26
|
+
other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
|
27
|
+
self
|
23
28
|
end
|
29
|
+
|
30
|
+
alias_method :merge!, :update
|
24
31
|
|
25
32
|
def key?(key)
|
26
33
|
super(convert_key(key))
|
@@ -38,6 +45,18 @@ class HashWithIndifferentAccess < Hash
|
|
38
45
|
indices.collect {|key| self[convert_key(key)]}
|
39
46
|
end
|
40
47
|
|
48
|
+
def dup
|
49
|
+
HashWithIndifferentAccess.new(self)
|
50
|
+
end
|
51
|
+
|
52
|
+
def merge(hash)
|
53
|
+
self.dup.update(hash)
|
54
|
+
end
|
55
|
+
|
56
|
+
def delete(key)
|
57
|
+
super(convert_key(key))
|
58
|
+
end
|
59
|
+
|
41
60
|
protected
|
42
61
|
def convert_key(key)
|
43
62
|
key.kind_of?(Symbol) ? key.to_s : key
|
@@ -57,4 +76,4 @@ module ActiveSupport #:nodoc:
|
|
57
76
|
end
|
58
77
|
end
|
59
78
|
end
|
60
|
-
end
|
79
|
+
end
|
@@ -1,79 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
# returning values = [] do
|
6
|
-
# values << 'bar'
|
7
|
-
# values << 'baz'
|
8
|
-
# end
|
9
|
-
# end
|
10
|
-
#
|
11
|
-
# foo # => ['bar', 'baz']
|
12
|
-
#
|
13
|
-
def returning(value)
|
14
|
-
yield
|
15
|
-
value
|
16
|
-
end
|
17
|
-
|
18
|
-
# Sets $VERBOSE to nil for the duration of the block and back to its original value afterwards.
|
19
|
-
#
|
20
|
-
# silence_warnings do
|
21
|
-
# value = noisy_call # no warning voiced
|
22
|
-
# end
|
23
|
-
#
|
24
|
-
# noisy_call # warning voiced
|
25
|
-
def silence_warnings
|
26
|
-
old_verbose, $VERBOSE = $VERBOSE, nil
|
27
|
-
yield
|
28
|
-
ensure
|
29
|
-
$VERBOSE = old_verbose
|
30
|
-
end
|
31
|
-
|
32
|
-
# Silences stderr for the duration of the block.
|
33
|
-
#
|
34
|
-
# silence_stderr do
|
35
|
-
# $stderr.puts 'This will never be seen'
|
36
|
-
# end
|
37
|
-
#
|
38
|
-
# $stderr.puts 'But this will'
|
39
|
-
def silence_stderr
|
40
|
-
old_stderr = STDERR.dup
|
41
|
-
STDERR.reopen(RUBY_PLATFORM =~ /mswin/ ? 'NUL:' : '/dev/null')
|
42
|
-
STDERR.sync = true
|
43
|
-
yield
|
44
|
-
ensure
|
45
|
-
STDERR.reopen(old_stderr)
|
46
|
-
end
|
47
|
-
|
48
|
-
# Makes backticks behave (somewhat more) similarly on all platforms.
|
49
|
-
# On win32 `nonexistent_command` raises Errno::ENOENT; on Unix, the
|
50
|
-
# spawned shell prints a message to stderr and sets $?. We emulate
|
51
|
-
# Unix on the former but not the latter.
|
52
|
-
def `(command) #:nodoc:
|
53
|
-
super
|
54
|
-
rescue Errno::ENOENT => e
|
55
|
-
STDERR.puts "#$0: #{e}"
|
56
|
-
end
|
57
|
-
|
58
|
-
# Method that requires a library, ensuring that rubygems is loaded
|
59
|
-
def require_library_or_gem(library_name)
|
60
|
-
begin
|
61
|
-
require library_name
|
62
|
-
rescue LoadError => cannot_require
|
63
|
-
# 1. Requiring the module is unsuccessful, maybe it's a gem and nobody required rubygems yet. Try.
|
64
|
-
begin
|
65
|
-
require 'rubygems'
|
66
|
-
rescue LoadError => rubygems_not_installed
|
67
|
-
raise cannot_require
|
68
|
-
end
|
69
|
-
# 2. Rubygems is installed and loaded. Try to load the library again
|
70
|
-
begin
|
71
|
-
require library_name
|
72
|
-
rescue LoadError => gem_not_installed
|
73
|
-
raise cannot_require
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
|
79
|
-
end
|
1
|
+
require File.dirname(__FILE__) + '/kernel/daemonizing'
|
2
|
+
require File.dirname(__FILE__) + '/kernel/reporting'
|
3
|
+
require File.dirname(__FILE__) + '/kernel/agnostics'
|
4
|
+
require File.dirname(__FILE__) + '/kernel/requires'
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class Object
|
2
|
+
# Makes backticks behave (somewhat more) similarly on all platforms.
|
3
|
+
# On win32 `nonexistent_command` raises Errno::ENOENT; on Unix, the
|
4
|
+
# spawned shell prints a message to stderr and sets $?. We emulate
|
5
|
+
# Unix on the former but not the latter.
|
6
|
+
def `(command) #:nodoc:
|
7
|
+
super
|
8
|
+
rescue Errno::ENOENT => e
|
9
|
+
STDERR.puts "#$0: #{e}"
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Kernel
|
2
|
+
# Turns the current script into a daemon process that detaches from the console.
|
3
|
+
# It can be shut down with a TERM signal.
|
4
|
+
def daemonize
|
5
|
+
exit if fork # Parent exits, child continues.
|
6
|
+
Process.setsid # Become session leader.
|
7
|
+
exit if fork # Zap session leader. See [1].
|
8
|
+
Dir.chdir "/" # Release old working directory.
|
9
|
+
File.umask 0000 # Ensure sensible umask. Adjust as needed.
|
10
|
+
STDIN.reopen "/dev/null" # Free file descriptors and
|
11
|
+
STDOUT.reopen "/dev/null", "a" # point them somewhere sensible.
|
12
|
+
STDERR.reopen STDOUT # STDOUT/ERR should better go to a logfile.
|
13
|
+
trap("TERM") { exit }
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Kernel
|
2
|
+
# Sets $VERBOSE to nil for the duration of the block and back to its original value afterwards.
|
3
|
+
#
|
4
|
+
# silence_warnings do
|
5
|
+
# value = noisy_call # no warning voiced
|
6
|
+
# end
|
7
|
+
#
|
8
|
+
# noisy_call # warning voiced
|
9
|
+
def silence_warnings
|
10
|
+
old_verbose, $VERBOSE = $VERBOSE, nil
|
11
|
+
yield
|
12
|
+
ensure
|
13
|
+
$VERBOSE = old_verbose
|
14
|
+
end
|
15
|
+
|
16
|
+
# Sets $VERBOSE to true for the duration of the block and back to its original value afterwards.
|
17
|
+
def enable_warnings
|
18
|
+
old_verbose, $VERBOSE = $VERBOSE, true
|
19
|
+
yield
|
20
|
+
ensure
|
21
|
+
$VERBOSE = old_verbose
|
22
|
+
end
|
23
|
+
|
24
|
+
# For compatibility
|
25
|
+
def silence_stderr #:nodoc:
|
26
|
+
silence_stream(STDERR) { yield }
|
27
|
+
end
|
28
|
+
|
29
|
+
# Silences any stream for the duration of the block.
|
30
|
+
#
|
31
|
+
# silence_stream(STDOUT) do
|
32
|
+
# puts 'This will never be seen'
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# puts 'But this will'
|
36
|
+
def silence_stream(stream)
|
37
|
+
old_stream = stream.dup
|
38
|
+
stream.reopen(RUBY_PLATFORM =~ /mswin/ ? 'NUL:' : '/dev/null')
|
39
|
+
stream.sync = true
|
40
|
+
yield
|
41
|
+
ensure
|
42
|
+
stream.reopen(old_stream)
|
43
|
+
end
|
44
|
+
|
45
|
+
def suppress(*exception_classes)
|
46
|
+
begin yield
|
47
|
+
rescue Exception => e
|
48
|
+
raise unless exception_classes.any? { |cls| e.kind_of?(cls) }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Kernel
|
2
|
+
# Require a library with fallback to RubyGems. Warnings during library
|
3
|
+
# loading are silenced to increase signal/noise for application warnings.
|
4
|
+
def require_library_or_gem(library_name)
|
5
|
+
silence_warnings do
|
6
|
+
begin
|
7
|
+
require library_name
|
8
|
+
rescue LoadError => cannot_require
|
9
|
+
# 1. Requiring the module is unsuccessful, maybe it's a gem and nobody required rubygems yet. Try.
|
10
|
+
begin
|
11
|
+
require 'rubygems'
|
12
|
+
rescue LoadError => rubygems_not_installed
|
13
|
+
raise cannot_require
|
14
|
+
end
|
15
|
+
# 2. Rubygems is installed and loaded. Try to load the library again
|
16
|
+
begin
|
17
|
+
require library_name
|
18
|
+
rescue LoadError => gem_not_installed
|
19
|
+
raise cannot_require
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Adds the 'around_level' method to Logger.
|
2
|
+
|
3
|
+
class Logger
|
4
|
+
def self.define_around_helper(level)
|
5
|
+
module_eval <<-end_eval
|
6
|
+
def around_#{level}(before_message, after_message, &block)
|
7
|
+
self.#{level}(before_message)
|
8
|
+
return_value = block.call(self)
|
9
|
+
self.#{level}(after_message)
|
10
|
+
return return_value
|
11
|
+
end
|
12
|
+
end_eval
|
13
|
+
end
|
14
|
+
[:debug, :info, :error, :fatal].each {|level| define_around_helper(level) }
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,5 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/module/inclusion'
|
2
|
+
require File.dirname(__FILE__) + '/module/attribute_accessors'
|
3
|
+
require File.dirname(__FILE__) + '/module/delegation'
|
4
|
+
require File.dirname(__FILE__) + '/module/introspection'
|
5
|
+
require File.dirname(__FILE__) + '/module/loading'
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Extends the module object with module and instance accessors for class attributes,
|
2
|
+
# just like the native attr* accessors for instance attributes.
|
3
|
+
class Module # :nodoc:
|
4
|
+
def mattr_reader(*syms)
|
5
|
+
syms.each do |sym|
|
6
|
+
class_eval(<<-EOS, __FILE__, __LINE__)
|
7
|
+
unless defined? @@#{sym}
|
8
|
+
@@#{sym} = nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.#{sym}
|
12
|
+
@@#{sym}
|
13
|
+
end
|
14
|
+
|
15
|
+
def #{sym}
|
16
|
+
@@#{sym}
|
17
|
+
end
|
18
|
+
EOS
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def mattr_writer(*syms)
|
23
|
+
syms.each do |sym|
|
24
|
+
class_eval(<<-EOS, __FILE__, __LINE__)
|
25
|
+
unless defined? @@#{sym}
|
26
|
+
@@#{sym} = nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.#{sym}=(obj)
|
30
|
+
@@#{sym} = obj
|
31
|
+
end
|
32
|
+
|
33
|
+
def #{sym}=(obj)
|
34
|
+
@@#{sym} = obj
|
35
|
+
end
|
36
|
+
EOS
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def mattr_accessor(*syms)
|
41
|
+
mattr_reader(*syms)
|
42
|
+
mattr_writer(*syms)
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class Module
|
2
|
+
def delegate(*methods)
|
3
|
+
options = methods.pop
|
4
|
+
unless options.is_a?(Hash) && to = options[:to]
|
5
|
+
raise ArgumentError, "Delegation needs a target. Supply an options hash with a :to key"
|
6
|
+
end
|
7
|
+
|
8
|
+
methods.each do |method|
|
9
|
+
module_eval(<<-EOS, "(__DELEGATION__)", 1)
|
10
|
+
def #{method}(*args, &block)
|
11
|
+
#{to}.__send__(#{method.inspect}, *args, &block)
|
12
|
+
end
|
13
|
+
EOS
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|