activesupport 2.2.3 → 2.3.2
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 +128 -89
- data/lib/active_support.rb +31 -33
- data/lib/active_support/backtrace_cleaner.rb +72 -0
- data/lib/active_support/buffered_logger.rb +9 -7
- data/lib/active_support/cache.rb +13 -8
- data/lib/active_support/cache/drb_store.rb +2 -3
- data/lib/active_support/cache/mem_cache_store.rb +6 -1
- data/lib/active_support/cache/strategy/local_cache.rb +104 -0
- data/lib/active_support/callbacks.rb +20 -21
- data/lib/active_support/core_ext.rb +1 -1
- data/lib/active_support/core_ext/array.rb +2 -0
- data/lib/active_support/core_ext/array/conversions.rb +26 -13
- data/lib/active_support/core_ext/array/wrapper.rb +24 -0
- data/lib/active_support/core_ext/benchmark.rb +13 -6
- data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +14 -5
- data/lib/active_support/core_ext/class/attribute_accessors.rb +24 -24
- data/lib/active_support/core_ext/class/delegating_attributes.rb +20 -19
- data/lib/active_support/core_ext/class/inheritable_attributes.rb +34 -34
- data/lib/active_support/core_ext/date/conversions.rb +3 -3
- data/lib/active_support/core_ext/date_time/conversions.rb +1 -1
- data/lib/active_support/core_ext/enumerable.rb +9 -0
- data/lib/active_support/core_ext/exception.rb +12 -8
- data/lib/active_support/core_ext/file/atomic.rb +2 -2
- data/lib/active_support/core_ext/hash/conversions.rb +32 -54
- data/lib/active_support/core_ext/hash/indifferent_access.rb +6 -0
- data/lib/active_support/core_ext/hash/keys.rb +1 -1
- data/lib/active_support/core_ext/hash/slice.rb +8 -1
- data/lib/active_support/core_ext/logger.rb +8 -6
- data/lib/active_support/core_ext/module/aliasing.rb +3 -3
- data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +4 -4
- data/lib/active_support/core_ext/module/attribute_accessors.rb +24 -24
- data/lib/active_support/core_ext/module/delegation.rb +29 -3
- data/lib/active_support/core_ext/module/synchronization.rb +5 -5
- data/lib/active_support/core_ext/object/conversions.rb +2 -1
- data/lib/active_support/core_ext/object/misc.rb +16 -0
- data/lib/active_support/core_ext/range/conversions.rb +1 -1
- data/lib/active_support/core_ext/rexml.rb +29 -24
- data/lib/active_support/core_ext/string/inflections.rb +3 -3
- data/lib/active_support/core_ext/time/calculations.rb +1 -2
- data/lib/active_support/core_ext/time/conversions.rb +1 -1
- data/lib/active_support/core_ext/try.rb +36 -0
- data/lib/active_support/dependencies.rb +18 -14
- data/lib/active_support/deprecation.rb +10 -57
- data/lib/active_support/duration.rb +3 -1
- data/lib/active_support/inflections.rb +1 -0
- data/lib/active_support/inflector.rb +16 -7
- data/lib/active_support/json/decoding.rb +21 -3
- data/lib/active_support/json/encoders/date.rb +1 -1
- data/lib/active_support/json/encoders/date_time.rb +1 -1
- data/lib/active_support/json/encoders/hash.rb +10 -11
- data/lib/active_support/json/encoders/time.rb +1 -1
- data/lib/active_support/json/encoding.rb +23 -29
- data/lib/active_support/locale/en.yml +3 -2
- data/lib/active_support/memoizable.rb +61 -43
- data/lib/active_support/message_encryptor.rb +70 -0
- data/lib/active_support/message_verifier.rb +46 -0
- data/lib/active_support/multibyte.rb +6 -30
- data/lib/active_support/multibyte/chars.rb +30 -9
- data/lib/active_support/multibyte/unicode_database.rb +4 -4
- data/lib/active_support/option_merger.rb +7 -1
- data/lib/active_support/ordered_hash.rb +75 -27
- data/lib/active_support/secure_random.rb +8 -6
- data/lib/active_support/test_case.rb +32 -17
- data/lib/active_support/testing/{core_ext/test/unit/assertions.rb → assertions.rb} +13 -20
- data/lib/active_support/testing/declarative.rb +21 -0
- data/lib/active_support/testing/deprecation.rb +55 -0
- data/lib/active_support/testing/performance.rb +1 -1
- data/lib/active_support/testing/setup_and_teardown.rb +57 -86
- data/lib/active_support/time_with_zone.rb +8 -6
- data/lib/active_support/values/time_zone.rb +1 -0
- data/lib/active_support/vendor.rb +6 -11
- data/lib/active_support/vendor/i18n-0.1.3/MIT-LICENSE +20 -0
- data/lib/active_support/vendor/i18n-0.1.3/README.textile +20 -0
- data/lib/active_support/vendor/i18n-0.1.3/Rakefile +5 -0
- data/lib/active_support/vendor/i18n-0.1.3/i18n.gemspec +27 -0
- data/lib/active_support/vendor/{i18n-0.0.1 → i18n-0.1.3/lib}/i18n.rb +42 -37
- data/lib/active_support/vendor/{i18n-0.0.1 → i18n-0.1.3/lib}/i18n/backend/simple.rb +37 -39
- data/lib/active_support/vendor/{i18n-0.0.1 → i18n-0.1.3/lib}/i18n/exceptions.rb +3 -3
- data/lib/active_support/vendor/i18n-0.1.3/test/all.rb +5 -0
- data/lib/active_support/vendor/i18n-0.1.3/test/i18n_exceptions_test.rb +100 -0
- data/lib/active_support/vendor/i18n-0.1.3/test/i18n_test.rb +125 -0
- data/lib/active_support/vendor/i18n-0.1.3/test/locale/en.rb +1 -0
- data/lib/active_support/vendor/i18n-0.1.3/test/locale/en.yml +3 -0
- data/lib/active_support/vendor/i18n-0.1.3/test/simple_backend_test.rb +568 -0
- data/lib/active_support/vendor/{memcache-client-1.5.1 → memcache-client-1.6.5}/memcache.rb +381 -295
- data/lib/active_support/version.rb +2 -2
- data/lib/active_support/xml_mini.rb +31 -0
- data/lib/active_support/xml_mini/libxml.rb +133 -0
- data/lib/active_support/xml_mini/nokogiri.rb +77 -0
- data/lib/active_support/xml_mini/rexml.rb +108 -0
- metadata +85 -14
- data/lib/active_support/multibyte/utils.rb +0 -61
- data/lib/active_support/testing/core_ext/test.rb +0 -6
- data/lib/active_support/vendor/xml-simple-1.0.11/xmlsimple.rb +0 -1021
@@ -1,10 +1,10 @@
|
|
1
1
|
module ActiveSupport
|
2
2
|
module Memoizable
|
3
|
-
|
3
|
+
def self.memoized_ivar_for(symbol)
|
4
4
|
"@_memoized_#{symbol.to_s.sub(/\?\Z/, '_query').sub(/!\Z/, '_bang')}".to_sym
|
5
5
|
end
|
6
6
|
|
7
|
-
module
|
7
|
+
module InstanceMethods
|
8
8
|
def self.included(base)
|
9
9
|
base.class_eval do
|
10
10
|
unless base.method_defined?(:freeze_without_memoizable)
|
@@ -19,23 +19,35 @@ module ActiveSupport
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def memoize_all
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
22
|
+
prime_cache ".*"
|
23
|
+
end
|
24
|
+
|
25
|
+
def unmemoize_all
|
26
|
+
flush_cache ".*"
|
27
|
+
end
|
28
|
+
|
29
|
+
def prime_cache(*syms)
|
30
|
+
syms.each do |sym|
|
31
|
+
methods.each do |m|
|
32
|
+
if m.to_s =~ /^_unmemoized_(#{sym})/
|
33
|
+
if method(m).arity == 0
|
34
|
+
__send__($1)
|
35
|
+
else
|
36
|
+
ivar = ActiveSupport::Memoizable.memoized_ivar_for($1)
|
37
|
+
instance_variable_set(ivar, {})
|
38
|
+
end
|
29
39
|
end
|
30
40
|
end
|
31
41
|
end
|
32
42
|
end
|
33
43
|
|
34
|
-
def
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
44
|
+
def flush_cache(*syms, &block)
|
45
|
+
syms.each do |sym|
|
46
|
+
methods.each do |m|
|
47
|
+
if m.to_s =~ /^_unmemoized_(#{sym})/
|
48
|
+
ivar = ActiveSupport::Memoizable.memoized_ivar_for($1)
|
49
|
+
instance_variable_get(ivar).clear if instance_variable_defined?(ivar)
|
50
|
+
end
|
39
51
|
end
|
40
52
|
end
|
41
53
|
end
|
@@ -44,37 +56,43 @@ module ActiveSupport
|
|
44
56
|
def memoize(*symbols)
|
45
57
|
symbols.each do |symbol|
|
46
58
|
original_method = :"_unmemoized_#{symbol}"
|
47
|
-
memoized_ivar =
|
59
|
+
memoized_ivar = ActiveSupport::Memoizable.memoized_ivar_for(symbol)
|
48
60
|
|
49
61
|
class_eval <<-EOS, __FILE__, __LINE__
|
50
|
-
include
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
if
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
#{memoized_ivar}[args]
|
72
|
-
|
73
|
-
|
74
|
-
#
|
75
|
-
|
76
|
-
|
77
|
-
|
62
|
+
include InstanceMethods # include InstanceMethods
|
63
|
+
#
|
64
|
+
if method_defined?(:#{original_method}) # if method_defined?(:_unmemoized_mime_type)
|
65
|
+
raise "Already memoized #{symbol}" # raise "Already memoized mime_type"
|
66
|
+
end # end
|
67
|
+
alias #{original_method} #{symbol} # alias _unmemoized_mime_type mime_type
|
68
|
+
#
|
69
|
+
if instance_method(:#{symbol}).arity == 0 # if instance_method(:mime_type).arity == 0
|
70
|
+
def #{symbol}(reload = false) # def mime_type(reload = false)
|
71
|
+
if reload || !defined?(#{memoized_ivar}) || #{memoized_ivar}.empty? # if reload || !defined?(@_memoized_mime_type) || @_memoized_mime_type.empty?
|
72
|
+
#{memoized_ivar} = [#{original_method}.freeze] # @_memoized_mime_type = [_unmemoized_mime_type.freeze]
|
73
|
+
end # end
|
74
|
+
#{memoized_ivar}[0] # @_memoized_mime_type[0]
|
75
|
+
end # end
|
76
|
+
else # else
|
77
|
+
def #{symbol}(*args) # def mime_type(*args)
|
78
|
+
#{memoized_ivar} ||= {} unless frozen? # @_memoized_mime_type ||= {} unless frozen?
|
79
|
+
reload = args.pop if args.last == true || args.last == :reload # reload = args.pop if args.last == true || args.last == :reload
|
80
|
+
#
|
81
|
+
if defined?(#{memoized_ivar}) && #{memoized_ivar} # if defined?(@_memoized_mime_type) && @_memoized_mime_type
|
82
|
+
if !reload && #{memoized_ivar}.has_key?(args) # if !reload && @_memoized_mime_type.has_key?(args)
|
83
|
+
#{memoized_ivar}[args] # @_memoized_mime_type[args]
|
84
|
+
elsif #{memoized_ivar} # elsif @_memoized_mime_type
|
85
|
+
#{memoized_ivar}[args] = #{original_method}(*args).freeze # @_memoized_mime_type[args] = _unmemoized_mime_type(*args).freeze
|
86
|
+
end # end
|
87
|
+
else # else
|
88
|
+
#{original_method}(*args) # _unmemoized_mime_type(*args)
|
89
|
+
end # end
|
90
|
+
end # end
|
91
|
+
end # end
|
92
|
+
#
|
93
|
+
if private_method_defined?(#{original_method.inspect}) # if private_method_defined?(:_unmemoized_mime_type)
|
94
|
+
private #{symbol.inspect} # private :mime_type
|
95
|
+
end # end
|
78
96
|
EOS
|
79
97
|
end
|
80
98
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
# MessageEncryptor is a simple way to encrypt values which get stored somewhere
|
5
|
+
# you don't trust.
|
6
|
+
#
|
7
|
+
# The cipher text and initialization vector are base64 encoded and returned to you.
|
8
|
+
#
|
9
|
+
# This can be used in situations similar to the MessageVerifier, but where you don't
|
10
|
+
# want users to be able to determine the value of the payload.
|
11
|
+
class MessageEncryptor
|
12
|
+
class InvalidMessage < StandardError; end
|
13
|
+
OpenSSLCipherError = OpenSSL::Cipher.const_defined?(:CipherError) ? OpenSSL::Cipher::CipherError : OpenSSL::CipherError
|
14
|
+
|
15
|
+
def initialize(secret, cipher = 'aes-256-cbc')
|
16
|
+
@secret = secret
|
17
|
+
@cipher = cipher
|
18
|
+
end
|
19
|
+
|
20
|
+
def encrypt(value)
|
21
|
+
cipher = new_cipher
|
22
|
+
# Rely on OpenSSL for the initialization vector
|
23
|
+
iv = cipher.random_iv
|
24
|
+
|
25
|
+
cipher.encrypt
|
26
|
+
cipher.key = @secret
|
27
|
+
cipher.iv = iv
|
28
|
+
|
29
|
+
encrypted_data = cipher.update(Marshal.dump(value))
|
30
|
+
encrypted_data << cipher.final
|
31
|
+
|
32
|
+
[encrypted_data, iv].map {|v| ActiveSupport::Base64.encode64s(v)}.join("--")
|
33
|
+
end
|
34
|
+
|
35
|
+
def decrypt(encrypted_message)
|
36
|
+
cipher = new_cipher
|
37
|
+
encrypted_data, iv = encrypted_message.split("--").map {|v| ActiveSupport::Base64.decode64(v)}
|
38
|
+
|
39
|
+
cipher.decrypt
|
40
|
+
cipher.key = @secret
|
41
|
+
cipher.iv = iv
|
42
|
+
|
43
|
+
decrypted_data = cipher.update(encrypted_data)
|
44
|
+
decrypted_data << cipher.final
|
45
|
+
|
46
|
+
Marshal.load(decrypted_data)
|
47
|
+
rescue OpenSSLCipherError, TypeError
|
48
|
+
raise InvalidMessage
|
49
|
+
end
|
50
|
+
|
51
|
+
def encrypt_and_sign(value)
|
52
|
+
verifier.generate(encrypt(value))
|
53
|
+
end
|
54
|
+
|
55
|
+
def decrypt_and_verify(value)
|
56
|
+
decrypt(verifier.verify(value))
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
private
|
62
|
+
def new_cipher
|
63
|
+
OpenSSL::Cipher::Cipher.new(@cipher)
|
64
|
+
end
|
65
|
+
|
66
|
+
def verifier
|
67
|
+
MessageVerifier.new(@secret)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module ActiveSupport
|
2
|
+
# MessageVerifier makes it easy to generate and verify messages which are signed
|
3
|
+
# to prevent tampering.
|
4
|
+
#
|
5
|
+
# This is useful for cases like remember-me tokens and auto-unsubscribe links where the
|
6
|
+
# session store isn't suitable or available.
|
7
|
+
#
|
8
|
+
# Remember Me:
|
9
|
+
# cookies[:remember_me] = @verifier.generate([@user.id, 2.weeks.from_now])
|
10
|
+
#
|
11
|
+
# In the authentication filter:
|
12
|
+
#
|
13
|
+
# id, time = @verifier.verify(cookies[:remember_me])
|
14
|
+
# if time < Time.now
|
15
|
+
# self.current_user = User.find(id)
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
class MessageVerifier
|
19
|
+
class InvalidSignature < StandardError; end
|
20
|
+
|
21
|
+
def initialize(secret, digest = 'SHA1')
|
22
|
+
@secret = secret
|
23
|
+
@digest = digest
|
24
|
+
end
|
25
|
+
|
26
|
+
def verify(signed_message)
|
27
|
+
data, digest = signed_message.split("--")
|
28
|
+
if digest != generate_digest(data)
|
29
|
+
raise InvalidSignature
|
30
|
+
else
|
31
|
+
Marshal.load(ActiveSupport::Base64.decode64(data))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def generate(value)
|
36
|
+
data = ActiveSupport::Base64.encode64s(Marshal.dump(value))
|
37
|
+
"#{data}--#{generate_digest(data)}"
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def generate_digest(data)
|
42
|
+
require 'openssl' unless defined?(OpenSSL)
|
43
|
+
OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new(@digest), @secret, data)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -1,5 +1,9 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
require 'active_support/multibyte/chars'
|
4
|
+
require 'active_support/multibyte/exceptions'
|
5
|
+
require 'active_support/multibyte/unicode_database'
|
6
|
+
|
3
7
|
module ActiveSupport #:nodoc:
|
4
8
|
module Multibyte
|
5
9
|
# A list of all available normalization forms. See http://www.unicode.org/reports/tr15/tr15-29.html for more
|
@@ -23,35 +27,7 @@ module ActiveSupport #:nodoc:
|
|
23
27
|
#
|
24
28
|
# Example:
|
25
29
|
# ActiveSupport::Multibyte.proxy_class = CharsForUTF32
|
26
|
-
|
27
|
-
|
28
|
-
end
|
29
|
-
|
30
|
-
# Returns the currect proxy class
|
31
|
-
def self.proxy_class
|
32
|
-
@proxy_class ||= ActiveSupport::Multibyte::Chars
|
33
|
-
end
|
34
|
-
|
35
|
-
# Regular expressions that describe valid byte sequences for a character
|
36
|
-
VALID_CHARACTER = {
|
37
|
-
# Borrowed from the Kconv library by Shinji KONO - (also as seen on the W3C site)
|
38
|
-
'UTF-8' => /\A(?:
|
39
|
-
[\x00-\x7f] |
|
40
|
-
[\xc2-\xdf] [\x80-\xbf] |
|
41
|
-
\xe0 [\xa0-\xbf] [\x80-\xbf] |
|
42
|
-
[\xe1-\xef] [\x80-\xbf] [\x80-\xbf] |
|
43
|
-
\xf0 [\x90-\xbf] [\x80-\xbf] [\x80-\xbf] |
|
44
|
-
[\xf1-\xf3] [\x80-\xbf] [\x80-\xbf] [\x80-\xbf] |
|
45
|
-
\xf4 [\x80-\x8f] [\x80-\xbf] [\x80-\xbf])\z /xn,
|
46
|
-
# Quick check for valid Shift-JIS characters, disregards the odd-even pairing
|
47
|
-
'Shift_JIS' => /\A(?:
|
48
|
-
[\x00-\x7e \xa1-\xdf] |
|
49
|
-
[\x81-\x9f \xe0-\xef] [\x40-\x7e \x80-\x9e \x9f-\xfc])\z /xn
|
50
|
-
}
|
30
|
+
mattr_accessor :proxy_class
|
31
|
+
self.proxy_class = ActiveSupport::Multibyte::Chars
|
51
32
|
end
|
52
33
|
end
|
53
|
-
|
54
|
-
require 'active_support/multibyte/chars'
|
55
|
-
require 'active_support/multibyte/exceptions'
|
56
|
-
require 'active_support/multibyte/unicode_database'
|
57
|
-
require 'active_support/multibyte/utils'
|
@@ -73,7 +73,16 @@ module ActiveSupport #:nodoc:
|
|
73
73
|
UNICODE_TRAILERS_PAT = /(#{codepoints_to_pattern(UNICODE_LEADERS_AND_TRAILERS)})+\Z/
|
74
74
|
UNICODE_LEADERS_PAT = /\A(#{codepoints_to_pattern(UNICODE_LEADERS_AND_TRAILERS)})+/
|
75
75
|
|
76
|
-
|
76
|
+
# Borrowed from the Kconv library by Shinji KONO - (also as seen on the W3C site)
|
77
|
+
UTF8_PAT = /\A(?:
|
78
|
+
[\x00-\x7f] |
|
79
|
+
[\xc2-\xdf] [\x80-\xbf] |
|
80
|
+
\xe0 [\xa0-\xbf] [\x80-\xbf] |
|
81
|
+
[\xe1-\xef] [\x80-\xbf] [\x80-\xbf] |
|
82
|
+
\xf0 [\x90-\xbf] [\x80-\xbf] [\x80-\xbf] |
|
83
|
+
[\xf1-\xf3] [\x80-\xbf] [\x80-\xbf] [\x80-\xbf] |
|
84
|
+
\xf4 [\x80-\x8f] [\x80-\xbf] [\x80-\xbf]
|
85
|
+
)*\z/xn
|
77
86
|
|
78
87
|
attr_reader :wrapped_string
|
79
88
|
alias to_s wrapped_string
|
@@ -283,23 +292,23 @@ module ActiveSupport #:nodoc:
|
|
283
292
|
def rstrip
|
284
293
|
chars(@wrapped_string.gsub(UNICODE_TRAILERS_PAT, ''))
|
285
294
|
end
|
286
|
-
|
295
|
+
|
287
296
|
# Strips entire range of Unicode whitespace from the left of the string.
|
288
297
|
def lstrip
|
289
298
|
chars(@wrapped_string.gsub(UNICODE_LEADERS_PAT, ''))
|
290
299
|
end
|
291
|
-
|
300
|
+
|
292
301
|
# Strips entire range of Unicode whitespace from the right and left of the string.
|
293
302
|
def strip
|
294
303
|
rstrip.lstrip
|
295
304
|
end
|
296
|
-
|
305
|
+
|
297
306
|
# Returns the number of codepoints in the string
|
298
307
|
def size
|
299
308
|
self.class.u_unpack(@wrapped_string).size
|
300
309
|
end
|
301
310
|
alias_method :length, :size
|
302
|
-
|
311
|
+
|
303
312
|
# Reverses all characters in the string.
|
304
313
|
#
|
305
314
|
# Example:
|
@@ -307,7 +316,7 @@ module ActiveSupport #:nodoc:
|
|
307
316
|
def reverse
|
308
317
|
chars(self.class.u_unpack(@wrapped_string).reverse.pack('U*'))
|
309
318
|
end
|
310
|
-
|
319
|
+
|
311
320
|
# Implements Unicode-aware slice with codepoints. Slicing on one point returns the codepoints for that
|
312
321
|
# character.
|
313
322
|
#
|
@@ -335,7 +344,19 @@ module ActiveSupport #:nodoc:
|
|
335
344
|
end
|
336
345
|
alias_method :[], :slice
|
337
346
|
|
338
|
-
#
|
347
|
+
# Like <tt>String#slice!</tt>, except instead of byte offsets you specify character offsets.
|
348
|
+
#
|
349
|
+
# Example:
|
350
|
+
# s = 'こんにちは'
|
351
|
+
# s.mb_chars.slice!(2..3).to_s #=> "にち"
|
352
|
+
# s #=> "こんは"
|
353
|
+
def slice!(*args)
|
354
|
+
slice = self[*args]
|
355
|
+
self[*args] = ''
|
356
|
+
slice
|
357
|
+
end
|
358
|
+
|
359
|
+
# Returns the codepoint of the first character in the string.
|
339
360
|
#
|
340
361
|
# Example:
|
341
362
|
# 'こんにちは'.mb_chars.ord #=> 12371
|
@@ -423,7 +444,7 @@ module ActiveSupport #:nodoc:
|
|
423
444
|
chars(self.class.tidy_bytes(@wrapped_string))
|
424
445
|
end
|
425
446
|
|
426
|
-
%w(lstrip rstrip strip reverse upcase downcase
|
447
|
+
%w(lstrip rstrip strip reverse upcase downcase tidy_bytes capitalize).each do |method|
|
427
448
|
define_method("#{method}!") do |*args|
|
428
449
|
unless args.nil?
|
429
450
|
@wrapped_string = send(method, *args).to_s
|
@@ -610,7 +631,7 @@ module ActiveSupport #:nodoc:
|
|
610
631
|
string.split(//u).map do |c|
|
611
632
|
c.force_encoding(Encoding::ASCII) if c.respond_to?(:force_encoding)
|
612
633
|
|
613
|
-
if !
|
634
|
+
if !UTF8_PAT.match(c)
|
614
635
|
n = c.unpack('C')[0]
|
615
636
|
n < 128 ? n.chr :
|
616
637
|
n < 160 ? [UCD.cp1252[n] || n].pack('U') :
|
@@ -24,10 +24,10 @@ module ActiveSupport #:nodoc:
|
|
24
24
|
# Lazy load the Unicode database so it's only loaded when it's actually used
|
25
25
|
ATTRIBUTES.each do |attr_name|
|
26
26
|
class_eval(<<-EOS, __FILE__, __LINE__)
|
27
|
-
def #{attr_name}
|
28
|
-
load
|
29
|
-
@#{attr_name}
|
30
|
-
end
|
27
|
+
def #{attr_name} # def codepoints
|
28
|
+
load # load
|
29
|
+
@#{attr_name} # @codepoints
|
30
|
+
end # end
|
31
31
|
EOS
|
32
32
|
end
|
33
33
|
|
@@ -10,7 +10,13 @@ module ActiveSupport
|
|
10
10
|
|
11
11
|
private
|
12
12
|
def method_missing(method, *arguments, &block)
|
13
|
-
|
13
|
+
if arguments.last.is_a?(Proc)
|
14
|
+
proc = arguments.pop
|
15
|
+
arguments << lambda { |*args| @options.deep_merge(proc.call(*args)) }
|
16
|
+
else
|
17
|
+
arguments << (arguments.last.respond_to?(:to_hash) ? @options.deep_merge(arguments.pop) : @options.dup)
|
18
|
+
end
|
19
|
+
|
14
20
|
@context.__send__(method, *arguments, &block)
|
15
21
|
end
|
16
22
|
end
|
@@ -4,55 +4,103 @@ module ActiveSupport
|
|
4
4
|
if RUBY_VERSION >= '1.9'
|
5
5
|
OrderedHash = ::Hash
|
6
6
|
else
|
7
|
-
class OrderedHash <
|
7
|
+
class OrderedHash < Hash #:nodoc:
|
8
|
+
def initialize(*args, &block)
|
9
|
+
super
|
10
|
+
@keys = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize_copy(other)
|
14
|
+
super
|
15
|
+
# make a deep copy of keys
|
16
|
+
@keys = other.keys
|
17
|
+
end
|
18
|
+
|
8
19
|
def []=(key, value)
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
20
|
+
@keys << key if !has_key?(key)
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
def delete(key)
|
25
|
+
if has_key? key
|
26
|
+
index = @keys.index(key)
|
27
|
+
@keys.delete_at index
|
14
28
|
end
|
15
|
-
|
29
|
+
super
|
30
|
+
end
|
31
|
+
|
32
|
+
def delete_if
|
33
|
+
super
|
34
|
+
sync_keys!
|
35
|
+
self
|
16
36
|
end
|
17
37
|
|
18
|
-
def
|
19
|
-
|
20
|
-
|
38
|
+
def reject!
|
39
|
+
super
|
40
|
+
sync_keys!
|
41
|
+
self
|
21
42
|
end
|
22
43
|
|
23
|
-
def
|
24
|
-
|
25
|
-
pair ? array_index = index(pair) : nil
|
26
|
-
array_index ? delete_at(array_index).last : nil
|
44
|
+
def reject(&block)
|
45
|
+
dup.reject!(&block)
|
27
46
|
end
|
28
47
|
|
29
48
|
def keys
|
30
|
-
|
49
|
+
@keys.dup
|
31
50
|
end
|
32
51
|
|
33
52
|
def values
|
34
|
-
collect { |key
|
53
|
+
@keys.collect { |key| self[key] }
|
35
54
|
end
|
36
55
|
|
37
56
|
def to_hash
|
38
|
-
|
39
|
-
|
40
|
-
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
def each_key
|
61
|
+
@keys.each { |key| yield key }
|
41
62
|
end
|
42
63
|
|
43
|
-
def
|
44
|
-
|
64
|
+
def each_value
|
65
|
+
@keys.each { |key| yield self[key]}
|
45
66
|
end
|
46
67
|
|
47
|
-
|
48
|
-
|
49
|
-
|
68
|
+
def each
|
69
|
+
@keys.each {|key| yield [key, self[key]]}
|
70
|
+
end
|
71
|
+
|
72
|
+
alias_method :each_pair, :each
|
73
|
+
|
74
|
+
def clear
|
75
|
+
super
|
76
|
+
@keys.clear
|
77
|
+
self
|
78
|
+
end
|
79
|
+
|
80
|
+
def shift
|
81
|
+
k = @keys.first
|
82
|
+
v = delete(k)
|
83
|
+
[k, v]
|
84
|
+
end
|
50
85
|
|
51
|
-
def
|
52
|
-
|
86
|
+
def merge!(other_hash)
|
87
|
+
other_hash.each {|k,v| self[k] = v }
|
88
|
+
self
|
53
89
|
end
|
54
90
|
|
55
|
-
|
91
|
+
def merge(other_hash)
|
92
|
+
dup.merge!(other_hash)
|
93
|
+
end
|
94
|
+
|
95
|
+
def inspect
|
96
|
+
"#<OrderedHash #{super}>"
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def sync_keys!
|
102
|
+
@keys.delete_if {|k| !has_key?(k)}
|
103
|
+
end
|
56
104
|
end
|
57
105
|
end
|
58
106
|
end
|