activeobject 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. data/CHANGE +10 -0
  2. data/Interface_desc +21 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README +72 -0
  5. data/Rakefile.rb +9 -0
  6. data/active-object.gemspec +50 -0
  7. data/examples/account.rb +69 -0
  8. data/examples/data.tch +0 -0
  9. data/examples/light_cloud.yml +18 -0
  10. data/examples/test.rb +3 -0
  11. data/examples/user.rb +112 -0
  12. data/init.rb +4 -0
  13. data/lib/active-object.rb +23 -0
  14. data/lib/active_object/adapters/light_cloud.rb +40 -0
  15. data/lib/active_object/adapters/tokyo_cabinet.rb +48 -0
  16. data/lib/active_object/adapters/tokyo_tyrant.rb +14 -0
  17. data/lib/active_object/associations.rb +200 -0
  18. data/lib/active_object/base.rb +415 -0
  19. data/lib/active_object/callbacks.rb +180 -0
  20. data/lib/active_object/observer.rb +180 -0
  21. data/lib/active_object/serialization.rb +99 -0
  22. data/lib/active_object/serializers/json_serializer.rb +75 -0
  23. data/lib/active_object/serializers/xml_serializer.rb +325 -0
  24. data/lib/active_object/validations.rb +687 -0
  25. data/lib/active_support/callbacks.rb +303 -0
  26. data/lib/active_support/core_ext/array/access.rb +53 -0
  27. data/lib/active_support/core_ext/array/conversions.rb +183 -0
  28. data/lib/active_support/core_ext/array/extract_options.rb +20 -0
  29. data/lib/active_support/core_ext/array/grouping.rb +106 -0
  30. data/lib/active_support/core_ext/array/random_access.rb +12 -0
  31. data/lib/active_support/core_ext/array.rb +13 -0
  32. data/lib/active_support/core_ext/blank.rb +58 -0
  33. data/lib/active_support/core_ext/class/attribute_accessors.rb +54 -0
  34. data/lib/active_support/core_ext/class/inheritable_attributes.rb +140 -0
  35. data/lib/active_support/core_ext/class/removal.rb +50 -0
  36. data/lib/active_support/core_ext/class.rb +3 -0
  37. data/lib/active_support/core_ext/duplicable.rb +43 -0
  38. data/lib/active_support/core_ext/enumerable.rb +72 -0
  39. data/lib/active_support/core_ext/hash/conversions.rb +259 -0
  40. data/lib/active_support/core_ext/hash/keys.rb +52 -0
  41. data/lib/active_support/core_ext/hash.rb +8 -0
  42. data/lib/active_support/core_ext/module/aliasing.rb +74 -0
  43. data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +31 -0
  44. data/lib/active_support/core_ext/module/attribute_accessors.rb +58 -0
  45. data/lib/active_support/core_ext/module.rb +16 -0
  46. data/lib/active_support/core_ext/object/conversions.rb +14 -0
  47. data/lib/active_support/core_ext/object/extending.rb +80 -0
  48. data/lib/active_support/core_ext/object/instance_variables.rb +74 -0
  49. data/lib/active_support/core_ext/object/metaclass.rb +13 -0
  50. data/lib/active_support/core_ext/object/misc.rb +43 -0
  51. data/lib/active_support/core_ext/object.rb +5 -0
  52. data/lib/active_support/core_ext/string/inflections.rb +167 -0
  53. data/lib/active_support/core_ext/string.rb +7 -0
  54. data/lib/active_support/core_ext.rb +4 -0
  55. data/lib/active_support/inflections.rb +55 -0
  56. data/lib/active_support/inflector.rb +348 -0
  57. data/lib/active_support/vendor/builder-2.1.2/blankslate.rb +113 -0
  58. data/lib/active_support/vendor/builder-2.1.2/builder/blankslate.rb +20 -0
  59. data/lib/active_support/vendor/builder-2.1.2/builder/css.rb +250 -0
  60. data/lib/active_support/vendor/builder-2.1.2/builder/xchar.rb +115 -0
  61. data/lib/active_support/vendor/builder-2.1.2/builder/xmlbase.rb +139 -0
  62. data/lib/active_support/vendor/builder-2.1.2/builder/xmlevents.rb +63 -0
  63. data/lib/active_support/vendor/builder-2.1.2/builder/xmlmarkup.rb +328 -0
  64. data/lib/active_support/vendor/builder-2.1.2/builder.rb +13 -0
  65. data/lib/active_support/vendor/xml-simple-1.0.11/xmlsimple.rb +1021 -0
  66. data/lib/active_support/vendor.rb +14 -0
  67. data/lib/active_support.rb +6 -0
  68. data/spec/case/association_test.rb +97 -0
  69. data/spec/case/base_test.rb +74 -0
  70. data/spec/case/callbacks_observers_test.rb +38 -0
  71. data/spec/case/callbacks_test.rb +424 -0
  72. data/spec/case/serialization_test.rb +87 -0
  73. data/spec/case/validations_test.rb +1482 -0
  74. data/spec/data.tch +0 -0
  75. data/spec/helper.rb +15 -0
  76. data/spec/light_cloud.yml +18 -0
  77. data/spec/model/account.rb +4 -0
  78. data/spec/model/topic.rb +26 -0
  79. data/spec/model/user.rb +8 -0
  80. metadata +173 -0
@@ -0,0 +1,55 @@
1
+ module ActiveSupport
2
+ Inflector.inflections do |inflect|
3
+ inflect.plural(/$/, 's')
4
+ inflect.plural(/s$/i, 's')
5
+ inflect.plural(/(ax|test)is$/i, '\1es')
6
+ inflect.plural(/(octop|vir)us$/i, '\1i')
7
+ inflect.plural(/(alias|status)$/i, '\1es')
8
+ inflect.plural(/(bu)s$/i, '\1ses')
9
+ inflect.plural(/(buffal|tomat)o$/i, '\1oes')
10
+ inflect.plural(/([ti])um$/i, '\1a')
11
+ inflect.plural(/sis$/i, 'ses')
12
+ inflect.plural(/(?:([^f])fe|([lr])f)$/i, '\1\2ves')
13
+ inflect.plural(/(hive)$/i, '\1s')
14
+ inflect.plural(/([^aeiouy]|qu)y$/i, '\1ies')
15
+ inflect.plural(/(x|ch|ss|sh)$/i, '\1es')
16
+ inflect.plural(/(matr|vert|ind)(?:ix|ex)$/i, '\1ices')
17
+ inflect.plural(/([m|l])ouse$/i, '\1ice')
18
+ inflect.plural(/^(ox)$/i, '\1en')
19
+ inflect.plural(/(quiz)$/i, '\1zes')
20
+
21
+ inflect.singular(/s$/i, '')
22
+ inflect.singular(/(n)ews$/i, '\1ews')
23
+ inflect.singular(/([ti])a$/i, '\1um')
24
+ inflect.singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i, '\1\2sis')
25
+ inflect.singular(/(^analy)ses$/i, '\1sis')
26
+ inflect.singular(/([^f])ves$/i, '\1fe')
27
+ inflect.singular(/(hive)s$/i, '\1')
28
+ inflect.singular(/(tive)s$/i, '\1')
29
+ inflect.singular(/([lr])ves$/i, '\1f')
30
+ inflect.singular(/([^aeiouy]|qu)ies$/i, '\1y')
31
+ inflect.singular(/(s)eries$/i, '\1eries')
32
+ inflect.singular(/(m)ovies$/i, '\1ovie')
33
+ inflect.singular(/(x|ch|ss|sh)es$/i, '\1')
34
+ inflect.singular(/([m|l])ice$/i, '\1ouse')
35
+ inflect.singular(/(bus)es$/i, '\1')
36
+ inflect.singular(/(o)es$/i, '\1')
37
+ inflect.singular(/(shoe)s$/i, '\1')
38
+ inflect.singular(/(cris|ax|test)es$/i, '\1is')
39
+ inflect.singular(/(octop|vir)i$/i, '\1us')
40
+ inflect.singular(/(alias|status)es$/i, '\1')
41
+ inflect.singular(/^(ox)en/i, '\1')
42
+ inflect.singular(/(vert|ind)ices$/i, '\1ex')
43
+ inflect.singular(/(matr)ices$/i, '\1ix')
44
+ inflect.singular(/(quiz)zes$/i, '\1')
45
+
46
+ inflect.irregular('person', 'people')
47
+ inflect.irregular('man', 'men')
48
+ inflect.irregular('child', 'children')
49
+ inflect.irregular('sex', 'sexes')
50
+ inflect.irregular('move', 'moves')
51
+ inflect.irregular('cow', 'kine')
52
+
53
+ inflect.uncountable(%w(equipment information rice money species series fish sheep))
54
+ end
55
+ end
@@ -0,0 +1,348 @@
1
+ # encoding: utf-8
2
+ require 'singleton'
3
+ require 'iconv'
4
+
5
+ module ActiveSupport
6
+ # The Inflector transforms words from singular to plural, class names to table names, modularized class names to ones without,
7
+ # and class names to foreign keys. The default inflections for pluralization, singularization, and uncountable words are kept
8
+ # in inflections.rb.
9
+ #
10
+ module Inflector
11
+ extend self
12
+
13
+ # A singleton instance of this class is yielded by Inflector.inflections, which can then be used to specify additional
14
+ # inflection rules. Examples:
15
+ #
16
+ # ActiveSupport::Inflector.inflections do |inflect|
17
+ # inflect.plural /^(ox)$/i, '\1\2en'
18
+ # inflect.singular /^(ox)en/i, '\1'
19
+ #
20
+ # inflect.irregular 'octopus', 'octopi'
21
+ #
22
+ # inflect.uncountable "equipment"
23
+ # end
24
+ #
25
+ # New rules are added at the top. So in the example above, the irregular rule for octopus will now be the first of the
26
+ # pluralization and singularization rules that is runs. This guarantees that your rules run before any of the rules that may
27
+ # already have been loaded.
28
+ class Inflections
29
+ include Singleton
30
+
31
+ attr_reader :plurals, :singulars, :uncountables, :humans
32
+
33
+ def initialize
34
+ @plurals, @singulars, @uncountables, @humans = [], [], [], []
35
+ end
36
+
37
+ # Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression.
38
+ # The replacement should always be a string that may include references to the matched data from the rule.
39
+ def plural(rule, replacement)
40
+ @uncountables.delete(rule) if rule.is_a?(String)
41
+ @uncountables.delete(replacement)
42
+ @plurals.insert(0, [rule, replacement])
43
+ end
44
+
45
+ # Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression.
46
+ # The replacement should always be a string that may include references to the matched data from the rule.
47
+ def singular(rule, replacement)
48
+ @uncountables.delete(rule) if rule.is_a?(String)
49
+ @uncountables.delete(replacement)
50
+ @singulars.insert(0, [rule, replacement])
51
+ end
52
+
53
+ # Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used
54
+ # for strings, not regular expressions. You simply pass the irregular in singular and plural form.
55
+ #
56
+ # Examples:
57
+ # irregular 'octopus', 'octopi'
58
+ # irregular 'person', 'people'
59
+ def irregular(singular, plural)
60
+ @uncountables.delete(singular)
61
+ @uncountables.delete(plural)
62
+ if singular[0,1].upcase == plural[0,1].upcase
63
+ plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1])
64
+ singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1])
65
+ else
66
+ plural(Regexp.new("#{singular[0,1].upcase}(?i)#{singular[1..-1]}$"), plural[0,1].upcase + plural[1..-1])
67
+ plural(Regexp.new("#{singular[0,1].downcase}(?i)#{singular[1..-1]}$"), plural[0,1].downcase + plural[1..-1])
68
+ singular(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), singular[0,1].upcase + singular[1..-1])
69
+ singular(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), singular[0,1].downcase + singular[1..-1])
70
+ end
71
+ end
72
+
73
+ # Add uncountable words that shouldn't be attempted inflected.
74
+ #
75
+ # Examples:
76
+ # uncountable "money"
77
+ # uncountable "money", "information"
78
+ # uncountable %w( money information rice )
79
+ def uncountable(*words)
80
+ (@uncountables << words).flatten!
81
+ end
82
+
83
+ # Specifies a humanized form of a string by a regular expression rule or by a string mapping.
84
+ # When using a regular expression based replacement, the normal humanize formatting is called after the replacement.
85
+ # When a string is used, the human form should be specified as desired (example: 'The name', not 'the_name')
86
+ #
87
+ # Examples:
88
+ # human /_cnt$/i, '\1_count'
89
+ # human "legacy_col_person_name", "Name"
90
+ def human(rule, replacement)
91
+ @humans.insert(0, [rule, replacement])
92
+ end
93
+
94
+ # Clears the loaded inflections within a given scope (default is <tt>:all</tt>).
95
+ # Give the scope as a symbol of the inflection type, the options are: <tt>:plurals</tt>,
96
+ # <tt>:singulars</tt>, <tt>:uncountables</tt>, <tt>:humans</tt>.
97
+ #
98
+ # Examples:
99
+ # clear :all
100
+ # clear :plurals
101
+ def clear(scope = :all)
102
+ case scope
103
+ when :all
104
+ @plurals, @singulars, @uncountables = [], [], []
105
+ else
106
+ instance_variable_set "@#{scope}", []
107
+ end
108
+ end
109
+ end
110
+
111
+ # Yields a singleton instance of Inflector::Inflections so you can specify additional
112
+ # inflector rules.
113
+ #
114
+ # Example:
115
+ # ActiveSupport::Inflector.inflections do |inflect|
116
+ # inflect.uncountable "rails"
117
+ # end
118
+ def inflections
119
+ if block_given?
120
+ yield Inflections.instance
121
+ else
122
+ Inflections.instance
123
+ end
124
+ end
125
+
126
+ # Returns the plural form of the word in the string.
127
+ #
128
+ # Examples:
129
+ # "post".pluralize # => "posts"
130
+ # "octopus".pluralize # => "octopi"
131
+ # "sheep".pluralize # => "sheep"
132
+ # "words".pluralize # => "words"
133
+ # "CamelOctopus".pluralize # => "CamelOctopi"
134
+ def pluralize(word)
135
+ result = word.to_s.dup
136
+
137
+ if word.empty? || inflections.uncountables.include?(result.downcase)
138
+ result
139
+ else
140
+ inflections.plurals.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
141
+ result
142
+ end
143
+ end
144
+
145
+ # The reverse of +pluralize+, returns the singular form of a word in a string.
146
+ #
147
+ # Examples:
148
+ # "posts".singularize # => "post"
149
+ # "octopi".singularize # => "octopus"
150
+ # "sheep".singluarize # => "sheep"
151
+ # "word".singularize # => "word"
152
+ # "CamelOctopi".singularize # => "CamelOctopus"
153
+ def singularize(word)
154
+ result = word.to_s.dup
155
+
156
+ if inflections.uncountables.include?(result.downcase)
157
+ result
158
+ else
159
+ inflections.singulars.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
160
+ result
161
+ end
162
+ end
163
+
164
+ # By default, +camelize+ converts strings to UpperCamelCase. If the argument to +camelize+
165
+ # is set to <tt>:lower</tt> then +camelize+ produces lowerCamelCase.
166
+ #
167
+ # +camelize+ will also convert '/' to '::' which is useful for converting paths to namespaces.
168
+ #
169
+ # Examples:
170
+ # "active_record".camelize # => "ActiveRecord"
171
+ # "active_record".camelize(:lower) # => "activeRecord"
172
+ # "active_record/errors".camelize # => "ActiveRecord::Errors"
173
+ # "active_record/errors".camelize(:lower) # => "activeRecord::Errors"
174
+ def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
175
+ if first_letter_in_uppercase
176
+ lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
177
+ else
178
+ lower_case_and_underscored_word.first.downcase + camelize(lower_case_and_underscored_word)[1..-1]
179
+ end
180
+ end
181
+
182
+ # Capitalizes all the words and replaces some characters in the string to create
183
+ # a nicer looking title. +titleize+ is meant for creating pretty output. It is not
184
+ # used in the Rails internals.
185
+ #
186
+ # +titleize+ is also aliased as as +titlecase+.
187
+ #
188
+ # Examples:
189
+ # "man from the boondocks".titleize # => "Man From The Boondocks"
190
+ # "x-men: the last stand".titleize # => "X Men: The Last Stand"
191
+ def titleize(word)
192
+ humanize(underscore(word)).gsub(/\b('?[a-z])/) { $1.capitalize }
193
+ end
194
+
195
+ # The reverse of +camelize+. Makes an underscored, lowercase form from the expression in the string.
196
+ #
197
+ # Changes '::' to '/' to convert namespaces to paths.
198
+ #
199
+ # Examples:
200
+ # "ActiveRecord".underscore # => "active_record"
201
+ # "ActiveRecord::Errors".underscore # => active_record/errors
202
+ def underscore(camel_cased_word)
203
+ camel_cased_word.to_s.gsub(/::/, '/').
204
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
205
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
206
+ tr("-", "_").
207
+ downcase
208
+ end
209
+
210
+ # Replaces underscores with dashes in the string.
211
+ #
212
+ # Example:
213
+ # "puni_puni" # => "puni-puni"
214
+ def dasherize(underscored_word)
215
+ underscored_word.gsub(/_/, '-')
216
+ end
217
+
218
+ # Capitalizes the first word and turns underscores into spaces and strips a
219
+ # trailing "_id", if any. Like +titleize+, this is meant for creating pretty output.
220
+ #
221
+ # Examples:
222
+ # "employee_salary" # => "Employee salary"
223
+ # "author_id" # => "Author"
224
+ def humanize(lower_case_and_underscored_word)
225
+ result = lower_case_and_underscored_word.to_s.dup
226
+
227
+ inflections.humans.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
228
+ result.gsub(/_id$/, "").gsub(/_/, " ").capitalize
229
+ end
230
+
231
+ # Removes the module part from the expression in the string.
232
+ #
233
+ # Examples:
234
+ # "ActiveRecord::CoreExtensions::String::Inflections".demodulize # => "Inflections"
235
+ # "Inflections".demodulize # => "Inflections"
236
+ def demodulize(class_name_in_module)
237
+ class_name_in_module.to_s.gsub(/^.*::/, '')
238
+ end
239
+
240
+ # Replaces special characters in a string so that it may be used as part of a 'pretty' URL.
241
+ #
242
+ # ==== Examples
243
+ #
244
+ # class Person
245
+ # def to_param
246
+ # "#{id}-#{name.parameterize}"
247
+ # end
248
+ # end
249
+ #
250
+ # @person = Person.find(1)
251
+ # # => #<Person id: 1, name: "Donald E. Knuth">
252
+ #
253
+ # <%= link_to(@person.name, person_path %>
254
+ # # => <a href="/person/1-donald-e-knuth">Donald E. Knuth</a>
255
+ def parameterize(string, sep = '-')
256
+ re_sep = Regexp.escape(sep)
257
+ # replace accented chars with ther ascii equivalents
258
+ parameterized_string = transliterate(string)
259
+ # Turn unwanted chars into the seperator
260
+ parameterized_string.gsub!(/[^a-z0-9\-_\+]+/i, sep)
261
+ # No more than one of the separator in a row.
262
+ parameterized_string.squeeze!(sep)
263
+ # Remove leading/trailing separator.
264
+ parameterized_string.gsub!(/^#{re_sep}|#{re_sep}$/i, '')
265
+ parameterized_string.downcase
266
+ end
267
+
268
+
269
+ # Replaces accented characters with their ascii equivalents.
270
+ def transliterate(string)
271
+ Iconv.iconv('ascii//ignore//translit', 'utf-8', string).to_s
272
+ end
273
+
274
+ # The iconv transliteration code doesn't function correctly
275
+ # on some platforms, but it's very fast where it does function.
276
+ if "foo" != Inflector.transliterate("föö")
277
+ undef_method :transliterate
278
+ def transliterate(string)
279
+ string.mb_chars.normalize(:kd). # Decompose accented characters
280
+ gsub(/[^\x00-\x7F]+/, '') # Remove anything non-ASCII entirely (e.g. diacritics).
281
+ end
282
+ end
283
+
284
+ # Ruby 1.9 introduces an inherit argument for Module#const_get and
285
+ # #const_defined? and changes their default behavior.
286
+ if Module.method(:const_get).arity == 1
287
+ # Tries to find a constant with the name specified in the argument string:
288
+ #
289
+ # "Module".constantize # => Module
290
+ # "Test::Unit".constantize # => Test::Unit
291
+ #
292
+ # The name is assumed to be the one of a top-level constant, no matter whether
293
+ # it starts with "::" or not. No lexical context is taken into account:
294
+ #
295
+ # C = 'outside'
296
+ # module M
297
+ # C = 'inside'
298
+ # C # => 'inside'
299
+ # "C".constantize # => 'outside', same as ::C
300
+ # end
301
+ #
302
+ # NameError is raised when the name is not in CamelCase or the constant is
303
+ # unknown.
304
+ def constantize(camel_cased_word)
305
+ names = camel_cased_word.split('::')
306
+ names.shift if names.empty? || names.first.empty?
307
+
308
+ constant = Object
309
+ names.each do |name|
310
+ constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
311
+ end
312
+ constant
313
+ end
314
+ else
315
+ def constantize(camel_cased_word) #:nodoc:
316
+ names = camel_cased_word.split('::')
317
+ names.shift if names.empty? || names.first.empty?
318
+
319
+ constant = Object
320
+ names.each do |name|
321
+ constant = constant.const_get(name, false) || constant.const_missing(name)
322
+ end
323
+ constant
324
+ end
325
+ end
326
+
327
+ # Turns a number into an ordinal string used to denote the position in an
328
+ # ordered sequence such as 1st, 2nd, 3rd, 4th.
329
+ #
330
+ # Examples:
331
+ # ordinalize(1) # => "1st"
332
+ # ordinalize(2) # => "2nd"
333
+ # ordinalize(1002) # => "1002nd"
334
+ # ordinalize(1003) # => "1003rd"
335
+ def ordinalize(number)
336
+ if (11..13).include?(number.to_i % 100)
337
+ "#{number}th"
338
+ else
339
+ case number.to_i % 10
340
+ when 1; "#{number}st"
341
+ when 2; "#{number}nd"
342
+ when 3; "#{number}rd"
343
+ else "#{number}th"
344
+ end
345
+ end
346
+ end
347
+ end
348
+ end
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # Copyright 2004, 2006 by Jim Weirich (jim@weirichhouse.org).
4
+ # All rights reserved.
5
+
6
+ # Permission is granted for use, copying, modification, distribution,
7
+ # and distribution of modified versions of this work as long as the
8
+ # above copyright notice is included.
9
+ #++
10
+
11
+ ######################################################################
12
+ # BlankSlate provides an abstract base class with no predefined
13
+ # methods (except for <tt>\_\_send__</tt> and <tt>\_\_id__</tt>).
14
+ # BlankSlate is useful as a base class when writing classes that
15
+ # depend upon <tt>method_missing</tt> (e.g. dynamic proxies).
16
+ #
17
+ class BlankSlate
18
+ class << self
19
+
20
+ # Hide the method named +name+ in the BlankSlate class. Don't
21
+ # hide +instance_eval+ or any method beginning with "__".
22
+ def hide(name)
23
+ if instance_methods.include?(name.to_s) and
24
+ name !~ /^(__|instance_eval)/
25
+ @hidden_methods ||= {}
26
+ @hidden_methods[name.to_sym] = instance_method(name)
27
+ undef_method name
28
+ end
29
+ end
30
+
31
+ def find_hidden_method(name)
32
+ @hidden_methods ||= {}
33
+ @hidden_methods[name] || superclass.find_hidden_method(name)
34
+ end
35
+
36
+ # Redefine a previously hidden method so that it may be called on a blank
37
+ # slate object.
38
+ def reveal(name)
39
+ bound_method = nil
40
+ unbound_method = find_hidden_method(name)
41
+ fail "Don't know how to reveal method '#{name}'" unless unbound_method
42
+ define_method(name) do |*args|
43
+ bound_method ||= unbound_method.bind(self)
44
+ bound_method.call(*args)
45
+ end
46
+ end
47
+ end
48
+
49
+ instance_methods.each { |m| hide(m) }
50
+ end
51
+
52
+ ######################################################################
53
+ # Since Ruby is very dynamic, methods added to the ancestors of
54
+ # BlankSlate <em>after BlankSlate is defined</em> will show up in the
55
+ # list of available BlankSlate methods. We handle this by defining a
56
+ # hook in the Object and Kernel classes that will hide any method
57
+ # defined after BlankSlate has been loaded.
58
+ #
59
+ module Kernel
60
+ class << self
61
+ alias_method :blank_slate_method_added, :method_added
62
+
63
+ # Detect method additions to Kernel and remove them in the
64
+ # BlankSlate class.
65
+ def method_added(name)
66
+ result = blank_slate_method_added(name)
67
+ return result if self != Kernel
68
+ BlankSlate.hide(name)
69
+ result
70
+ end
71
+ end
72
+ end
73
+
74
+ ######################################################################
75
+ # Same as above, except in Object.
76
+ #
77
+ class Object
78
+ class << self
79
+ alias_method :blank_slate_method_added, :method_added
80
+
81
+ # Detect method additions to Object and remove them in the
82
+ # BlankSlate class.
83
+ def method_added(name)
84
+ result = blank_slate_method_added(name)
85
+ return result if self != Object
86
+ BlankSlate.hide(name)
87
+ result
88
+ end
89
+
90
+ def find_hidden_method(name)
91
+ nil
92
+ end
93
+ end
94
+ end
95
+
96
+ ######################################################################
97
+ # Also, modules included into Object need to be scanned and have their
98
+ # instance methods removed from blank slate. In theory, modules
99
+ # included into Kernel would have to be removed as well, but a
100
+ # "feature" of Ruby prevents late includes into modules from being
101
+ # exposed in the first place.
102
+ #
103
+ class Module
104
+ alias blankslate_original_append_features append_features
105
+ def append_features(mod)
106
+ result = blankslate_original_append_features(mod)
107
+ return result if mod != Object
108
+ instance_methods.each do |name|
109
+ BlankSlate.hide(name)
110
+ end
111
+ result
112
+ end
113
+ end
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # Copyright 2004, 2006 by Jim Weirich (jim@weirichhouse.org).
4
+ # All rights reserved.
5
+
6
+ # Permission is granted for use, copying, modification, distribution,
7
+ # and distribution of modified versions of this work as long as the
8
+ # above copyright notice is included.
9
+ #++
10
+
11
+ require 'blankslate'
12
+
13
+ ######################################################################
14
+ # BlankSlate has been promoted to a top level name and is now
15
+ # available as a standalone gem. We make the name available in the
16
+ # Builder namespace for compatibility.
17
+ #
18
+ module Builder
19
+ BlankSlate = ::BlankSlate
20
+ end