monetra-ruby 0.0.6
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.
- data/Rakefile +35 -0
- data/lib/monetra.rb +239 -0
- data/lib/monetra/active_support.rb +42 -0
- data/lib/monetra/active_support/binding_of_caller.rb +84 -0
- data/lib/monetra/active_support/breakpoint.rb +523 -0
- data/lib/monetra/active_support/caching_tools.rb +62 -0
- data/lib/monetra/active_support/clean_logger.rb +38 -0
- data/lib/monetra/active_support/core_ext.rb +1 -0
- data/lib/monetra/active_support/core_ext/array.rb +7 -0
- data/lib/monetra/active_support/core_ext/array/conversions.rb +72 -0
- data/lib/monetra/active_support/core_ext/array/grouping.rb +46 -0
- data/lib/monetra/active_support/core_ext/bigdecimal.rb +3 -0
- data/lib/monetra/active_support/core_ext/bigdecimal/formatting.rb +7 -0
- data/lib/monetra/active_support/core_ext/blank.rb +50 -0
- data/lib/monetra/active_support/core_ext/cgi.rb +5 -0
- data/lib/monetra/active_support/core_ext/cgi/escape_skipping_slashes.rb +14 -0
- data/lib/monetra/active_support/core_ext/class.rb +3 -0
- data/lib/monetra/active_support/core_ext/class/attribute_accessors.rb +44 -0
- data/lib/monetra/active_support/core_ext/class/inheritable_attributes.rb +115 -0
- data/lib/monetra/active_support/core_ext/class/removal.rb +24 -0
- data/lib/monetra/active_support/core_ext/date.rb +6 -0
- data/lib/monetra/active_support/core_ext/date/conversions.rb +39 -0
- data/lib/monetra/active_support/core_ext/enumerable.rb +62 -0
- data/lib/monetra/active_support/core_ext/exception.rb +33 -0
- data/lib/monetra/active_support/core_ext/hash.rb +13 -0
- data/lib/monetra/active_support/core_ext/hash/conversions.rb +148 -0
- data/lib/monetra/active_support/core_ext/hash/diff.rb +11 -0
- data/lib/monetra/active_support/core_ext/hash/indifferent_access.rb +88 -0
- data/lib/monetra/active_support/core_ext/hash/keys.rb +53 -0
- data/lib/monetra/active_support/core_ext/hash/reverse_merge.rb +25 -0
- data/lib/monetra/active_support/core_ext/integer.rb +7 -0
- data/lib/monetra/active_support/core_ext/integer/even_odd.rb +24 -0
- data/lib/monetra/active_support/core_ext/integer/inflections.rb +15 -0
- data/lib/monetra/active_support/core_ext/kernel.rb +4 -0
- data/lib/monetra/active_support/core_ext/kernel/agnostics.rb +11 -0
- data/lib/monetra/active_support/core_ext/kernel/daemonizing.rb +15 -0
- data/lib/monetra/active_support/core_ext/kernel/reporting.rb +51 -0
- data/lib/monetra/active_support/core_ext/kernel/requires.rb +24 -0
- data/lib/monetra/active_support/core_ext/load_error.rb +38 -0
- data/lib/monetra/active_support/core_ext/logger.rb +16 -0
- data/lib/monetra/active_support/core_ext/module.rb +7 -0
- data/lib/monetra/active_support/core_ext/module/aliasing.rb +57 -0
- data/lib/monetra/active_support/core_ext/module/attr_internal.rb +31 -0
- data/lib/monetra/active_support/core_ext/module/attribute_accessors.rb +44 -0
- data/lib/monetra/active_support/core_ext/module/delegation.rb +41 -0
- data/lib/monetra/active_support/core_ext/module/inclusion.rb +11 -0
- data/lib/monetra/active_support/core_ext/module/introspection.rb +21 -0
- data/lib/monetra/active_support/core_ext/module/loading.rb +13 -0
- data/lib/monetra/active_support/core_ext/name_error.rb +20 -0
- data/lib/monetra/active_support/core_ext/numeric.rb +7 -0
- data/lib/monetra/active_support/core_ext/numeric/bytes.rb +44 -0
- data/lib/monetra/active_support/core_ext/numeric/time.rb +72 -0
- data/lib/monetra/active_support/core_ext/object.rb +2 -0
- data/lib/monetra/active_support/core_ext/object/extending.rb +47 -0
- data/lib/monetra/active_support/core_ext/object/misc.rb +34 -0
- data/lib/monetra/active_support/core_ext/pathname.rb +7 -0
- data/lib/monetra/active_support/core_ext/pathname/clean_within.rb +14 -0
- data/lib/monetra/active_support/core_ext/proc.rb +12 -0
- data/lib/monetra/active_support/core_ext/range.rb +5 -0
- data/lib/monetra/active_support/core_ext/range/conversions.rb +21 -0
- data/lib/monetra/active_support/core_ext/string.rb +13 -0
- data/lib/monetra/active_support/core_ext/string/access.rb +58 -0
- data/lib/monetra/active_support/core_ext/string/conversions.rb +19 -0
- data/lib/monetra/active_support/core_ext/string/inflections.rb +153 -0
- data/lib/monetra/active_support/core_ext/string/iterators.rb +17 -0
- data/lib/monetra/active_support/core_ext/string/starts_ends_with.rb +20 -0
- data/lib/monetra/active_support/core_ext/symbol.rb +12 -0
- data/lib/monetra/active_support/core_ext/time.rb +7 -0
- data/lib/monetra/active_support/core_ext/time/calculations.rb +188 -0
- data/lib/monetra/active_support/core_ext/time/conversions.rb +36 -0
- data/lib/monetra/active_support/dependencies.rb +187 -0
- data/lib/monetra/active_support/deprecation.rb +106 -0
- data/lib/monetra/active_support/inflections.rb +53 -0
- data/lib/monetra/active_support/inflector.rb +179 -0
- data/lib/monetra/active_support/json.rb +37 -0
- data/lib/monetra/active_support/json/encoders.rb +25 -0
- data/lib/monetra/active_support/json/encoders/core.rb +65 -0
- data/lib/monetra/active_support/option_merger.rb +25 -0
- data/lib/monetra/active_support/ordered_options.rb +50 -0
- data/lib/monetra/active_support/reloadable.rb +30 -0
- data/lib/monetra/active_support/values/time_zone.rb +180 -0
- data/lib/monetra/active_support/vendor/builder.rb +13 -0
- data/lib/monetra/active_support/vendor/builder/blankslate.rb +63 -0
- data/lib/monetra/active_support/vendor/builder/xchar.rb +112 -0
- data/lib/monetra/active_support/vendor/builder/xmlbase.rb +145 -0
- data/lib/monetra/active_support/vendor/builder/xmlevents.rb +63 -0
- data/lib/monetra/active_support/vendor/builder/xmlmarkup.rb +328 -0
- data/lib/monetra/active_support/vendor/flexmock.rb +84 -0
- data/lib/monetra/active_support/vendor/xml_simple.rb +1019 -0
- data/lib/monetra/active_support/version.rb +9 -0
- data/lib/monetra/active_support/whiny_nil.rb +38 -0
- data/test/test.rb +21 -0
- metadata +167 -0
@@ -0,0 +1,106 @@
|
|
1
|
+
module ActiveSupport
|
2
|
+
module Deprecation
|
3
|
+
# Choose the default warn behavior according to RAILS_ENV.
|
4
|
+
# Ignore deprecation warnings in production.
|
5
|
+
DEFAULT_BEHAVIORS = {
|
6
|
+
'test' => Proc.new { |message| $stderr.puts message },
|
7
|
+
'development' => Proc.new { |message| RAILS_DEFAULT_LOGGER.warn message },
|
8
|
+
}
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def warn(message = nil, callstack = caller)
|
12
|
+
behavior.call(deprecation_message(callstack, message)) if behavior
|
13
|
+
end
|
14
|
+
|
15
|
+
def default_behavior
|
16
|
+
DEFAULT_BEHAVIORS[RAILS_ENV.to_s] if defined?(RAILS_ENV)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
def deprecation_message(callstack, message = nil)
|
21
|
+
file, line, method = extract_callstack(callstack)
|
22
|
+
message ||= "WARNING: #{method} is deprecated and will be removed from the next Rails release"
|
23
|
+
"#{message} (#{method} at #{file}:#{line})"
|
24
|
+
end
|
25
|
+
|
26
|
+
def extract_callstack(callstack)
|
27
|
+
callstack.first.match(/^(.+?):(\d+)(?::in `(.*?)')?/).captures
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Behavior is a block that takes a message argument.
|
32
|
+
mattr_accessor :behavior
|
33
|
+
self.behavior = default_behavior
|
34
|
+
|
35
|
+
module ClassMethods
|
36
|
+
# Declare that a method has been deprecated.
|
37
|
+
def deprecate(*method_names)
|
38
|
+
method_names.each do |method_name|
|
39
|
+
class_eval(<<-EOS, __FILE__, __LINE__)
|
40
|
+
def #{method_name}_with_deprecation(*args, &block)
|
41
|
+
::ActiveSupport::Deprecation.warn
|
42
|
+
#{method_name}_without_deprecation(*args, &block)
|
43
|
+
end
|
44
|
+
EOS
|
45
|
+
alias_method_chain(method_name, :deprecation)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
module Assertions
|
51
|
+
def assert_deprecated(match = nil, &block)
|
52
|
+
last = with_last_message_tracking_deprecation_behavior(&block)
|
53
|
+
assert last, "Expected a deprecation warning within the block but received none"
|
54
|
+
match = Regexp.new(Regexp.escape(match)) unless match.is_a?(Regexp)
|
55
|
+
assert_match match, last, "Deprecation warning didn't match #{match}: #{last}"
|
56
|
+
end
|
57
|
+
|
58
|
+
def assert_not_deprecated(&block)
|
59
|
+
last = with_last_message_tracking_deprecation_behavior(&block)
|
60
|
+
assert_nil last, "Expected no deprecation warning within the block but received one: #{last}"
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
def with_last_message_tracking_deprecation_behavior
|
65
|
+
old_behavior = ActiveSupport::Deprecation.behavior
|
66
|
+
last_message = nil
|
67
|
+
ActiveSupport::Deprecation.behavior = Proc.new { |message| last_message = message; old_behavior.call(message) if old_behavior }
|
68
|
+
yield
|
69
|
+
last_message
|
70
|
+
ensure
|
71
|
+
ActiveSupport::Deprecation.behavior = old_behavior
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Stand-in for @request, @attributes, etc.
|
76
|
+
class DeprecatedInstanceVariableProxy
|
77
|
+
instance_methods.each { |m| undef_method m unless m =~ /^__/ }
|
78
|
+
|
79
|
+
def initialize(instance, method, var = "@#{method}")
|
80
|
+
@instance, @method, @var = instance, method, var
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
def warn(callstack, called, args)
|
85
|
+
ActiveSupport::Deprecation.warn("#{@var} is deprecated! Call #{@method}.#{called} instead of #{@var}.#{called}. Args: #{args.inspect}", callstack)
|
86
|
+
end
|
87
|
+
|
88
|
+
def method_missing(called, *args, &block)
|
89
|
+
warn caller, called, args
|
90
|
+
@instance.__send__(@method).__send__(called, *args, &block)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
class Class
|
97
|
+
include ActiveSupport::Deprecation::ClassMethods
|
98
|
+
end
|
99
|
+
|
100
|
+
module Test
|
101
|
+
module Unit
|
102
|
+
class TestCase
|
103
|
+
include ActiveSupport::Deprecation::Assertions
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
Inflector.inflections do |inflect|
|
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
|
+
|
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
|
+
|
52
|
+
inflect.uncountable(%w(equipment information rice money species series fish sheep))
|
53
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
# The Inflector transforms words from singular to plural, class names to table names, modularized class names to ones without,
|
4
|
+
# and class names to foreign keys. The default inflections for pluralization, singularization, and uncountable words are kept
|
5
|
+
# in inflections.rb.
|
6
|
+
module Inflector
|
7
|
+
# A singleton instance of this class is yielded by Inflector.inflections, which can then be used to specify additional
|
8
|
+
# inflection rules. Examples:
|
9
|
+
#
|
10
|
+
# Inflector.inflections do |inflect|
|
11
|
+
# inflect.plural /^(ox)$/i, '\1\2en'
|
12
|
+
# inflect.singular /^(ox)en/i, '\1'
|
13
|
+
#
|
14
|
+
# inflect.irregular 'octopus', 'octopi'
|
15
|
+
#
|
16
|
+
# inflect.uncountable "equipment"
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# New rules are added at the top. So in the example above, the irregular rule for octopus will now be the first of the
|
20
|
+
# pluralization and singularization rules that is runs. This guarantees that your rules run before any of the rules that may
|
21
|
+
# already have been loaded.
|
22
|
+
class Inflections
|
23
|
+
include Singleton
|
24
|
+
|
25
|
+
attr_reader :plurals, :singulars, :uncountables
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@plurals, @singulars, @uncountables = [], [], []
|
29
|
+
end
|
30
|
+
|
31
|
+
# Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression.
|
32
|
+
# The replacement should always be a string that may include references to the matched data from the rule.
|
33
|
+
def plural(rule, replacement)
|
34
|
+
@plurals.insert(0, [rule, replacement])
|
35
|
+
end
|
36
|
+
|
37
|
+
# Specifies a new singularization 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 singular(rule, replacement)
|
40
|
+
@singulars.insert(0, [rule, replacement])
|
41
|
+
end
|
42
|
+
|
43
|
+
# Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used
|
44
|
+
# for strings, not regular expressions. You simply pass the irregular in singular and plural form.
|
45
|
+
#
|
46
|
+
# Examples:
|
47
|
+
# irregular 'octopus', 'octopi'
|
48
|
+
# irregular 'person', 'people'
|
49
|
+
def irregular(singular, plural)
|
50
|
+
plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1])
|
51
|
+
singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1])
|
52
|
+
end
|
53
|
+
|
54
|
+
# Add uncountable words that shouldn't be attempted inflected.
|
55
|
+
#
|
56
|
+
# Examples:
|
57
|
+
# uncountable "money"
|
58
|
+
# uncountable "money", "information"
|
59
|
+
# uncountable %w( money information rice )
|
60
|
+
def uncountable(*words)
|
61
|
+
(@uncountables << words).flatten!
|
62
|
+
end
|
63
|
+
|
64
|
+
# Clears the loaded inflections within a given scope (default is :all). Give the scope as a symbol of the inflection type,
|
65
|
+
# the options are: :plurals, :singulars, :uncountables
|
66
|
+
#
|
67
|
+
# Examples:
|
68
|
+
# clear :all
|
69
|
+
# clear :plurals
|
70
|
+
def clear(scope = :all)
|
71
|
+
case scope
|
72
|
+
when :all
|
73
|
+
@plurals, @singulars, @uncountables = [], [], []
|
74
|
+
else
|
75
|
+
instance_variable_set "@#{scope}", []
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
extend self
|
81
|
+
|
82
|
+
def inflections
|
83
|
+
if block_given?
|
84
|
+
yield Inflections.instance
|
85
|
+
else
|
86
|
+
Inflections.instance
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def pluralize(word)
|
91
|
+
result = word.to_s.dup
|
92
|
+
|
93
|
+
if inflections.uncountables.include?(result.downcase)
|
94
|
+
result
|
95
|
+
else
|
96
|
+
inflections.plurals.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
|
97
|
+
result
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def singularize(word)
|
102
|
+
result = word.to_s.dup
|
103
|
+
|
104
|
+
if inflections.uncountables.include?(result.downcase)
|
105
|
+
result
|
106
|
+
else
|
107
|
+
inflections.singulars.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
|
108
|
+
result
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
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
|
118
|
+
end
|
119
|
+
|
120
|
+
def titleize(word)
|
121
|
+
humanize(underscore(word)).gsub(/\b([a-z])/) { $1.capitalize }
|
122
|
+
end
|
123
|
+
|
124
|
+
def underscore(camel_cased_word)
|
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(/_/, '-')
|
134
|
+
end
|
135
|
+
|
136
|
+
def humanize(lower_case_and_underscored_word)
|
137
|
+
lower_case_and_underscored_word.to_s.gsub(/_id$/, "").gsub(/_/, " ").capitalize
|
138
|
+
end
|
139
|
+
|
140
|
+
def demodulize(class_name_in_module)
|
141
|
+
class_name_in_module.to_s.gsub(/^.*::/, '')
|
142
|
+
end
|
143
|
+
|
144
|
+
def tableize(class_name)
|
145
|
+
pluralize(underscore(class_name))
|
146
|
+
end
|
147
|
+
|
148
|
+
def classify(table_name)
|
149
|
+
# strip out any leading schema name
|
150
|
+
camelize(singularize(table_name.to_s.sub(/.*\./, '')))
|
151
|
+
end
|
152
|
+
|
153
|
+
def foreign_key(class_name, separate_class_name_and_id_with_underscore = true)
|
154
|
+
underscore(demodulize(class_name)) + (separate_class_name_and_id_with_underscore ? "_id" : "id")
|
155
|
+
end
|
156
|
+
|
157
|
+
def constantize(camel_cased_word)
|
158
|
+
raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!" unless
|
159
|
+
/^(::)?([A-Z]\w*)(::[A-Z]\w*)*$/ =~ camel_cased_word
|
160
|
+
|
161
|
+
camel_cased_word = "::#{camel_cased_word}" unless $1
|
162
|
+
Object.module_eval(camel_cased_word, __FILE__, __LINE__)
|
163
|
+
end
|
164
|
+
|
165
|
+
def ordinalize(number)
|
166
|
+
if (11..13).include?(number.to_i % 100)
|
167
|
+
"#{number}th"
|
168
|
+
else
|
169
|
+
case number.to_i % 10
|
170
|
+
when 1: "#{number}st"
|
171
|
+
when 2: "#{number}nd"
|
172
|
+
when 3: "#{number}rd"
|
173
|
+
else "#{number}th"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
require File.dirname(__FILE__) + '/inflections'
|
@@ -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
|