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.
- data/CHANGELOG +163 -4
- data/lib/active_support.rb +8 -3
- data/lib/active_support/breakpoint.rb +1 -1
- data/lib/active_support/caching_tools.rb +62 -0
- data/lib/active_support/clean_logger.rb +3 -1
- data/lib/active_support/core_ext/array.rb +16 -0
- data/lib/active_support/core_ext/array/conversions.rb +18 -2
- data/lib/active_support/core_ext/blank.rb +14 -2
- data/lib/active_support/core_ext/class.rb +3 -0
- data/lib/active_support/core_ext/class/attribute_accessors.rb +44 -0
- data/lib/active_support/{class_inheritable_attributes.rb → core_ext/class/inheritable_attributes.rb} +2 -4
- data/lib/active_support/core_ext/class/removal.rb +24 -0
- data/lib/active_support/core_ext/date/conversions.rb +2 -0
- data/lib/active_support/core_ext/enumerable.rb +23 -1
- data/lib/active_support/core_ext/exception.rb +0 -1
- data/lib/active_support/core_ext/hash.rb +4 -0
- data/lib/active_support/core_ext/hash/conversions.rb +44 -0
- data/lib/active_support/core_ext/hash/diff.rb +11 -0
- data/lib/active_support/core_ext/hash/indifferent_access.rb +23 -4
- data/lib/active_support/core_ext/integer/inflections.rb +1 -1
- data/lib/active_support/core_ext/kernel.rb +4 -79
- data/lib/active_support/core_ext/kernel/agnostics.rb +11 -0
- data/lib/active_support/core_ext/kernel/daemonizing.rb +15 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +51 -0
- data/lib/active_support/core_ext/kernel/requires.rb +24 -0
- data/lib/active_support/core_ext/logger.rb +16 -0
- data/lib/active_support/core_ext/module.rb +5 -0
- data/lib/active_support/core_ext/module/attribute_accessors.rb +44 -0
- data/lib/active_support/core_ext/module/delegation.rb +16 -0
- data/lib/active_support/core_ext/module/inclusion.rb +11 -0
- data/lib/active_support/core_ext/module/introspection.rb +21 -0
- data/lib/active_support/core_ext/module/loading.rb +13 -0
- data/lib/active_support/core_ext/numeric/time.rb +14 -1
- data/lib/active_support/core_ext/object.rb +2 -0
- data/lib/active_support/core_ext/object/extending.rb +47 -0
- data/lib/active_support/core_ext/object/misc.rb +34 -0
- data/lib/active_support/core_ext/proc.rb +12 -0
- data/lib/active_support/core_ext/string.rb +2 -0
- data/lib/active_support/core_ext/string/access.rb +2 -2
- data/lib/active_support/core_ext/string/inflections.rb +10 -3
- data/lib/active_support/core_ext/string/iterators.rb +17 -0
- data/lib/active_support/core_ext/symbol.rb +5 -0
- data/lib/active_support/core_ext/time/calculations.rb +15 -0
- data/lib/active_support/core_ext/time/conversions.rb +1 -0
- data/lib/active_support/dependencies.rb +81 -159
- data/lib/active_support/inflections.rb +48 -48
- data/lib/active_support/inflector.rb +17 -5
- data/lib/active_support/json.rb +37 -0
- data/lib/active_support/json/encoders.rb +25 -0
- data/lib/active_support/json/encoders/core.rb +65 -0
- data/lib/active_support/option_merger.rb +25 -0
- data/lib/active_support/ordered_options.rb +23 -11
- data/lib/active_support/reloadable.rb +30 -0
- data/lib/active_support/vendor/builder.rb +13 -0
- data/lib/active_support/vendor/builder/blankslate.rb +53 -0
- data/lib/active_support/vendor/builder/xmlbase.rb +143 -0
- data/lib/active_support/vendor/builder/xmlevents.rb +63 -0
- data/lib/active_support/vendor/builder/xmlmarkup.rb +308 -0
- data/lib/active_support/version.rb +2 -2
- metadata +113 -69
- data/lib/active_support/class_attribute_accessors.rb +0 -57
- data/lib/active_support/core_ext/object_and_class.rb +0 -44
- data/lib/active_support/module_attribute_accessors.rb +0 -57
@@ -1,53 +1,53 @@
|
|
1
1
|
Inflector.inflections do |inflect|
|
2
|
-
inflect.plural
|
3
|
-
inflect.plural
|
4
|
-
inflect.plural
|
5
|
-
inflect.plural
|
6
|
-
inflect.plural
|
7
|
-
inflect.plural
|
8
|
-
inflect.plural
|
9
|
-
inflect.plural
|
10
|
-
inflect.plural
|
11
|
-
inflect.plural
|
12
|
-
inflect.plural
|
13
|
-
inflect.plural
|
14
|
-
inflect.plural
|
15
|
-
inflect.plural
|
16
|
-
inflect.plural
|
17
|
-
inflect.plural
|
18
|
-
inflect.plural
|
19
|
-
inflect.plural
|
2
|
+
inflect.plural(/$/, 's')
|
3
|
+
inflect.plural(/s$/i, 's')
|
4
|
+
inflect.plural(/(ax|test)is$/i, '\1es')
|
5
|
+
inflect.plural(/(octop|vir)us$/i, '\1i')
|
6
|
+
inflect.plural(/(alias|status)$/i, '\1es')
|
7
|
+
inflect.plural(/(bu)s$/i, '\1ses')
|
8
|
+
inflect.plural(/(buffal|tomat)o$/i, '\1oes')
|
9
|
+
inflect.plural(/([ti])um$/i, '\1a')
|
10
|
+
inflect.plural(/sis$/i, 'ses')
|
11
|
+
inflect.plural(/(?:([^f])fe|([lr])f)$/i, '\1\2ves')
|
12
|
+
inflect.plural(/(hive)$/i, '\1s')
|
13
|
+
inflect.plural(/([^aeiouy]|qu)y$/i, '\1ies')
|
14
|
+
inflect.plural(/([^aeiouy]|qu)ies$/i, '\1y')
|
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
20
|
|
21
|
-
inflect.singular
|
22
|
-
inflect.singular
|
23
|
-
inflect.singular
|
24
|
-
inflect.singular
|
25
|
-
inflect.singular
|
26
|
-
inflect.singular
|
27
|
-
inflect.singular
|
28
|
-
inflect.singular
|
29
|
-
inflect.singular
|
30
|
-
inflect.singular
|
31
|
-
inflect.singular
|
32
|
-
inflect.singular
|
33
|
-
inflect.singular
|
34
|
-
inflect.singular
|
35
|
-
inflect.singular
|
36
|
-
inflect.singular
|
37
|
-
inflect.singular
|
38
|
-
inflect.singular
|
39
|
-
inflect.singular
|
40
|
-
inflect.singular
|
41
|
-
inflect.singular
|
42
|
-
inflect.singular
|
43
|
-
inflect.singular
|
44
|
-
inflect.singular
|
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
45
|
|
46
|
-
inflect.irregular
|
47
|
-
inflect.irregular
|
48
|
-
inflect.irregular
|
49
|
-
inflect.irregular
|
50
|
-
inflect.irregular
|
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
51
|
|
52
|
-
inflect.uncountable
|
52
|
+
inflect.uncountable(%w(equipment information rice money species series fish sheep))
|
53
53
|
end
|
@@ -109,8 +109,12 @@ module Inflector
|
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
112
|
-
def camelize(lower_case_and_underscored_word)
|
113
|
-
|
112
|
+
def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
|
113
|
+
if first_letter_in_uppercase
|
114
|
+
lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
|
115
|
+
else
|
116
|
+
lower_case_and_underscored_word.first + camelize(lower_case_and_underscored_word)[1..-1]
|
117
|
+
end
|
114
118
|
end
|
115
119
|
|
116
120
|
def titleize(word)
|
@@ -118,7 +122,15 @@ module Inflector
|
|
118
122
|
end
|
119
123
|
|
120
124
|
def underscore(camel_cased_word)
|
121
|
-
camel_cased_word.to_s.gsub(/::/, '/').
|
125
|
+
camel_cased_word.to_s.gsub(/::/, '/').
|
126
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
127
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
128
|
+
tr("-", "_").
|
129
|
+
downcase
|
130
|
+
end
|
131
|
+
|
132
|
+
def dasherize(underscored_word)
|
133
|
+
underscored_word.gsub(/_/, '-')
|
122
134
|
end
|
123
135
|
|
124
136
|
def humanize(lower_case_and_underscored_word)
|
@@ -143,9 +155,9 @@ module Inflector
|
|
143
155
|
|
144
156
|
def constantize(camel_cased_word)
|
145
157
|
raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!" unless
|
146
|
-
|
158
|
+
/^(::)?([A-Z]\w*)(::[A-Z]\w*)*$/ =~ camel_cased_word
|
147
159
|
|
148
|
-
camel_cased_word = "::#{camel_cased_word}" unless
|
160
|
+
camel_cased_word = "::#{camel_cased_word}" unless $1
|
149
161
|
Object.module_eval(camel_cased_word, __FILE__, __LINE__)
|
150
162
|
end
|
151
163
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'active_support/json/encoders'
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
module JSON #:nodoc:
|
5
|
+
class CircularReferenceError < StandardError #:nodoc:
|
6
|
+
end
|
7
|
+
# returns the literal string as its JSON encoded form. Useful for passing javascript variables into functions.
|
8
|
+
#
|
9
|
+
# page.call 'Element.show', ActiveSupport::JSON::Variable.new("$$(#items li)")
|
10
|
+
class Variable < String #:nodoc:
|
11
|
+
def to_json
|
12
|
+
self
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class << self
|
17
|
+
REFERENCE_STACK_VARIABLE = :json_reference_stack
|
18
|
+
|
19
|
+
def encode(value)
|
20
|
+
raise_on_circular_reference(value) do
|
21
|
+
Encoders[value.class].call(value)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
def raise_on_circular_reference(value)
|
27
|
+
stack = Thread.current[REFERENCE_STACK_VARIABLE] ||= []
|
28
|
+
raise CircularReferenceError, 'object references itself' if
|
29
|
+
stack.include? value
|
30
|
+
stack << value
|
31
|
+
yield
|
32
|
+
ensure
|
33
|
+
stack.pop
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ActiveSupport
|
2
|
+
module JSON #:nodoc:
|
3
|
+
module Encoders
|
4
|
+
mattr_accessor :encoders
|
5
|
+
@@encoders = {}
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def define_encoder(klass, &block)
|
9
|
+
encoders[klass] = block
|
10
|
+
end
|
11
|
+
|
12
|
+
def [](klass)
|
13
|
+
klass.ancestors.each do |k|
|
14
|
+
encoder = encoders[k]
|
15
|
+
return encoder if encoder
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
Dir[File.dirname(__FILE__) + '/encoders/*.rb'].each do |file|
|
24
|
+
require file[0..-4]
|
25
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module ActiveSupport
|
2
|
+
module JSON #:nodoc:
|
3
|
+
module Encoders #:nodoc:
|
4
|
+
define_encoder Object do |object|
|
5
|
+
object.instance_values.to_json
|
6
|
+
end
|
7
|
+
|
8
|
+
define_encoder TrueClass do
|
9
|
+
'true'
|
10
|
+
end
|
11
|
+
|
12
|
+
define_encoder FalseClass do
|
13
|
+
'false'
|
14
|
+
end
|
15
|
+
|
16
|
+
define_encoder NilClass do
|
17
|
+
'null'
|
18
|
+
end
|
19
|
+
|
20
|
+
define_encoder String do |string|
|
21
|
+
returning value = '"' do
|
22
|
+
string.each_char do |char|
|
23
|
+
value << case
|
24
|
+
when char == "\010": '\b'
|
25
|
+
when char == "\f": '\f'
|
26
|
+
when char == "\n": '\n'
|
27
|
+
when char == "\r": '\r'
|
28
|
+
when char == "\t": '\t'
|
29
|
+
when char == '"': '\"'
|
30
|
+
when char == '\\': '\\\\'
|
31
|
+
when char.length > 1: "\\u#{'%04x' % char.unpack('U').first}"
|
32
|
+
else; char
|
33
|
+
end
|
34
|
+
end
|
35
|
+
value << '"'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
define_encoder Numeric do |numeric|
|
40
|
+
numeric.to_s
|
41
|
+
end
|
42
|
+
|
43
|
+
define_encoder Symbol do |symbol|
|
44
|
+
symbol.to_s.to_json
|
45
|
+
end
|
46
|
+
|
47
|
+
define_encoder Enumerable do |enumerable|
|
48
|
+
"[#{enumerable.map { |value| value.to_json } * ', '}]"
|
49
|
+
end
|
50
|
+
|
51
|
+
define_encoder Hash do |hash|
|
52
|
+
returning result = '{' do
|
53
|
+
result << hash.map do |pair|
|
54
|
+
pair.map { |value| value.to_json } * ': '
|
55
|
+
end * ', '
|
56
|
+
result << '}'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
define_encoder Regexp do |regexp|
|
61
|
+
regexp.inspect
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ActiveSupport
|
2
|
+
class OptionMerger #:nodoc:
|
3
|
+
instance_methods.each do |method|
|
4
|
+
undef_method(method) if method !~ /^(__|instance_eval)/
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(context, options)
|
8
|
+
@context, @options = context, options
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
def method_missing(method, *arguments, &block)
|
13
|
+
merge_argument_options! arguments
|
14
|
+
@context.send(method, *arguments, &block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def merge_argument_options!(arguments)
|
18
|
+
arguments << if arguments.last.respond_to? :merge!
|
19
|
+
arguments.pop.dup.merge!(@options)
|
20
|
+
else
|
21
|
+
@options.dup
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1,7 +1,5 @@
|
|
1
|
-
class
|
2
|
-
def []=(key, value)
|
3
|
-
key = key.to_sym
|
4
|
-
|
1
|
+
class OrderedHash < Array #:nodoc:
|
2
|
+
def []=(key, value)
|
5
3
|
if pair = find_pair(key)
|
6
4
|
pair.pop
|
7
5
|
pair << value
|
@@ -11,16 +9,12 @@ class OrderedOptions < Array #:nodoc:
|
|
11
9
|
end
|
12
10
|
|
13
11
|
def [](key)
|
14
|
-
pair = find_pair(key
|
12
|
+
pair = find_pair(key)
|
15
13
|
pair ? pair.last : nil
|
16
14
|
end
|
17
15
|
|
18
|
-
def
|
19
|
-
|
20
|
-
self[$1.to_sym] = args.first
|
21
|
-
else
|
22
|
-
self[name]
|
23
|
-
end
|
16
|
+
def keys
|
17
|
+
self.collect { |i| i.first }
|
24
18
|
end
|
25
19
|
|
26
20
|
private
|
@@ -28,4 +22,22 @@ class OrderedOptions < Array #:nodoc:
|
|
28
22
|
self.each { |i| return i if i.first == key }
|
29
23
|
return false
|
30
24
|
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class OrderedOptions < OrderedHash #:nodoc:
|
28
|
+
def []=(key, value)
|
29
|
+
super(key.to_sym, value)
|
30
|
+
end
|
31
|
+
|
32
|
+
def [](key)
|
33
|
+
super(key.to_sym)
|
34
|
+
end
|
35
|
+
|
36
|
+
def method_missing(name, *args)
|
37
|
+
if name.to_s =~ /(.*)=$/
|
38
|
+
self[$1.to_sym] = args.first
|
39
|
+
else
|
40
|
+
self[name]
|
41
|
+
end
|
42
|
+
end
|
31
43
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Classes that include this module will automatically be reloaded
|
2
|
+
# by the Rails dispatcher when Dependencies.mechanism = :load.
|
3
|
+
module Reloadable
|
4
|
+
class << self
|
5
|
+
def included(base) #nodoc:
|
6
|
+
raise TypeError, "Only Classes can be Reloadable!" unless base.is_a? Class
|
7
|
+
|
8
|
+
unless base.respond_to?(:reloadable?)
|
9
|
+
class << base
|
10
|
+
define_method(:reloadable?) { true }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def reloadable_classes
|
16
|
+
included_in_classes.select { |klass| klass.reloadable? }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Captures the common pattern where a base class should not be reloaded,
|
21
|
+
# but its subclasses should be.
|
22
|
+
module Subclasses
|
23
|
+
def self.included(base) #nodoc:
|
24
|
+
base.send :include, Reloadable
|
25
|
+
(class << base; self; end).send(:define_method, :reloadable?) do
|
26
|
+
base != self
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright 2004 by Jim Weirich (jim@weirichhouse.org).
|
5
|
+
# All rights reserved.
|
6
|
+
|
7
|
+
# Permission is granted for use, copying, modification, distribution,
|
8
|
+
# and distribution of modified versions of this work as long as the
|
9
|
+
# above copyright notice is included.
|
10
|
+
#++
|
11
|
+
|
12
|
+
require 'builder/xmlmarkup'
|
13
|
+
require 'builder/xmlevents'
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#--
|
3
|
+
# Copyright 2004 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
|
+
module Builder #:nodoc:
|
12
|
+
|
13
|
+
# BlankSlate provides an abstract base class with no predefined
|
14
|
+
# methods (except for <tt>\_\_send__</tt> and <tt>\_\_id__</tt>).
|
15
|
+
# BlankSlate is useful as a base class when writing classes that
|
16
|
+
# depend upon <tt>method_missing</tt> (e.g. dynamic proxies).
|
17
|
+
class BlankSlate #:nodoc:
|
18
|
+
class << self
|
19
|
+
def hide(name)
|
20
|
+
undef_method name if
|
21
|
+
instance_methods.include?(name.to_s) and
|
22
|
+
name !~ /^(__|instance_eval)/
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
instance_methods.each { |m| hide(m) }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Since Ruby is very dynamic, methods added to the ancestors of
|
31
|
+
# BlankSlate <em>after BlankSlate is defined</em> will show up in the
|
32
|
+
# list of available BlankSlate methods. We handle this by defining a hook in the Object and Kernel classes that will hide any defined
|
33
|
+
module Kernel #:nodoc:
|
34
|
+
class << self
|
35
|
+
alias_method :blank_slate_method_added, :method_added
|
36
|
+
def method_added(name)
|
37
|
+
blank_slate_method_added(name)
|
38
|
+
return if self != Kernel
|
39
|
+
Builder::BlankSlate.hide(name)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class Object #:nodoc:
|
45
|
+
class << self
|
46
|
+
alias_method :blank_slate_method_added, :method_added
|
47
|
+
def method_added(name)
|
48
|
+
blank_slate_method_added(name)
|
49
|
+
return if self != Object
|
50
|
+
Builder::BlankSlate.hide(name)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|