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.

Files changed (63) hide show
  1. data/CHANGELOG +163 -4
  2. data/lib/active_support.rb +8 -3
  3. data/lib/active_support/breakpoint.rb +1 -1
  4. data/lib/active_support/caching_tools.rb +62 -0
  5. data/lib/active_support/clean_logger.rb +3 -1
  6. data/lib/active_support/core_ext/array.rb +16 -0
  7. data/lib/active_support/core_ext/array/conversions.rb +18 -2
  8. data/lib/active_support/core_ext/blank.rb +14 -2
  9. data/lib/active_support/core_ext/class.rb +3 -0
  10. data/lib/active_support/core_ext/class/attribute_accessors.rb +44 -0
  11. data/lib/active_support/{class_inheritable_attributes.rb → core_ext/class/inheritable_attributes.rb} +2 -4
  12. data/lib/active_support/core_ext/class/removal.rb +24 -0
  13. data/lib/active_support/core_ext/date/conversions.rb +2 -0
  14. data/lib/active_support/core_ext/enumerable.rb +23 -1
  15. data/lib/active_support/core_ext/exception.rb +0 -1
  16. data/lib/active_support/core_ext/hash.rb +4 -0
  17. data/lib/active_support/core_ext/hash/conversions.rb +44 -0
  18. data/lib/active_support/core_ext/hash/diff.rb +11 -0
  19. data/lib/active_support/core_ext/hash/indifferent_access.rb +23 -4
  20. data/lib/active_support/core_ext/integer/inflections.rb +1 -1
  21. data/lib/active_support/core_ext/kernel.rb +4 -79
  22. data/lib/active_support/core_ext/kernel/agnostics.rb +11 -0
  23. data/lib/active_support/core_ext/kernel/daemonizing.rb +15 -0
  24. data/lib/active_support/core_ext/kernel/reporting.rb +51 -0
  25. data/lib/active_support/core_ext/kernel/requires.rb +24 -0
  26. data/lib/active_support/core_ext/logger.rb +16 -0
  27. data/lib/active_support/core_ext/module.rb +5 -0
  28. data/lib/active_support/core_ext/module/attribute_accessors.rb +44 -0
  29. data/lib/active_support/core_ext/module/delegation.rb +16 -0
  30. data/lib/active_support/core_ext/module/inclusion.rb +11 -0
  31. data/lib/active_support/core_ext/module/introspection.rb +21 -0
  32. data/lib/active_support/core_ext/module/loading.rb +13 -0
  33. data/lib/active_support/core_ext/numeric/time.rb +14 -1
  34. data/lib/active_support/core_ext/object.rb +2 -0
  35. data/lib/active_support/core_ext/object/extending.rb +47 -0
  36. data/lib/active_support/core_ext/object/misc.rb +34 -0
  37. data/lib/active_support/core_ext/proc.rb +12 -0
  38. data/lib/active_support/core_ext/string.rb +2 -0
  39. data/lib/active_support/core_ext/string/access.rb +2 -2
  40. data/lib/active_support/core_ext/string/inflections.rb +10 -3
  41. data/lib/active_support/core_ext/string/iterators.rb +17 -0
  42. data/lib/active_support/core_ext/symbol.rb +5 -0
  43. data/lib/active_support/core_ext/time/calculations.rb +15 -0
  44. data/lib/active_support/core_ext/time/conversions.rb +1 -0
  45. data/lib/active_support/dependencies.rb +81 -159
  46. data/lib/active_support/inflections.rb +48 -48
  47. data/lib/active_support/inflector.rb +17 -5
  48. data/lib/active_support/json.rb +37 -0
  49. data/lib/active_support/json/encoders.rb +25 -0
  50. data/lib/active_support/json/encoders/core.rb +65 -0
  51. data/lib/active_support/option_merger.rb +25 -0
  52. data/lib/active_support/ordered_options.rb +23 -11
  53. data/lib/active_support/reloadable.rb +30 -0
  54. data/lib/active_support/vendor/builder.rb +13 -0
  55. data/lib/active_support/vendor/builder/blankslate.rb +53 -0
  56. data/lib/active_support/vendor/builder/xmlbase.rb +143 -0
  57. data/lib/active_support/vendor/builder/xmlevents.rb +63 -0
  58. data/lib/active_support/vendor/builder/xmlmarkup.rb +308 -0
  59. data/lib/active_support/version.rb +2 -2
  60. metadata +113 -69
  61. data/lib/active_support/class_attribute_accessors.rb +0 -57
  62. data/lib/active_support/core_ext/object_and_class.rb +0 -44
  63. data/lib/active_support/module_attribute_accessors.rb +0 -57
data/CHANGELOG CHANGED
@@ -1,12 +1,171 @@
1
- *1.2.5* (December 13th, 2005)
1
+ *1.3.0* (March 27th, 2005)
2
2
 
3
- * Become part of Rails 1.0
3
+ * When possible, avoid incorrectly obtaining constants from parent modules. Fixes #4221. [Nicholas Seckar]
4
4
 
5
+ * Add more tests for dependencies; refactor existing cases. [Nicholas Seckar]
5
6
 
6
- *1.2.4* (December 7th, 2005)
7
+ * Move Module#parent and Module#as_load_path into core_ext. Add Module#parent. [Nicholas Seckar]
7
8
 
8
- * Rename Version constant to VERSION. #2802 [Marcel Molina Jr.]
9
+ * Add CachingTools::HashCaching to simplify the creation of nested, autofilling hashes. [Nicholas Seckar]
10
+
11
+ * Remove a hack intended to avoid unloading the same class twice, but which would not work anyways. [Nicholas Seckar]
12
+
13
+ * Update Object.subclasses_of to locate nested classes. This affects Object.remove_subclasses_of in that nested classes will now be unloaded. [Nicholas Seckar]
14
+
15
+ * Update Object.remove_subclasses_of to use Class.remove_class, reducing duplication. [Nicholas Seckar]
16
+
17
+ * Added Fixnum#seconds for consistency, so you can say 5.minutes + 30.seconds instead of 5.minutes + 30 #4389 [François Beausoleil]
18
+
19
+ * Added option to String#camelize to generate lower-cased camel case by passing in :lower, like "super_man".camelize(:lower) # => "superMan" [DHH]
20
+
21
+ * Added Hash#diff to show the difference between two hashes [Chris McGrath]
22
+
23
+ * Added Time#advance to do precise time time calculations for cases where a month being approximated to 30 days won't do #1860 [Rick Olson]
24
+
25
+ * Enhance Inflector.underscore to convert '-' into '_' (as the inverse of Inflector.dasherize) [Jamis Buck]
26
+
27
+ * Switched to_xml to use the xml schema format for datetimes. This allows the encoding of time zones and should improve operability. [Koz]
28
+
29
+ * Added a note to the documentation for the Date related Numeric extensions to indicate that they're
30
+ approximations and shouldn't be used for critical calculations. [Koz]
31
+
32
+ * Added Hash#to_xml and Array#to_xml that makes it much easier to produce XML from basic structures [DHH]. Examples:
33
+
34
+ { :name => "David", :street_name => "Paulina", :age => 26, :moved_on => Date.new(2005, 11, 15) }.to_xml
35
+
36
+ ...returns:
37
+
38
+ <person>
39
+ <street-name>Paulina</street-name>
40
+ <name>David</name>
41
+ <age type="integer">26</age>
42
+ <moved-on type="date">2005-11-15</moved-on>
43
+ </person>
44
+
45
+ * Moved Jim Weirich's wonderful Builder from Action Pack to Active Support (it's simply too useful to be stuck in AP) [DHH]
46
+
47
+ * Fixed that Array#to_sentence will return "" on an empty array instead of ", and" #3842, #4031 [rubyonrails@beautifulpixel.com]
48
+
49
+ * Add Enumerable#group_by for grouping collections based on the result of some
50
+ block. Useful, for example, for grouping records by date.
51
+
52
+ ex.
53
+
54
+ latest_transcripts.group_by(&:day).each do |day, transcripts|
55
+ p "#{day} -> #{transcripts.map(&:class) * ', '}"
56
+ end
57
+ "2006-03-01 -> Transcript"
58
+ "2006-02-28 -> Transcript"
59
+ "2006-02-27 -> Transcript, Transcript"
60
+ "2006-02-26 -> Transcript, Transcript"
61
+
62
+ Add Array#in_groups_of, for iterating over an array in groups of a certain
63
+ size.
64
+
65
+ ex.
66
+
67
+ %w(1 2 3 4 5 6 7).in_groups_of(3) {|g| p g}
68
+ ["1", "2", "3"]
69
+ ["4", "5", "6"]
70
+ ["7", nil, nil]
71
+
72
+ [Marcel Molina Jr., Sam Stephenson]
73
+
74
+ * Added Kernel#daemonize to turn the current process into a daemon that can be killed with a TERM signal [DHH]
75
+
76
+ * Add 'around' methods to Logger, to make it easy to log before and after messages for a given block as requested in #3809. [Michael Koziarski] Example:
77
+
78
+ logger.around_info("Start rendering component (#{options.inspect}): ",
79
+ "\n\nEnd of component rendering") { yield }
80
+
81
+ * Added Time#beginning_of_quarter #3607 [cohen.jeff@gmail.com]
82
+
83
+ * Fix Object.subclasses_of to only return currently defined objects [Jonathan Viney <jonathan@bluewire.net.nz>]
84
+
85
+ * Fix constantize to properly handle names beginning with '::'. [Nicholas Seckar]
86
+
87
+ * Make String#last return the string instead of nil when it is shorter than the limit [Scott Barron].
88
+
89
+ * Added delegation support to Module that allows multiple delegations at once (unlike Forwardable in the stdlib) [DHH]. Example:
9
90
 
91
+ class Account < ActiveRecord::Base
92
+ has_one :subscription
93
+ delegate :free?, :paying?, :to => :subscription
94
+ delegate :overdue?, :to => "subscription.last_payment"
95
+ end
96
+
97
+ account.free? # => account.subscription.free?
98
+ account.overdue? # => account.subscription.last_payment.overdue?
99
+
100
+ * Fix Reloadable to handle the case where a class that has been 'removed' has not yet been garbage collected. [Nicholas Seckar]
101
+
102
+ * Don't allow Reloadable to be included into Modules.
103
+
104
+ * Remove LoadingModule. [Nicholas Seckar]
105
+
106
+ * Add documentation for Reloadable::Subclasses. [Nicholas Seckar]
107
+
108
+ * Add Reloadable::Subclasses which handles the common case where a base class should not be reloaded, but its subclasses should be. [Nicholas Seckar]
109
+
110
+ * Further improvements to reloading code [Nicholas Seckar, Trevor Squires]
111
+
112
+ - All classes/modules which include Reloadable can define reloadable? for fine grained control of reloading
113
+ - Class.remove_class uses Module#parent to access the parent module
114
+ - Class.remove_class expanded to handle multiple classes in a single call
115
+ - LoadingModule.clear! has been removed as it is no longer required
116
+ - Module#remove_classes_including has been removed in favor of Reloadable.reloadable_classes
117
+
118
+ * Added reusable reloading support through the inclusion of the Relodable module that all subclasses of ActiveRecord::Base, ActiveRecord::Observer, ActiveController::Base, and ActionMailer::Base automatically gets. This means that these classes will be reloaded by the dispatcher when Dependencies.mechanism = :load. You can make your own models reloadable easily:
119
+
120
+ class Setting
121
+ include Reloadable
122
+ end
123
+
124
+ Reloading a class is done by removing its constant which will cause it to be loaded again on the next reference. [DHH]
125
+
126
+ * Added auto-loading support for classes in modules, so Conductor::Migration will look for conductor/migration.rb and Conductor::Database::Settings will look for conductor/database/settings.rb [Nicholas Seckar]
127
+
128
+ * Add Object#instance_exec, like instance_eval but passes its arguments to the block. (Active Support will not override the Ruby 1.9 implementation of this method.) [Sam Stephenson]
129
+
130
+ * Add Proc#bind(object) for changing a proc or block's self by returning a Method bound to the given object. Based on why the lucky stiff's "cloaker" method. [Sam Stephenson]
131
+
132
+ * Fix merge and dup for hashes with indifferent access #3404 [kenneth.miller@bitfield.net]
133
+
134
+ * Fix the requires in option_merger_test to unbreak AS tests. [Sam Stephenson]
135
+
136
+ * Make HashWithIndifferentAccess#update behave like Hash#update by returning the hash. #3419, #3425 [asnem@student.ethz.ch, JanPrill@blauton.de, Marcel Molina Jr.]
137
+
138
+ * Add ActiveSupport::JSON and Object#to_json for converting Ruby objects to JSON strings. [Sam Stephenson]
139
+
140
+ * Add Object#with_options for DRYing up multiple calls to methods having shared options. [Sam Stephenson] Example:
141
+
142
+ ActionController::Routing::Routes.draw do |map|
143
+ # Account routes
144
+ map.with_options(:controller => 'account') do |account|
145
+ account.home '', :action => 'dashboard'
146
+ account.signup 'signup', :action => 'new'
147
+ account.logout 'logout', :action => 'logout'
148
+ end
149
+ end
150
+
151
+ * Introduce Dependencies.warnings_on_first_load setting. If true, enables warnings on first load of a require_dependency. Otherwise, loads without warnings. Disabled (set to false) by default. [Jeremy Kemper]
152
+
153
+ * Active Support is warnings-safe. #1792 [Eric Hodel]
154
+
155
+ * Introduce enable_warnings counterpart to silence_warnings. Turn warnings on when loading a file for the first time if Dependencies.mechanism == :load. Common mistakes such as redefined methods will print warnings to stderr. [Jeremy Kemper]
156
+
157
+ * Add Symbol#to_proc, which allows for, e.g. [:foo, :bar].map(&:to_s). [Marcel Molina Jr.]
158
+
159
+ * Added the following methods [Marcel Molina Jr., Sam Stephenson]:
160
+ * Object#copy_instance_variables_from(object) to copy instance variables from one object to another
161
+ * Object#extended_by to get an instance's included/extended modules
162
+ * Object#extend_with_included_modules_from(object) to extend an instance with the modules from another instance
163
+
164
+ *1.2.5* (December 13th, 2005)
165
+
166
+ * Become part of Rails 1.0
167
+
168
+ * Rename Version constant to VERSION. #2802 [Marcel Molina Jr.]
10
169
 
11
170
  *1.2.3* (November 7th, 2005)
12
171
 
@@ -22,15 +22,20 @@
22
22
  #++
23
23
 
24
24
  $:.unshift(File.dirname(__FILE__))
25
+ $:.unshift(File.dirname(__FILE__) + "/active_support/vendor")
26
+
27
+ require 'builder'
25
28
 
26
- require 'active_support/class_attribute_accessors'
27
- require 'active_support/class_inheritable_attributes'
28
29
  require 'active_support/inflector'
29
30
 
30
31
  require 'active_support/core_ext'
31
32
  require 'active_support/clean_logger'
32
33
  require 'active_support/dependencies'
34
+ require 'active_support/reloadable'
33
35
 
34
36
  require 'active_support/ordered_options'
37
+ require 'active_support/option_merger'
38
+
39
+ require 'active_support/values/time_zone'
35
40
 
36
- require 'active_support/values/time_zone'
41
+ require 'active_support/json'
@@ -16,7 +16,7 @@
16
16
  # license please contact me.
17
17
 
18
18
  require 'irb'
19
- require File.dirname(__FILE__) + '/binding_of_caller'
19
+ require File.dirname(__FILE__) + '/binding_of_caller' unless defined? Binding.of_caller
20
20
  require 'drb'
21
21
  require 'drb/acl'
22
22
 
@@ -0,0 +1,62 @@
1
+ module ActiveSupport
2
+ module CachingTools #:nodoc:
3
+
4
+ # Provide shortcuts to simply the creation of nested default hashes. This
5
+ # pattern is useful, common practice, and unsightly when done manually.
6
+ module HashCaching
7
+ # Dynamically create a nested hash structure used to cache calls to +method_name+
8
+ # The cache method is named +#{method_name}_cache+ unless :as => :alternate_name
9
+ # is given.
10
+ #
11
+ # The hash structure is created using nested Hash.new. For example:
12
+ #
13
+ # def slow_method(a, b) a ** b end
14
+ #
15
+ # can be cached using hash_cache :slow_method, which will define the method
16
+ # slow_method_cache. We can then find the result of a ** b using:
17
+ #
18
+ # slow_method_cache[a][b]
19
+ #
20
+ # The hash structure returned by slow_method_cache would look like this:
21
+ #
22
+ # Hash.new do |as, a|
23
+ # as[a] = Hash.new do |bs, b|
24
+ # bs[b] = slow_method(a, b)
25
+ # end
26
+ # end
27
+ #
28
+ # The generated code is actually compressed onto a single line to maintain
29
+ # sensible backtrace signatures.
30
+ #
31
+ def hash_cache(method_name, options = {})
32
+ selector = options[:as] || "#{method_name}_cache"
33
+ method = self.instance_method(method_name)
34
+
35
+ args = []
36
+ code = "def #{selector}(); @#{selector} ||= "
37
+
38
+ (1..method.arity).each do |n|
39
+ args << "v#{n}"
40
+ code << "Hash.new {|h#{n}, v#{n}| h#{n}[v#{n}] = "
41
+ end
42
+
43
+ # Add the method call with arguments, followed by closing braces and end.
44
+ code << "#{method_name}(#{args * ', '}) #{'}' * method.arity} end"
45
+
46
+ # Extract the line number information from the caller. Exceptions arising
47
+ # in the generated code should point to the +hash_cache :...+ line.
48
+ if caller[0] && /^(.*):(\d+)$/ =~ caller[0]
49
+ file, line_number = $1, $2.to_i
50
+ else # We can't give good trackback info; fallback to this line:
51
+ file, line_number = __FILE__, __LINE__
52
+ end
53
+
54
+ # We use eval rather than building proc's because it allows us to avoid
55
+ # linking the Hash's to this method's binding. Experience has shown that
56
+ # doing so can cause obtuse memory leaks.
57
+ class_eval code, file, line_number
58
+ end
59
+ end
60
+
61
+ end
62
+ end
@@ -1,5 +1,5 @@
1
1
  require 'logger'
2
- require File.dirname(__FILE__) + '/class_attribute_accessors'
2
+ require File.dirname(__FILE__) + '/core_ext/class/attribute_accessors'
3
3
 
4
4
  class Logger #:nodoc:
5
5
  cattr_accessor :silencer
@@ -20,6 +20,8 @@ class Logger #:nodoc:
20
20
  end
21
21
 
22
22
  private
23
+ alias old_format_message format_message
24
+
23
25
  # Ruby 1.8.3 transposed the msg and progname arguments to format_message.
24
26
  # We can't test RUBY_VERSION because some distributions don't keep Ruby
25
27
  # and its standard library in sync, leading to installations of Ruby 1.8.2
@@ -2,4 +2,20 @@ require File.dirname(__FILE__) + '/array/conversions'
2
2
 
3
3
  class Array #:nodoc:
4
4
  include ActiveSupport::CoreExtensions::Array::Conversions
5
+
6
+ # Iterate over an array in groups of a certain size, padding any remaining
7
+ # slots with specified value (<tt>nil</tt> by default).
8
+ #
9
+ # E.g.
10
+ #
11
+ # %w(1 2 3 4 5 6 7).in_groups_of(3) {|g| p g}
12
+ # ["1", "2", "3"]
13
+ # ["4", "5", "6"]
14
+ # ["7", nil, nil]
15
+ def in_groups_of(number, fill_with = nil, &block)
16
+ require 'enumerator'
17
+ collection = dup
18
+ collection << fill_with until collection.size.modulo(number).zero?
19
+ collection.each_slice(number, &block)
20
+ end
5
21
  end
@@ -1,16 +1,17 @@
1
1
  module ActiveSupport #:nodoc:
2
2
  module CoreExtensions #:nodoc:
3
3
  module Array #:nodoc:
4
- # Enables to conversion of Arrays to human readable lists. ['one', 'two', 'three'] => "one, two, and three"
5
4
  module Conversions
6
5
  # Converts the array to comma-seperated sentence where the last element is joined by the connector word. Options:
7
6
  # * <tt>:connector</tt>: The word used to join the last element in arrays with more than two elements (default: "and")
8
- # * <tt>:skip_last_comma</tt>: Set to true to return "a, b and c" instead of "a, b, and c".
7
+ # * <tt>:skip_last_comma</tt>: Set to true to return "a, b, and c" instead of "a, b and c".
9
8
  def to_sentence(options = {})
10
9
  options.assert_valid_keys(:connector, :skip_last_comma)
11
10
  options.reverse_merge! :connector => 'and', :skip_last_comma => false
12
11
 
13
12
  case length
13
+ when 0
14
+ ""
14
15
  when 1
15
16
  self[0]
16
17
  when 2
@@ -24,6 +25,21 @@ module ActiveSupport #:nodoc:
24
25
  def to_param
25
26
  join '/'
26
27
  end
28
+
29
+ def to_xml(options = {})
30
+ raise "Not all elements respond to to_xml" unless all? { |e| e.respond_to? :to_xml }
31
+
32
+ options[:root] ||= all? { |e| e.is_a?(first.class) && first.class.to_s != "Hash" } ? first.class.to_s.underscore.pluralize : "records"
33
+ options[:children] ||= options[:root].singularize
34
+ options[:indent] ||= 2
35
+ options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
36
+
37
+ root = options.delete(:root)
38
+ children = options.delete(:children)
39
+
40
+ options[:builder].instruct! unless options.delete(:skip_instruct)
41
+ options[:builder].tag!(root.to_s.dasherize) { each { |e| e.to_xml(options.merge({ :skip_instruct => true, :root => children })) } }
42
+ end
27
43
  end
28
44
  end
29
45
  end
@@ -1,4 +1,16 @@
1
- # The methods here are provided to speed up function blank? in class Object
1
+ class Object #:nodoc:
2
+ # "", " ", nil, [], and {} are blank
3
+ def blank?
4
+ if respond_to?(:empty?) && respond_to?(:strip)
5
+ empty? or strip.empty?
6
+ elsif respond_to?(:empty?)
7
+ empty?
8
+ else
9
+ !self
10
+ end
11
+ end
12
+ end
13
+
2
14
  class NilClass #:nodoc:
3
15
  def blank?
4
16
  true
@@ -35,4 +47,4 @@ class Numeric #:nodoc:
35
47
  def blank?
36
48
  false
37
49
  end
38
- end
50
+ end
@@ -0,0 +1,3 @@
1
+ require File.dirname(__FILE__) + '/class/attribute_accessors'
2
+ require File.dirname(__FILE__) + '/class/inheritable_attributes'
3
+ require File.dirname(__FILE__) + '/class/removal'
@@ -0,0 +1,44 @@
1
+ # Extends the class object with class and instance accessors for class attributes,
2
+ # just like the native attr* accessors for instance attributes.
3
+ class Class # :nodoc:
4
+ def cattr_reader(*syms)
5
+ syms.flatten.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 cattr_writer(*syms)
23
+ syms.flatten.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 cattr_accessor(*syms)
41
+ cattr_reader(*syms)
42
+ cattr_writer(*syms)
43
+ end
44
+ end
@@ -110,8 +110,6 @@ class Class # :nodoc:
110
110
  child.instance_variable_set('@inheritable_attributes', inheritable_attributes.dup)
111
111
  end
112
112
 
113
- if respond_to?(:inherited)
114
- alias_method :inherited_without_inheritable_attributes, :inherited
115
- end
116
- alias_method :inherited, :inherited_with_inheritable_attributes
113
+ alias inherited_without_inheritable_attributes inherited
114
+ alias inherited inherited_with_inheritable_attributes
117
115
  end
@@ -0,0 +1,24 @@
1
+ class Class #:nodoc:
2
+ def remove_subclasses
3
+ Object.remove_subclasses_of(self)
4
+ end
5
+
6
+ def subclasses
7
+ Object.subclasses_of(self).map { |o| o.to_s }
8
+ end
9
+
10
+ def remove_class(*klasses)
11
+ klasses.flatten.each do |klass|
12
+ # Skip this class if there is nothing bound to this name
13
+ next unless defined?(klass.name)
14
+
15
+ basename = klass.to_s.split("::").last
16
+ parent = klass.parent
17
+
18
+ # Skip this class if it does not match the current one bound to this name
19
+ next unless parent.const_defined?(basename) && klass = parent.const_get(basename)
20
+
21
+ parent.send :remove_const, basename unless parent == klass
22
+ end
23
+ end
24
+ end