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.

Files changed (94) hide show
  1. data/CHANGELOG +128 -89
  2. data/lib/active_support.rb +31 -33
  3. data/lib/active_support/backtrace_cleaner.rb +72 -0
  4. data/lib/active_support/buffered_logger.rb +9 -7
  5. data/lib/active_support/cache.rb +13 -8
  6. data/lib/active_support/cache/drb_store.rb +2 -3
  7. data/lib/active_support/cache/mem_cache_store.rb +6 -1
  8. data/lib/active_support/cache/strategy/local_cache.rb +104 -0
  9. data/lib/active_support/callbacks.rb +20 -21
  10. data/lib/active_support/core_ext.rb +1 -1
  11. data/lib/active_support/core_ext/array.rb +2 -0
  12. data/lib/active_support/core_ext/array/conversions.rb +26 -13
  13. data/lib/active_support/core_ext/array/wrapper.rb +24 -0
  14. data/lib/active_support/core_ext/benchmark.rb +13 -6
  15. data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +14 -5
  16. data/lib/active_support/core_ext/class/attribute_accessors.rb +24 -24
  17. data/lib/active_support/core_ext/class/delegating_attributes.rb +20 -19
  18. data/lib/active_support/core_ext/class/inheritable_attributes.rb +34 -34
  19. data/lib/active_support/core_ext/date/conversions.rb +3 -3
  20. data/lib/active_support/core_ext/date_time/conversions.rb +1 -1
  21. data/lib/active_support/core_ext/enumerable.rb +9 -0
  22. data/lib/active_support/core_ext/exception.rb +12 -8
  23. data/lib/active_support/core_ext/file/atomic.rb +2 -2
  24. data/lib/active_support/core_ext/hash/conversions.rb +32 -54
  25. data/lib/active_support/core_ext/hash/indifferent_access.rb +6 -0
  26. data/lib/active_support/core_ext/hash/keys.rb +1 -1
  27. data/lib/active_support/core_ext/hash/slice.rb +8 -1
  28. data/lib/active_support/core_ext/logger.rb +8 -6
  29. data/lib/active_support/core_ext/module/aliasing.rb +3 -3
  30. data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +4 -4
  31. data/lib/active_support/core_ext/module/attribute_accessors.rb +24 -24
  32. data/lib/active_support/core_ext/module/delegation.rb +29 -3
  33. data/lib/active_support/core_ext/module/synchronization.rb +5 -5
  34. data/lib/active_support/core_ext/object/conversions.rb +2 -1
  35. data/lib/active_support/core_ext/object/misc.rb +16 -0
  36. data/lib/active_support/core_ext/range/conversions.rb +1 -1
  37. data/lib/active_support/core_ext/rexml.rb +29 -24
  38. data/lib/active_support/core_ext/string/inflections.rb +3 -3
  39. data/lib/active_support/core_ext/time/calculations.rb +1 -2
  40. data/lib/active_support/core_ext/time/conversions.rb +1 -1
  41. data/lib/active_support/core_ext/try.rb +36 -0
  42. data/lib/active_support/dependencies.rb +18 -14
  43. data/lib/active_support/deprecation.rb +10 -57
  44. data/lib/active_support/duration.rb +3 -1
  45. data/lib/active_support/inflections.rb +1 -0
  46. data/lib/active_support/inflector.rb +16 -7
  47. data/lib/active_support/json/decoding.rb +21 -3
  48. data/lib/active_support/json/encoders/date.rb +1 -1
  49. data/lib/active_support/json/encoders/date_time.rb +1 -1
  50. data/lib/active_support/json/encoders/hash.rb +10 -11
  51. data/lib/active_support/json/encoders/time.rb +1 -1
  52. data/lib/active_support/json/encoding.rb +23 -29
  53. data/lib/active_support/locale/en.yml +3 -2
  54. data/lib/active_support/memoizable.rb +61 -43
  55. data/lib/active_support/message_encryptor.rb +70 -0
  56. data/lib/active_support/message_verifier.rb +46 -0
  57. data/lib/active_support/multibyte.rb +6 -30
  58. data/lib/active_support/multibyte/chars.rb +30 -9
  59. data/lib/active_support/multibyte/unicode_database.rb +4 -4
  60. data/lib/active_support/option_merger.rb +7 -1
  61. data/lib/active_support/ordered_hash.rb +75 -27
  62. data/lib/active_support/secure_random.rb +8 -6
  63. data/lib/active_support/test_case.rb +32 -17
  64. data/lib/active_support/testing/{core_ext/test/unit/assertions.rb → assertions.rb} +13 -20
  65. data/lib/active_support/testing/declarative.rb +21 -0
  66. data/lib/active_support/testing/deprecation.rb +55 -0
  67. data/lib/active_support/testing/performance.rb +1 -1
  68. data/lib/active_support/testing/setup_and_teardown.rb +57 -86
  69. data/lib/active_support/time_with_zone.rb +8 -6
  70. data/lib/active_support/values/time_zone.rb +1 -0
  71. data/lib/active_support/vendor.rb +6 -11
  72. data/lib/active_support/vendor/i18n-0.1.3/MIT-LICENSE +20 -0
  73. data/lib/active_support/vendor/i18n-0.1.3/README.textile +20 -0
  74. data/lib/active_support/vendor/i18n-0.1.3/Rakefile +5 -0
  75. data/lib/active_support/vendor/i18n-0.1.3/i18n.gemspec +27 -0
  76. data/lib/active_support/vendor/{i18n-0.0.1 → i18n-0.1.3/lib}/i18n.rb +42 -37
  77. data/lib/active_support/vendor/{i18n-0.0.1 → i18n-0.1.3/lib}/i18n/backend/simple.rb +37 -39
  78. data/lib/active_support/vendor/{i18n-0.0.1 → i18n-0.1.3/lib}/i18n/exceptions.rb +3 -3
  79. data/lib/active_support/vendor/i18n-0.1.3/test/all.rb +5 -0
  80. data/lib/active_support/vendor/i18n-0.1.3/test/i18n_exceptions_test.rb +100 -0
  81. data/lib/active_support/vendor/i18n-0.1.3/test/i18n_test.rb +125 -0
  82. data/lib/active_support/vendor/i18n-0.1.3/test/locale/en.rb +1 -0
  83. data/lib/active_support/vendor/i18n-0.1.3/test/locale/en.yml +3 -0
  84. data/lib/active_support/vendor/i18n-0.1.3/test/simple_backend_test.rb +568 -0
  85. data/lib/active_support/vendor/{memcache-client-1.5.1 → memcache-client-1.6.5}/memcache.rb +381 -295
  86. data/lib/active_support/version.rb +2 -2
  87. data/lib/active_support/xml_mini.rb +31 -0
  88. data/lib/active_support/xml_mini/libxml.rb +133 -0
  89. data/lib/active_support/xml_mini/nokogiri.rb +77 -0
  90. data/lib/active_support/xml_mini/rexml.rb +108 -0
  91. metadata +85 -14
  92. data/lib/active_support/multibyte/utils.rb +0 -61
  93. data/lib/active_support/testing/core_ext/test.rb +0 -6
  94. data/lib/active_support/vendor/xml-simple-1.0.11/xmlsimple.rb +0 -1021
@@ -1,5 +1,3 @@
1
- require 'tempfile'
2
-
3
1
  module ActiveSupport #:nodoc:
4
2
  module CoreExtensions #:nodoc:
5
3
  module File #:nodoc:
@@ -18,6 +16,8 @@ module ActiveSupport #:nodoc:
18
16
  # file.write("hello")
19
17
  # end
20
18
  def atomic_write(file_name, temp_dir = Dir.tmpdir)
19
+ require 'tempfile' unless defined?(Tempfile)
20
+
21
21
  temp_file = Tempfile.new(basename(file_name), temp_dir)
22
22
  yield temp_file
23
23
  temp_file.close
@@ -1,47 +1,22 @@
1
1
  require 'date'
2
- require 'cgi'
3
- require 'builder'
4
- require 'xmlsimple'
5
-
6
- # Locked down XmlSimple#xml_in_string
7
- class XmlSimple
8
- # Same as xml_in but doesn't try to smartly shoot itself in the foot.
9
- def xml_in_string(string, options = nil)
10
- handle_options('in', options)
11
-
12
- @doc = parse(string)
13
- result = collapse(@doc.root)
14
-
15
- if @options['keeproot']
16
- merge({}, @doc.root.name, result)
17
- else
18
- result
19
- end
20
- end
21
-
22
- def self.xml_in_string(string, options = nil)
23
- new.xml_in_string(string, options)
24
- end
25
- end
26
-
27
- # This module exists to decorate files deserialized using Hash.from_xml with
28
- # the <tt>original_filename</tt> and <tt>content_type</tt> methods.
29
- module FileLike #:nodoc:
30
- attr_writer :original_filename, :content_type
31
-
32
- def original_filename
33
- @original_filename || 'untitled'
34
- end
35
-
36
- def content_type
37
- @content_type || 'application/octet-stream'
38
- end
39
- end
40
2
 
41
3
  module ActiveSupport #:nodoc:
42
4
  module CoreExtensions #:nodoc:
43
5
  module Hash #:nodoc:
44
6
  module Conversions
7
+ # This module exists to decorate files deserialized using Hash.from_xml with
8
+ # the <tt>original_filename</tt> and <tt>content_type</tt> methods.
9
+ module FileLike #:nodoc:
10
+ attr_writer :original_filename, :content_type
11
+
12
+ def original_filename
13
+ @original_filename || 'untitled'
14
+ end
15
+
16
+ def content_type
17
+ @content_type || 'application/octet-stream'
18
+ end
19
+ end
45
20
 
46
21
  XML_TYPE_NAMES = {
47
22
  "Symbol" => "symbol",
@@ -49,11 +24,12 @@ module ActiveSupport #:nodoc:
49
24
  "Bignum" => "integer",
50
25
  "BigDecimal" => "decimal",
51
26
  "Float" => "float",
27
+ "TrueClass" => "boolean",
28
+ "FalseClass" => "boolean",
52
29
  "Date" => "date",
53
30
  "DateTime" => "datetime",
54
31
  "Time" => "datetime",
55
- "TrueClass" => "boolean",
56
- "FalseClass" => "boolean"
32
+ "ActiveSupport::TimeWithZone" => "datetime"
57
33
  } unless defined?(XML_TYPE_NAMES)
58
34
 
59
35
  XML_FORMATTING = {
@@ -100,7 +76,7 @@ module ActiveSupport #:nodoc:
100
76
  # Converts a hash into a string suitable for use as a URL query string. An optional <tt>namespace</tt> can be
101
77
  # passed to enclose the param names (see example below).
102
78
  #
103
- # ==== Example:
79
+ # ==== Examples
104
80
  # { :name => 'David', :nationality => 'Danish' }.to_query # => "name=David&nationality=Danish"
105
81
  #
106
82
  # { :name => 'David', :nationality => 'Danish' }.to_query('user') # => "user%5Bname%5D=David&user%5Bnationality%5D=Danish"
@@ -113,12 +89,13 @@ module ActiveSupport #:nodoc:
113
89
  alias_method :to_param, :to_query
114
90
 
115
91
  def to_xml(options = {})
92
+ require 'builder' unless defined?(Builder)
93
+
116
94
  options[:indent] ||= 2
117
95
  options.reverse_merge!({ :builder => Builder::XmlMarkup.new(:indent => options[:indent]),
118
96
  :root => "hash" })
119
97
  options[:builder].instruct! unless options.delete(:skip_instruct)
120
- dasherize = !options.has_key?(:dasherize) || options[:dasherize]
121
- root = dasherize ? options[:root].to_s.dasherize : options[:root].to_s
98
+ root = rename_key(options[:root].to_s, options)
122
99
 
123
100
  options[:builder].__send__(:method_missing, root) do
124
101
  each do |key, value|
@@ -145,7 +122,7 @@ module ActiveSupport #:nodoc:
145
122
  else
146
123
  type_name = XML_TYPE_NAMES[value.class.name]
147
124
 
148
- key = dasherize ? key.to_s.dasherize : key.to_s
125
+ key = rename_key(key.to_s, options)
149
126
 
150
127
  attributes = options[:skip_types] || value.nil? || type_name.nil? ? { } : { :type => type_name }
151
128
  if value.nil?
@@ -165,15 +142,16 @@ module ActiveSupport #:nodoc:
165
142
 
166
143
  end
167
144
 
145
+ def rename_key(key, options = {})
146
+ camelize = options.has_key?(:camelize) && options[:camelize]
147
+ dasherize = !options.has_key?(:dasherize) || options[:dasherize]
148
+ key = key.camelize if camelize
149
+ dasherize ? key.dasherize : key
150
+ end
151
+
168
152
  module ClassMethods
169
153
  def from_xml(xml)
170
- # TODO: Refactor this into something much cleaner that doesn't rely on XmlSimple
171
- typecast_xml_value(undasherize_keys(XmlSimple.xml_in_string(xml,
172
- 'forcearray' => false,
173
- 'forcecontent' => true,
174
- 'keeproot' => true,
175
- 'contentkey' => '__content__')
176
- ))
154
+ typecast_xml_value(unrename_keys(XmlMini.parse(xml)))
177
155
  end
178
156
 
179
157
  private
@@ -239,15 +217,15 @@ module ActiveSupport #:nodoc:
239
217
  end
240
218
  end
241
219
 
242
- def undasherize_keys(params)
220
+ def unrename_keys(params)
243
221
  case params.class.to_s
244
222
  when "Hash"
245
223
  params.inject({}) do |h,(k,v)|
246
- h[k.to_s.tr("-", "_")] = undasherize_keys(v)
224
+ h[k.to_s.underscore.tr("-", "_")] = unrename_keys(v)
247
225
  h
248
226
  end
249
227
  when "Array"
250
- params.map { |v| undasherize_keys(v) }
228
+ params.map { |v| unrename_keys(v) }
251
229
  else
252
230
  params
253
231
  end
@@ -91,6 +91,12 @@ class HashWithIndifferentAccess < Hash
91
91
  self.dup.update(hash)
92
92
  end
93
93
 
94
+ # Performs the opposite of merge, with the keys and values from the first hash taking precedence over the second.
95
+ # This overloaded definition prevents returning a regular hash, if reverse_merge is called on a HashWithDifferentAccess.
96
+ def reverse_merge(other_hash)
97
+ super other_hash.with_indifferent_access
98
+ end
99
+
94
100
  # Removes a specified key from the hash.
95
101
  def delete(key)
96
102
  super(convert_key(key))
@@ -38,7 +38,7 @@ module ActiveSupport #:nodoc:
38
38
  # Note that keys are NOT treated indifferently, meaning if you use strings for keys but assert symbols
39
39
  # as keys, this will fail.
40
40
  #
41
- # ==== Examples:
41
+ # ==== Examples
42
42
  # { :name => "Rob", :years => "28" }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key(s): years"
43
43
  # { :name => "Rob", :age => "28" }.assert_valid_keys("name", "age") # => raises "ArgumentError: Unknown key(s): name, age"
44
44
  # { :name => "Rob", :age => "28" }.assert_valid_keys(:name, :age) # => passes, raises nothing
@@ -24,10 +24,17 @@ module ActiveSupport #:nodoc:
24
24
  end
25
25
 
26
26
  # Replaces the hash with only the given keys.
27
+ # Returns a hash contained the removed key/value pairs
28
+ # {:a => 1, :b => 2, :c => 3, :d => 4}.slice!(:a, :b) # => {:c => 3, :d =>4}
27
29
  def slice!(*keys)
28
- replace(slice(*keys))
30
+ keys = keys.map! { |key| convert_key(key) } if respond_to?(:convert_key)
31
+ omit = slice(*self.keys - keys)
32
+ hash = slice(*keys)
33
+ replace(hash)
34
+ omit
29
35
  end
30
36
  end
31
37
  end
32
38
  end
33
39
  end
40
+
@@ -3,12 +3,12 @@
3
3
  class Logger
4
4
  def self.define_around_helper(level)
5
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
6
+ def around_#{level}(before_message, after_message, &block) # def around_debug(before_message, after_message, &block)
7
+ self.#{level}(before_message) # self.debug(before_message)
8
+ return_value = block.call(self) # return_value = block.call(self)
9
+ self.#{level}(after_message) # self.debug(after_message)
10
+ return return_value # return return_value
11
+ end # end
12
12
  end_eval
13
13
  end
14
14
  [:debug, :info, :error, :fatal].each {|level| define_around_helper(level) }
@@ -30,6 +30,8 @@ require 'logger'
30
30
  #
31
31
  # Note: This logger is deprecated in favor of ActiveSupport::BufferedLogger
32
32
  class Logger
33
+ ##
34
+ # :singleton-method:
33
35
  # Set to false to disable the silencer
34
36
  cattr_accessor :silencer
35
37
  self.silencer = true
@@ -64,9 +64,9 @@ module ActiveSupport
64
64
  # e.title # => "Megastars"
65
65
  def alias_attribute(new_name, old_name)
66
66
  module_eval <<-STR, __FILE__, __LINE__+1
67
- def #{new_name}; self.#{old_name}; end
68
- def #{new_name}?; self.#{old_name}?; end
69
- def #{new_name}=(v); self.#{old_name} = v; end
67
+ def #{new_name}; self.#{old_name}; end # def subject; self.title; end
68
+ def #{new_name}?; self.#{old_name}?; end # def subject?; self.title?; end
69
+ def #{new_name}=(v); self.#{old_name} = v; end # def subject=(v); self.title = v; end
70
70
  STR
71
71
  end
72
72
  end
@@ -22,10 +22,10 @@ class Module
22
22
  raise 'Default value or block required' unless !default.nil? || block
23
23
  define_method(sym, block_given? ? block : Proc.new { default })
24
24
  module_eval(<<-EVAL, __FILE__, __LINE__)
25
- def #{sym}=(value)
26
- class << self; attr_reader :#{sym} end
27
- @#{sym} = value
28
- end
25
+ def #{sym}=(value) # def age=(value)
26
+ class << self; attr_reader :#{sym} end # class << self; attr_reader :age end
27
+ @#{sym} = value # @age = value
28
+ end # end
29
29
  EVAL
30
30
  end
31
31
  end
@@ -15,17 +15,17 @@ class Module
15
15
  syms.each do |sym|
16
16
  next if sym.is_a?(Hash)
17
17
  class_eval(<<-EOS, __FILE__, __LINE__)
18
- unless defined? @@#{sym}
19
- @@#{sym} = nil
20
- end
21
-
22
- def self.#{sym}
23
- @@#{sym}
24
- end
25
-
26
- def #{sym}
27
- @@#{sym}
28
- end
18
+ unless defined? @@#{sym} # unless defined? @@pagination_options
19
+ @@#{sym} = nil # @@pagination_options = nil
20
+ end # end
21
+ #
22
+ def self.#{sym} # def self.pagination_options
23
+ @@#{sym} # @@pagination_options
24
+ end # end
25
+ #
26
+ def #{sym} # def pagination_options
27
+ @@#{sym} # @@pagination_options
28
+ end # end
29
29
  EOS
30
30
  end
31
31
  end
@@ -34,19 +34,19 @@ class Module
34
34
  options = syms.extract_options!
35
35
  syms.each do |sym|
36
36
  class_eval(<<-EOS, __FILE__, __LINE__)
37
- unless defined? @@#{sym}
38
- @@#{sym} = nil
39
- end
40
-
41
- def self.#{sym}=(obj)
42
- @@#{sym} = obj
43
- end
44
-
45
- #{"
46
- def #{sym}=(obj)
47
- @@#{sym} = obj
48
- end
49
- " unless options[:instance_writer] == false }
37
+ unless defined? @@#{sym} # unless defined? @@pagination_options
38
+ @@#{sym} = nil # @@pagination_options = nil
39
+ end # end
40
+ #
41
+ def self.#{sym}=(obj) # def self.pagination_options=(obj)
42
+ @@#{sym} = obj # @@pagination_options = obj
43
+ end # end
44
+ #
45
+ #{" #
46
+ def #{sym}=(obj) # def pagination_options=(obj)
47
+ @@#{sym} = obj # @@pagination_options = obj
48
+ end # end
49
+ " unless options[:instance_writer] == false } # # instance writer above is generated unless options[:instance_writer] == false
50
50
  EOS
51
51
  end
52
52
  end
@@ -72,6 +72,30 @@ class Module
72
72
  # invoice.customer_name # => "John Doe"
73
73
  # invoice.customer_address # => "Vimmersvej 13"
74
74
  #
75
+ # If the object to which you delegate can be nil, you may want to use the
76
+ # :allow_nil option. In that case, it returns nil instead of raising a
77
+ # NoMethodError exception:
78
+ #
79
+ # class Foo
80
+ # attr_accessor :bar
81
+ # def initialize(bar = nil)
82
+ # @bar = bar
83
+ # end
84
+ # delegate :zoo, :to => :bar
85
+ # end
86
+ #
87
+ # Foo.new.zoo # raises NoMethodError exception (you called nil.zoo)
88
+ #
89
+ # class Foo
90
+ # attr_accessor :bar
91
+ # def initialize(bar = nil)
92
+ # @bar = bar
93
+ # end
94
+ # delegate :zoo, :to => :bar, :allow_nil => true
95
+ # end
96
+ #
97
+ # Foo.new.zoo # returns nil
98
+ #
75
99
  def delegate(*methods)
76
100
  options = methods.pop
77
101
  unless options.is_a?(Hash) && to = options[:to]
@@ -84,11 +108,13 @@ class Module
84
108
 
85
109
  prefix = options[:prefix] && "#{options[:prefix] == true ? to : options[:prefix]}_"
86
110
 
111
+ allow_nil = options[:allow_nil] && "#{to} && "
112
+
87
113
  methods.each do |method|
88
114
  module_eval(<<-EOS, "(__DELEGATION__)", 1)
89
- def #{prefix}#{method}(*args, &block)
90
- #{to}.__send__(#{method.inspect}, *args, &block)
91
- end
115
+ def #{prefix}#{method}(*args, &block) # def customer_name(*args, &block)
116
+ #{allow_nil}#{to}.__send__(#{method.inspect}, *args, &block) # client && client.__send__(:name, *args, &block)
117
+ end # end
92
118
  EOS
93
119
  end
94
120
  end
@@ -26,11 +26,11 @@ class Module
26
26
  end
27
27
 
28
28
  module_eval(<<-EOS, __FILE__, __LINE__)
29
- def #{aliased_method}_with_synchronization#{punctuation}(*args, &block)
30
- #{with}.synchronize do
31
- #{aliased_method}_without_synchronization#{punctuation}(*args, &block)
32
- end
33
- end
29
+ def #{aliased_method}_with_synchronization#{punctuation}(*args, &block) # def expire_with_synchronization(*args, &block)
30
+ #{with}.synchronize do # @@lock.synchronize do
31
+ #{aliased_method}_without_synchronization#{punctuation}(*args, &block) # expire_without_synchronization(*args, &block)
32
+ end # end
33
+ end # end
34
34
  EOS
35
35
 
36
36
  alias_method_chain method, :synchronization
@@ -9,6 +9,7 @@ class Object
9
9
  #
10
10
  # Note: This method is defined as a default implementation for all Objects for Hash#to_query to work.
11
11
  def to_query(key)
12
+ require 'cgi' unless defined?(CGI) && defined?(CGI::escape)
12
13
  "#{CGI.escape(key.to_s)}=#{CGI.escape(to_param.to_s)}"
13
14
  end
14
- end
15
+ end
@@ -40,6 +40,21 @@ class Object
40
40
  value
41
41
  end
42
42
 
43
+ # Yields <code>x</code> to the block, and then returns <code>x</code>.
44
+ # The primary purpose of this method is to "tap into" a method chain,
45
+ # in order to perform operations on intermediate results within the chain.
46
+ #
47
+ # (1..10).tap { |x| puts "original: #{x.inspect}" }.to_a.
48
+ # tap { |x| puts "array: #{x.inspect}" }.
49
+ # select { |x| x%2 == 0 }.
50
+ # tap { |x| puts "evens: #{x.inspect}" }.
51
+ # map { |x| x*x }.
52
+ # tap { |x| puts "squares: #{x.inspect}" }
53
+ def tap
54
+ yield self
55
+ self
56
+ end unless Object.respond_to?(:tap)
57
+
43
58
  # An elegant way to factor duplication out of options passed to a series of
44
59
  # method calls. Each method called in the block, with the block variable as
45
60
  # the receiver, will have its options merged with the default +options+ hash
@@ -71,4 +86,5 @@ class Object
71
86
  def acts_like?(duck)
72
87
  respond_to? "acts_like_#{duck}?"
73
88
  end
89
+
74
90
  end
@@ -15,7 +15,7 @@ module ActiveSupport #:nodoc:
15
15
  end
16
16
  # Gives a human readable format of the range.
17
17
  #
18
- # ==== Example:
18
+ # ==== Example
19
19
  #
20
20
  # [1..100].to_formatted_s # => "1..100"
21
21
  def to_formatted_s(format = :default)
@@ -1,34 +1,39 @@
1
- require 'rexml/document'
2
- require 'rexml/entity'
3
-
4
1
  # Fixes the rexml vulnerability disclosed at:
5
2
  # http://www.ruby-lang.org/en/news/2008/08/23/dos-vulnerability-in-rexml/
6
3
  # This fix is identical to rexml-expansion-fix version 1.0.1
4
+ require 'rexml/rexml'
7
5
 
8
6
  # Earlier versions of rexml defined REXML::Version, newer ones REXML::VERSION
9
- unless REXML::Document.respond_to?(:entity_expansion_limit=)
10
- module REXML
11
- class Entity < Child
12
- undef_method :unnormalized
13
- def unnormalized
14
- document.record_entity_expansion! if document
15
- v = value()
16
- return nil if v.nil?
17
- @unnormalized = Text::unnormalize(v, parent)
18
- @unnormalized
19
- end
20
- end
21
- class Document < Element
22
- @@entity_expansion_limit = 10_000
23
- def self.entity_expansion_limit= val
24
- @@entity_expansion_limit = val
7
+ unless (defined?(REXML::VERSION) ? REXML::VERSION : REXML::Version) > "3.1.7.2"
8
+ require 'rexml/document'
9
+
10
+ # REXML in 1.8.7 has the patch but didn't update Version from 3.1.7.2.
11
+ unless REXML::Document.respond_to?(:entity_expansion_limit=)
12
+ require 'rexml/entity'
13
+
14
+ module REXML
15
+ class Entity < Child
16
+ undef_method :unnormalized
17
+ def unnormalized
18
+ document.record_entity_expansion! if document
19
+ v = value()
20
+ return nil if v.nil?
21
+ @unnormalized = Text::unnormalize(v, parent)
22
+ @unnormalized
23
+ end
25
24
  end
25
+ class Document < Element
26
+ @@entity_expansion_limit = 10_000
27
+ def self.entity_expansion_limit= val
28
+ @@entity_expansion_limit = val
29
+ end
26
30
 
27
- def record_entity_expansion!
28
- @number_of_expansions ||= 0
29
- @number_of_expansions += 1
30
- if @number_of_expansions > @@entity_expansion_limit
31
- raise "Number of entity expansions exceeded, processing aborted."
31
+ def record_entity_expansion!
32
+ @number_of_expansions ||= 0
33
+ @number_of_expansions += 1
34
+ if @number_of_expansions > @@entity_expansion_limit
35
+ raise "Number of entity expansions exceeded, processing aborted."
36
+ end
32
37
  end
33
38
  end
34
39
  end