diff options
author | Jeremy Kemper <jeremy@bitsweat.net> | 2008-09-02 18:21:36 +0200 |
---|---|---|
committer | Jeremy Kemper <jeremy@bitsweat.net> | 2008-09-02 18:32:54 +0200 |
commit | 6f932b4790371e548c0df9033da96b2cf8f51dcc (patch) | |
tree | b62c70a90a1716f49df5630e14ef1d847e7a7138 /activesupport | |
parent | 300754509b6990b387b056c122e90f50a79eeb81 (diff) | |
parent | ebfa43c423ac16bb699424d8d3db11855dd79a91 (diff) | |
download | rails-6f932b4790371e548c0df9033da96b2cf8f51dcc.tar.gz rails-6f932b4790371e548c0df9033da96b2cf8f51dcc.tar.bz2 rails-6f932b4790371e548c0df9033da96b2cf8f51dcc.zip |
Database connections are now pooled, one pool per #establish_connection call.
Pools start out empty and grow as necessary to a maximum size (default is 5,
configure size with key 'pool' in your database configuration). If no
connections are available, a thread will wait up to a 'wait_timeout' time
(default is 5 seconds).
Connections are verified and reset when checked out from the pool (usually
upon first access to ActiveRecord::Base.connection), and returned back to the
pool after each request.
If you would like to use connection pools outside of ActionPack, there is an
ActiveRecord::Base.connection_pool method that gives you access to the pool,
and you can manually checkout/checkin connections, or supply a block to
ActiveRecord::Base.connection_pool.with_connection which takes care of the
checkout/checkin for you.
[#936 state:resolved]
Diffstat (limited to 'activesupport')
15 files changed, 264 insertions, 193 deletions
diff --git a/activesupport/lib/active_support/core_ext/module.rb b/activesupport/lib/active_support/core_ext/module.rb index 392ba99f4e..da8d28ec13 100644 --- a/activesupport/lib/active_support/core_ext/module.rb +++ b/activesupport/lib/active_support/core_ext/module.rb @@ -9,6 +9,15 @@ require 'active_support/core_ext/module/aliasing' require 'active_support/core_ext/module/model_naming' require 'active_support/core_ext/module/synchronization' +module ActiveSupport + module CoreExtensions + # Various extensions for the Ruby core Module class. + module Module + # Nothing here. Only defined for API documentation purposes. + end + end +end + class Module - include ActiveSupport::CoreExt::Module::ModelNaming + include ActiveSupport::CoreExtensions::Module end diff --git a/activesupport/lib/active_support/core_ext/module/aliasing.rb b/activesupport/lib/active_support/core_ext/module/aliasing.rb index 1894e3b0a2..e640f64520 100644 --- a/activesupport/lib/active_support/core_ext/module/aliasing.rb +++ b/activesupport/lib/active_support/core_ext/module/aliasing.rb @@ -1,70 +1,74 @@ -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}" - - 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 +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? + + with_method, without_method = "#{aliased_target}_with_#{feature}#{punctuation}", "#{aliased_target}_without_#{feature}#{punctuation}" - # 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 #{new_name}?; self.#{old_name}?; end - def #{new_name}=(v); self.#{old_name} = v; end - STR + 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 #{new_name}?; self.#{old_name}?; end + def #{new_name}=(v); self.#{old_name} = v; end + STR + end + end 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 45f3e4bf5c..8beaff4b82 100644 --- a/activesupport/lib/active_support/core_ext/module/introspection.rb +++ b/activesupport/lib/active_support/core_ext/module/introspection.rb @@ -1,86 +1,90 @@ -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 +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 - # 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 + # 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 - 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 = {} + 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 - ancestors.each do |anc| - next if anc == self - anc.constants.each { |const| inherited[const] = anc.const_get(const) } + 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 - constants.select do |const| - !inherited.key?(const) || inherited[const].object_id != const_get(const).object_id + # 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 - 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/module/model_naming.rb b/activesupport/lib/active_support/core_ext/module/model_naming.rb index 5518f5417b..3ec4f3ba11 100644 --- a/activesupport/lib/active_support/core_ext/module/model_naming.rb +++ b/activesupport/lib/active_support/core_ext/module/model_naming.rb @@ -11,12 +11,12 @@ module ActiveSupport end end - module CoreExt + module CoreExtensions module Module - module ModelNaming - def model_name - @model_name ||= ModelName.new(name) - end + # Returns an ActiveSupport::ModelName object for module. It can be + # used to retrieve all kinds of naming-related information. + def model_name + @model_name ||= ModelName.new(name) end end end diff --git a/activesupport/lib/active_support/core_ext/object/misc.rb b/activesupport/lib/active_support/core_ext/object/misc.rb index 8384a12327..06a7d05702 100644 --- a/activesupport/lib/active_support/core_ext/object/misc.rb +++ b/activesupport/lib/active_support/core_ext/object/misc.rb @@ -1,9 +1,4 @@ class Object - unless respond_to?(:send!) - # Anticipating Ruby 1.9 neutering send - alias send! send - end - # A Ruby-ized realization of the K combinator, courtesy of Mikael Brockman. # # def foo diff --git a/activesupport/lib/active_support/core_ext/rexml.rb b/activesupport/lib/active_support/core_ext/rexml.rb new file mode 100644 index 0000000000..af8ce3af47 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/rexml.rb @@ -0,0 +1,35 @@ +require 'rexml/document' +require 'rexml/entity' + +# Fixes the rexml vulnerability disclosed at: +# http://www.ruby-lang.org/en/news/2008/08/23/dos-vulnerability-in-rexml/ +# This fix is identical to rexml-expansion-fix version 1.0.1 + +unless REXML::VERSION > "3.1.7.2" + module REXML + class Entity < Child + undef_method :unnormalized + def unnormalized + document.record_entity_expansion! if document + v = value() + return nil if v.nil? + @unnormalized = Text::unnormalize(v, parent) + @unnormalized + end + end + class Document < Element + @@entity_expansion_limit = 10_000 + def self.entity_expansion_limit= val + @@entity_expansion_limit = val + end + + def record_entity_expansion! + @number_of_expansions ||= 0 + @number_of_expansions += 1 + if @number_of_expansions > @@entity_expansion_limit + raise "Number of entity expansions exceeded, processing aborted." + end + end + 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 079ecdd48e..9d8eb73908 100644 --- a/activesupport/lib/active_support/core_ext/time/zones.rb +++ b/activesupport/lib/active_support/core_ext/time/zones.rb @@ -78,7 +78,7 @@ module ActiveSupport #:nodoc: # # 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)) + ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.__send__(:get_zone, zone)) end end end diff --git a/activesupport/lib/active_support/option_merger.rb b/activesupport/lib/active_support/option_merger.rb index c77bca1ac9..b563b093ed 100644 --- a/activesupport/lib/active_support/option_merger.rb +++ b/activesupport/lib/active_support/option_merger.rb @@ -11,7 +11,7 @@ module ActiveSupport private def method_missing(method, *arguments, &block) arguments << (arguments.last.respond_to?(:to_hash) ? @options.deep_merge(arguments.pop) : @options.dup) - @context.send!(method, *arguments, &block) + @context.__send__(method, *arguments, &block) end end end diff --git a/activesupport/lib/active_support/testing/core_ext/test/unit/assertions.rb b/activesupport/lib/active_support/testing/core_ext/test/unit/assertions.rb index 70a44eab8c..63d1ba6507 100644 --- a/activesupport/lib/active_support/testing/core_ext/test/unit/assertions.rb +++ b/activesupport/lib/active_support/testing/core_ext/test/unit/assertions.rb @@ -36,7 +36,11 @@ module Test # post :delete, :id => ... # end def assert_difference(expressions, difference = 1, message = nil, &block) - expression_evaluations = Array(expressions).collect{ |expression| lambda { eval(expression, block.send!(:binding)) } } + expression_evaluations = Array(expressions).map do |expression| + lambda do + eval(expression, block.__send__(:binding)) + end + end original_values = expression_evaluations.inject([]) { |memo, expression| memo << expression.call } yield diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index 4866fa0dc8..75591b7c34 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -275,7 +275,7 @@ module ActiveSupport end def marshal_load(variables) - initialize(variables[0].utc, ::Time.send!(:get_zone, variables[1]), variables[2].utc) + initialize(variables[0].utc, ::Time.__send__(:get_zone, variables[1]), variables[2].utc) end # Ensure proxy class responds to all methods that underlying time instance responds to. diff --git a/activesupport/lib/active_support/vendor/i18n-0.0.1/i18n/backend/simple.rb b/activesupport/lib/active_support/vendor/i18n-0.0.1/i18n/backend/simple.rb index 2e966a51be..da89b30c54 100644 --- a/activesupport/lib/active_support/vendor/i18n-0.0.1/i18n/backend/simple.rb +++ b/activesupport/lib/active_support/vendor/i18n-0.0.1/i18n/backend/simple.rb @@ -3,6 +3,9 @@ require 'strscan' module I18n module Backend class Simple + INTERPOLATION_RESERVED_KEYS = %w(scope default) + MATCH = /(\\\\)?\{\{([^\}]+)\}\}/ + # Accepts a list of paths to translation files. Loads translations from # plain Ruby (*.rb) or YAML files (*.yml). See #load_rb and #load_yml # for details. @@ -114,29 +117,29 @@ module I18n # the <tt>{{...}}</tt> key in a string (once for the string and once for the # interpolation). def interpolate(locale, string, values = {}) - return string if !string.is_a?(String) + return string unless string.is_a?(String) string = string.gsub(/%d/, '{{count}}').gsub(/%s/, '{{value}}') + if string.respond_to?(:force_encoding) - original_encoding = string.encoding - string.force_encoding(Encoding::BINARY) - end - s = StringScanner.new(string) - - while s.skip_until(/\{\{/) - s.string[s.pos - 3, 1] = '' and next if s.pre_match[-1, 1] == '\\' - start_pos = s.pos - 2 - key = s.scan_until(/\}\}/)[0..-3] - end_pos = s.pos - 1 + original_encoding = string.encoding + string.force_encoding(Encoding::BINARY) + end - raise ReservedInterpolationKey.new(key, string) if %w(scope default).include?(key) - raise MissingInterpolationArgument.new(key, string) unless values.has_key? key.to_sym + result = string.gsub(MATCH) do + escaped, pattern, key = $1, $2, $2.to_sym - s.string[start_pos..end_pos] = values[key.to_sym].to_s - s.unscan + if escaped + pattern + elsif INTERPOLATION_RESERVED_KEYS.include?(pattern) + raise ReservedInterpolationKey.new(pattern, string) + elsif !values.include?(key) + raise MissingInterpolationArgument.new(pattern, string) + else + values[key].to_s + end end - - result = s.string + result.force_encoding(original_encoding) if original_encoding result end diff --git a/activesupport/test/buffered_logger_test.rb b/activesupport/test/buffered_logger_test.rb index 6319c09210..28dd34334f 100644 --- a/activesupport/test/buffered_logger_test.rb +++ b/activesupport/test/buffered_logger_test.rb @@ -134,6 +134,7 @@ class BufferedLoggerTest < Test::Unit::TestCase a.join b.join - assert_equal "a\nb\nc\nx\ny\nz\n", @output.string + assert @output.string.include?("a\nb\nc\n") + assert @output.string.include?("x\ny\nz\n") end end diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index fc8ed45358..7a414e946f 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -62,7 +62,7 @@ class HashExtTest < Test::Unit::TestCase @symbols = @symbols.with_indifferent_access @mixed = @mixed.with_indifferent_access - assert_equal 'a', @strings.send!(:convert_key, :a) + assert_equal 'a', @strings.__send__(:convert_key, :a) assert_equal 1, @strings.fetch('a') assert_equal 1, @strings.fetch(:a.to_s) @@ -75,9 +75,9 @@ class HashExtTest < Test::Unit::TestCase hashes.each do |name, hash| method_map.sort_by { |m| m.to_s }.each do |meth, expected| - assert_equal(expected, hash.send!(meth, 'a'), + assert_equal(expected, hash.__send__(meth, 'a'), "Calling #{name}.#{meth} 'a'") - assert_equal(expected, hash.send!(meth, :a), + assert_equal(expected, hash.__send__(meth, :a), "Calling #{name}.#{meth} :a") end end @@ -733,7 +733,7 @@ class HashToXmlTest < Test::Unit::TestCase def test_empty_string_works_for_typecast_xml_value assert_nothing_raised do - Hash.send!(:typecast_xml_value, "") + Hash.__send__(:typecast_xml_value, "") end end @@ -839,6 +839,27 @@ class QueryTest < Test::Unit::TestCase :person => {:id => [20, 10]} end + def test_expansion_count_is_limited + assert_raises RuntimeError do + attack_xml = <<-EOT + <?xml version="1.0" encoding="UTF-8"?> + <!DOCTYPE member [ + <!ENTITY a "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;"> + <!ENTITY b "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;"> + <!ENTITY c "&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;"> + <!ENTITY d "&e;&e;&e;&e;&e;&e;&e;&e;&e;&e;"> + <!ENTITY e "&f;&f;&f;&f;&f;&f;&f;&f;&f;&f;"> + <!ENTITY f "&g;&g;&g;&g;&g;&g;&g;&g;&g;&g;"> + <!ENTITY g "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"> + ]> + <member> + &a; + </member> + EOT + Hash.from_xml(attack_xml) + end + end + private def assert_query_equal(expected, actual, message = nil) assert_equal expected.split('&'), actual.to_query.split('&') diff --git a/activesupport/test/core_ext/object_and_class_ext_test.rb b/activesupport/test/core_ext/object_and_class_ext_test.rb index b0a746fdc7..e88dcb52d5 100644 --- a/activesupport/test/core_ext/object_and_class_ext_test.rb +++ b/activesupport/test/core_ext/object_and_class_ext_test.rb @@ -108,11 +108,6 @@ class ClassExtTest < Test::Unit::TestCase end class ObjectTests < Test::Unit::TestCase - def test_send_bang_aliases_send_before_19 - assert_respond_to 'a', :send! - assert_equal 1, 'a'.send!(:size) - end - def test_suppress_re_raises assert_raises(LoadError) { suppress(ArgumentError) {raise LoadError} } end diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb index 39c9c74c94..18ad784837 100644 --- a/activesupport/test/dependencies_test.rb +++ b/activesupport/test/dependencies_test.rb @@ -146,42 +146,42 @@ class DependenciesTest < Test::Unit::TestCase def test_directories_manifest_as_modules_unless_const_defined with_loading 'autoloading_fixtures' do assert_kind_of Module, ModuleFolder - Object.send! :remove_const, :ModuleFolder + Object.__send__ :remove_const, :ModuleFolder end end def test_module_with_nested_class with_loading 'autoloading_fixtures' do assert_kind_of Class, ModuleFolder::NestedClass - Object.send! :remove_const, :ModuleFolder + Object.__send__ :remove_const, :ModuleFolder end end def test_module_with_nested_inline_class with_loading 'autoloading_fixtures' do assert_kind_of Class, ModuleFolder::InlineClass - Object.send! :remove_const, :ModuleFolder + Object.__send__ :remove_const, :ModuleFolder end end def test_directories_may_manifest_as_nested_classes with_loading 'autoloading_fixtures' do assert_kind_of Class, ClassFolder - Object.send! :remove_const, :ClassFolder + Object.__send__ :remove_const, :ClassFolder end end def test_class_with_nested_class with_loading 'autoloading_fixtures' do assert_kind_of Class, ClassFolder::NestedClass - Object.send! :remove_const, :ClassFolder + Object.__send__ :remove_const, :ClassFolder end end def test_class_with_nested_inline_class with_loading 'autoloading_fixtures' do assert_kind_of Class, ClassFolder::InlineClass - Object.send! :remove_const, :ClassFolder + Object.__send__ :remove_const, :ClassFolder end end @@ -190,7 +190,7 @@ class DependenciesTest < Test::Unit::TestCase assert_kind_of Class, ClassFolder::ClassFolderSubclass assert_kind_of Class, ClassFolder assert_equal 'indeed', ClassFolder::ClassFolderSubclass::ConstantInClassFolder - Object.send! :remove_const, :ClassFolder + Object.__send__ :remove_const, :ClassFolder end end @@ -199,7 +199,7 @@ class DependenciesTest < Test::Unit::TestCase sibling = ModuleFolder::NestedClass.class_eval "NestedSibling" assert defined?(ModuleFolder::NestedSibling) assert_equal ModuleFolder::NestedSibling, sibling - Object.send! :remove_const, :ModuleFolder + Object.__send__ :remove_const, :ModuleFolder end end @@ -208,7 +208,7 @@ class DependenciesTest < Test::Unit::TestCase assert ! defined?(ModuleFolder) assert_raises(NameError) { ModuleFolder::Object } assert_raises(NameError) { ModuleFolder::NestedClass::Object } - Object.send! :remove_const, :ModuleFolder + Object.__send__ :remove_const, :ModuleFolder end end |