activesupport 4.0.13 → 4.2.11.3
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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +406 -418
- data/MIT-LICENSE +1 -1
- data/README.rdoc +7 -2
- data/lib/active_support/backtrace_cleaner.rb +8 -8
- data/lib/active_support/benchmarkable.rb +0 -10
- data/lib/active_support/cache/file_store.rb +32 -22
- data/lib/active_support/cache/mem_cache_store.rb +5 -7
- data/lib/active_support/cache/memory_store.rb +1 -0
- data/lib/active_support/cache/strategy/local_cache.rb +11 -30
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +44 -0
- data/lib/active_support/cache.rb +75 -41
- data/lib/active_support/callbacks.rb +482 -261
- data/lib/active_support/concern.rb +23 -7
- data/lib/active_support/configurable.rb +1 -1
- data/lib/active_support/core_ext/array/access.rb +11 -1
- data/lib/active_support/core_ext/array/conversions.rb +2 -17
- data/lib/active_support/core_ext/array/grouping.rb +29 -12
- data/lib/active_support/core_ext/array/prepend_and_append.rb +2 -2
- data/lib/active_support/core_ext/array.rb +0 -1
- data/lib/active_support/core_ext/big_decimal/conversions.rb +0 -15
- data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +16 -0
- data/lib/active_support/core_ext/class/attribute.rb +1 -2
- data/lib/active_support/core_ext/class/attribute_accessors.rb +4 -170
- data/lib/active_support/core_ext/class/delegating_attributes.rb +13 -8
- data/lib/active_support/core_ext/class/subclasses.rb +0 -2
- data/lib/active_support/core_ext/class.rb +0 -1
- data/lib/active_support/core_ext/date/calculations.rb +10 -0
- data/lib/active_support/core_ext/date/conversions.rb +9 -1
- data/lib/active_support/core_ext/date/zones.rb +2 -33
- data/lib/active_support/core_ext/date_and_time/calculations.rb +41 -11
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
- data/lib/active_support/core_ext/date_and_time/zones.rb +41 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +45 -22
- data/lib/active_support/core_ext/date_time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +4 -2
- data/lib/active_support/core_ext/date_time/zones.rb +3 -21
- data/lib/active_support/core_ext/date_time.rb +1 -0
- data/lib/active_support/core_ext/digest/uuid.rb +51 -0
- data/lib/active_support/core_ext/enumerable.rb +17 -1
- data/lib/active_support/core_ext/file/atomic.rb +1 -1
- data/lib/active_support/core_ext/hash/compact.rb +24 -0
- data/lib/active_support/core_ext/hash/conversions.rb +9 -8
- data/lib/active_support/core_ext/hash/except.rb +8 -2
- data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -0
- data/lib/active_support/core_ext/hash/keys.rb +25 -19
- data/lib/active_support/core_ext/hash/slice.rb +8 -2
- data/lib/active_support/core_ext/hash/transform_values.rb +23 -0
- data/lib/active_support/core_ext/hash.rb +2 -1
- data/lib/active_support/core_ext/integer/time.rb +0 -15
- data/lib/active_support/core_ext/kernel/concern.rb +10 -0
- data/lib/active_support/core_ext/kernel/debugger.rb +1 -1
- data/lib/active_support/core_ext/kernel/reporting.rb +13 -2
- data/lib/active_support/core_ext/kernel.rb +3 -2
- data/lib/active_support/core_ext/load_error.rb +4 -1
- data/lib/active_support/core_ext/marshal.rb +8 -5
- data/lib/active_support/core_ext/module/aliasing.rb +2 -2
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -1
- data/lib/active_support/core_ext/module/attribute_accessors.rb +160 -14
- data/lib/active_support/core_ext/module/concerning.rb +135 -0
- data/lib/active_support/core_ext/module/delegation.rb +53 -25
- data/lib/active_support/core_ext/module/deprecation.rb +0 -2
- data/lib/active_support/core_ext/module/introspection.rb +0 -16
- data/lib/active_support/core_ext/module/method_transplanting.rb +13 -0
- data/lib/active_support/core_ext/module.rb +1 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +11 -3
- data/lib/active_support/core_ext/numeric/time.rb +4 -29
- data/lib/active_support/core_ext/object/blank.rb +44 -18
- data/lib/active_support/core_ext/object/deep_dup.rb +6 -6
- data/lib/active_support/core_ext/object/duplicable.rb +72 -33
- data/lib/active_support/core_ext/object/inclusion.rb +16 -15
- data/lib/active_support/core_ext/object/itself.rb +15 -0
- data/lib/active_support/core_ext/object/json.rb +197 -0
- data/lib/active_support/core_ext/object/to_query.rb +14 -6
- data/lib/active_support/core_ext/object/try.rb +36 -14
- data/lib/active_support/core_ext/object/with_options.rb +30 -3
- data/lib/active_support/core_ext/object.rb +2 -1
- data/lib/active_support/core_ext/string/access.rb +35 -35
- data/lib/active_support/core_ext/string/conversions.rb +10 -9
- data/lib/active_support/core_ext/string/exclude.rb +3 -3
- data/lib/active_support/core_ext/string/filters.rb +51 -3
- data/lib/active_support/core_ext/string/inflections.rb +15 -10
- data/lib/active_support/core_ext/string/output_safety.rb +97 -33
- data/lib/active_support/core_ext/string/zones.rb +1 -0
- data/lib/active_support/core_ext/thread.rb +12 -5
- data/lib/active_support/core_ext/time/calculations.rb +47 -68
- data/lib/active_support/core_ext/time/compatibility.rb +14 -0
- data/lib/active_support/core_ext/time/conversions.rb +4 -2
- data/lib/active_support/core_ext/time/zones.rb +2 -20
- data/lib/active_support/core_ext/time.rb +1 -0
- data/lib/active_support/core_ext.rb +0 -1
- data/lib/active_support/dependencies/autoload.rb +1 -1
- data/lib/active_support/dependencies.rb +64 -25
- data/lib/active_support/deprecation/behaviors.rb +4 -4
- data/lib/active_support/deprecation.rb +4 -4
- data/lib/active_support/duration.rb +55 -11
- data/lib/active_support/file_update_checker.rb +1 -1
- data/lib/active_support/gem_version.rb +15 -0
- data/lib/active_support/hash_with_indifferent_access.rb +39 -11
- data/lib/active_support/i18n.rb +4 -4
- data/lib/active_support/i18n_railtie.rb +1 -7
- data/lib/active_support/inflections.rb +6 -1
- data/lib/active_support/inflector/inflections.rb +19 -19
- data/lib/active_support/inflector/methods.rb +66 -25
- data/lib/active_support/json/decoding.rb +15 -22
- data/lib/active_support/json/encoding.rb +125 -286
- data/lib/active_support/key_generator.rb +8 -10
- data/lib/active_support/lazy_load_hooks.rb +1 -1
- data/lib/active_support/log_subscriber/test_helper.rb +1 -1
- data/lib/active_support/logger.rb +51 -1
- data/lib/active_support/logger_silence.rb +7 -4
- data/lib/active_support/logger_thread_safe_level.rb +32 -0
- data/lib/active_support/message_encryptor.rb +14 -6
- data/lib/active_support/message_verifier.rb +16 -12
- data/lib/active_support/multibyte/chars.rb +2 -3
- data/lib/active_support/multibyte/unicode.rb +46 -58
- data/lib/active_support/notifications/fanout.rb +12 -7
- data/lib/active_support/notifications/instrumenter.rb +2 -1
- data/lib/active_support/notifications.rb +11 -6
- data/lib/active_support/number_helper/number_converter.rb +182 -0
- data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +23 -0
- data/lib/active_support/number_helper/number_to_human_converter.rb +66 -0
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +58 -0
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +12 -0
- data/lib/active_support/number_helper/number_to_phone_converter.rb +49 -0
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +87 -0
- data/lib/active_support/number_helper.rb +32 -324
- data/lib/active_support/ordered_options.rb +8 -0
- data/lib/active_support/per_thread_registry.rb +13 -10
- data/lib/active_support/security_utils.rb +27 -0
- data/lib/active_support/subscriber.rb +35 -3
- data/lib/active_support/test_case.rb +52 -19
- data/lib/active_support/testing/assertions.rb +1 -31
- data/lib/active_support/testing/autorun.rb +2 -2
- data/lib/active_support/testing/constant_lookup.rb +1 -5
- data/lib/active_support/testing/declarative.rb +7 -21
- data/lib/active_support/testing/isolation.rb +29 -69
- data/lib/active_support/testing/setup_and_teardown.rb +17 -2
- data/lib/active_support/testing/tagged_logging.rb +2 -2
- data/lib/active_support/testing/time_helpers.rb +134 -0
- data/lib/active_support/time.rb +0 -2
- data/lib/active_support/time_with_zone.rb +60 -40
- data/lib/active_support/values/time_zone.rb +101 -101
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/version.rb +4 -7
- data/lib/active_support/xml_mini/jdom.rb +6 -5
- data/lib/active_support/xml_mini/libxml.rb +1 -3
- data/lib/active_support/xml_mini/libxmlsax.rb +1 -4
- data/lib/active_support/xml_mini/nokogiri.rb +1 -3
- data/lib/active_support/xml_mini/nokogirisax.rb +1 -3
- data/lib/active_support/xml_mini/rexml.rb +7 -8
- data/lib/active_support/xml_mini.rb +33 -15
- data/lib/active_support.rb +27 -2
- metadata +43 -43
- data/lib/active_support/basic_object.rb +0 -11
- data/lib/active_support/buffered_logger.rb +0 -21
- data/lib/active_support/core_ext/array/uniq_by.rb +0 -19
- data/lib/active_support/core_ext/hash/diff.rb +0 -14
- data/lib/active_support/core_ext/logger.rb +0 -67
- data/lib/active_support/core_ext/object/to_json.rb +0 -27
- data/lib/active_support/core_ext/proc.rb +0 -17
- data/lib/active_support/core_ext/string/encoding.rb +0 -8
- data/lib/active_support/file_watcher.rb +0 -36
- data/lib/active_support/json/variable.rb +0 -18
- data/lib/active_support/testing/pending.rb +0 -14
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'active_support/core_ext/hash/keys'
|
2
|
+
require 'active_support/core_ext/hash/reverse_merge'
|
2
3
|
|
3
4
|
module ActiveSupport
|
4
5
|
# Implements a hash where keys <tt>:foo</tt> and <tt>"foo"</tt> are considered
|
@@ -55,7 +56,7 @@ module ActiveSupport
|
|
55
56
|
end
|
56
57
|
|
57
58
|
def initialize(constructor = {})
|
58
|
-
if constructor.
|
59
|
+
if constructor.respond_to?(:to_hash)
|
59
60
|
super()
|
60
61
|
update(constructor)
|
61
62
|
else
|
@@ -75,6 +76,7 @@ module ActiveSupport
|
|
75
76
|
hash = hash.to_hash
|
76
77
|
new(hash).tap do |new_hash|
|
77
78
|
new_hash.default = hash.default
|
79
|
+
new_hash.default_proc = hash.default_proc if hash.default_proc
|
78
80
|
end
|
79
81
|
end
|
80
82
|
|
@@ -160,7 +162,7 @@ module ActiveSupport
|
|
160
162
|
#
|
161
163
|
# counters.fetch('foo') # => 1
|
162
164
|
# counters.fetch(:bar, 0) # => 0
|
163
|
-
# counters.fetch(:bar) {|key| 0} # => 0
|
165
|
+
# counters.fetch(:bar) { |key| 0 } # => 0
|
164
166
|
# counters.fetch(:zoo) # => KeyError: key not found: "zoo"
|
165
167
|
def fetch(key, *extras)
|
166
168
|
super(convert_key(key), *extras)
|
@@ -173,13 +175,20 @@ module ActiveSupport
|
|
173
175
|
# hash[:b] = 'y'
|
174
176
|
# hash.values_at('a', 'b') # => ["x", "y"]
|
175
177
|
def values_at(*indices)
|
176
|
-
indices.collect {|key| self[convert_key(key)]}
|
178
|
+
indices.collect { |key| self[convert_key(key)] }
|
177
179
|
end
|
178
180
|
|
179
|
-
# Returns
|
181
|
+
# Returns a shallow copy of the hash.
|
182
|
+
#
|
183
|
+
# hash = ActiveSupport::HashWithIndifferentAccess.new({ a: { b: 'b' } })
|
184
|
+
# dup = hash.dup
|
185
|
+
# dup[:a][:c] = 'c'
|
186
|
+
#
|
187
|
+
# hash[:a][:c] # => nil
|
188
|
+
# dup[:a][:c] # => "c"
|
180
189
|
def dup
|
181
190
|
self.class.new(self).tap do |new_hash|
|
182
|
-
new_hash
|
191
|
+
set_defaults(new_hash)
|
183
192
|
end
|
184
193
|
end
|
185
194
|
|
@@ -208,7 +217,7 @@ module ActiveSupport
|
|
208
217
|
# Replaces the contents of this hash with other_hash.
|
209
218
|
#
|
210
219
|
# h = { "a" => 100, "b" => 200 }
|
211
|
-
# h.replace({ "c" => 300, "d" => 400 })
|
220
|
+
# h.replace({ "c" => 300, "d" => 400 }) # => {"c"=>300, "d"=>400}
|
212
221
|
def replace(other_hash)
|
213
222
|
super(self.class.new_from_hash_copying_default(other_hash))
|
214
223
|
end
|
@@ -225,7 +234,7 @@ module ActiveSupport
|
|
225
234
|
undef :symbolize_keys!
|
226
235
|
undef :deep_symbolize_keys!
|
227
236
|
def symbolize_keys; to_hash.symbolize_keys! end
|
228
|
-
def deep_symbolize_keys; to_hash.deep_symbolize_keys end
|
237
|
+
def deep_symbolize_keys; to_hash.deep_symbolize_keys! end
|
229
238
|
def to_options!; self end
|
230
239
|
|
231
240
|
def select(*args, &block)
|
@@ -236,13 +245,24 @@ module ActiveSupport
|
|
236
245
|
dup.tap { |hash| hash.reject!(*args, &block) }
|
237
246
|
end
|
238
247
|
|
248
|
+
def transform_values(*args, &block)
|
249
|
+
return to_enum(:transform_values) unless block_given?
|
250
|
+
dup.tap { |hash| hash.transform_values!(*args, &block) }
|
251
|
+
end
|
252
|
+
|
253
|
+
def compact
|
254
|
+
dup.tap(&:compact!)
|
255
|
+
end
|
256
|
+
|
239
257
|
# Convert to a regular hash with string keys.
|
240
258
|
def to_hash
|
241
|
-
_new_hash=
|
259
|
+
_new_hash = Hash.new
|
260
|
+
set_defaults(_new_hash)
|
261
|
+
|
242
262
|
each do |key, value|
|
243
|
-
_new_hash[
|
263
|
+
_new_hash[key] = convert_value(value, for: :to_hash)
|
244
264
|
end
|
245
|
-
|
265
|
+
_new_hash
|
246
266
|
end
|
247
267
|
|
248
268
|
protected
|
@@ -258,7 +278,7 @@ module ActiveSupport
|
|
258
278
|
value.nested_under_indifferent_access
|
259
279
|
end
|
260
280
|
elsif value.is_a?(Array)
|
261
|
-
|
281
|
+
if options[:for] != :assignment || value.frozen?
|
262
282
|
value = value.dup
|
263
283
|
end
|
264
284
|
value.map! { |e| convert_value(e, options) }
|
@@ -266,6 +286,14 @@ module ActiveSupport
|
|
266
286
|
value
|
267
287
|
end
|
268
288
|
end
|
289
|
+
|
290
|
+
def set_defaults(target)
|
291
|
+
if default_proc
|
292
|
+
target.default_proc = default_proc.dup
|
293
|
+
else
|
294
|
+
target.default = default
|
295
|
+
end
|
296
|
+
end
|
269
297
|
end
|
270
298
|
end
|
271
299
|
|
data/lib/active_support/i18n.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
|
+
require 'active_support/core_ext/hash/deep_merge'
|
2
|
+
require 'active_support/core_ext/hash/except'
|
3
|
+
require 'active_support/core_ext/hash/slice'
|
1
4
|
begin
|
2
|
-
require 'active_support/core_ext/hash/deep_merge'
|
3
|
-
require 'active_support/core_ext/hash/except'
|
4
|
-
require 'active_support/core_ext/hash/slice'
|
5
5
|
require 'i18n'
|
6
|
-
require 'active_support/lazy_load_hooks'
|
7
6
|
rescue LoadError => e
|
8
7
|
$stderr.puts "The i18n gem is not available. Please add it to your Gemfile and run bundle install"
|
9
8
|
raise e
|
10
9
|
end
|
10
|
+
require 'active_support/lazy_load_hooks'
|
11
11
|
|
12
12
|
ActiveSupport.run_load_hooks(:i18n)
|
13
13
|
I18n.load_path << "#{File.dirname(__FILE__)}/locale/en.yml"
|
@@ -8,8 +8,6 @@ module I18n
|
|
8
8
|
config.i18n.railties_load_path = []
|
9
9
|
config.i18n.load_path = []
|
10
10
|
config.i18n.fallbacks = ActiveSupport::OrderedOptions.new
|
11
|
-
# Enforce I18n to check the available locales when setting a locale.
|
12
|
-
config.i18n.enforce_available_locales = true
|
13
11
|
|
14
12
|
# Set the i18n configuration after initialization since a lot of
|
15
13
|
# configuration is still usually done in application initializers.
|
@@ -36,11 +34,7 @@ module I18n
|
|
36
34
|
# Avoid issues with setting the default_locale by disabling available locales
|
37
35
|
# check while configuring.
|
38
36
|
enforce_available_locales = app.config.i18n.delete(:enforce_available_locales)
|
39
|
-
|
40
|
-
if enforce_available_locales.nil?
|
41
|
-
enforce_available_locales = I18n.enforce_available_locales
|
42
|
-
end
|
43
|
-
|
37
|
+
enforce_available_locales = I18n.enforce_available_locales if enforce_available_locales.nil?
|
44
38
|
I18n.enforce_available_locales = false
|
45
39
|
|
46
40
|
app.config.i18n.each do |setting, value|
|
@@ -1,5 +1,11 @@
|
|
1
1
|
require 'active_support/inflector/inflections'
|
2
2
|
|
3
|
+
#--
|
4
|
+
# Defines the standard inflection rules. These are the starting point for
|
5
|
+
# new projects and are not considered complete. The current set of inflection
|
6
|
+
# rules is frozen. This means, we do not change them to become more complete.
|
7
|
+
# This is a safety measure to keep existing applications from breaking.
|
8
|
+
#++
|
3
9
|
module ActiveSupport
|
4
10
|
Inflector.inflections(:en) do |inflect|
|
5
11
|
inflect.plural(/$/, 's')
|
@@ -57,7 +63,6 @@ module ActiveSupport
|
|
57
63
|
inflect.irregular('child', 'children')
|
58
64
|
inflect.irregular('sex', 'sexes')
|
59
65
|
inflect.irregular('move', 'moves')
|
60
|
-
inflect.irregular('cow', 'kine')
|
61
66
|
inflect.irregular('zombie', 'zombies')
|
62
67
|
|
63
68
|
inflect.uncountable(%w(equipment information rice money species series fish sheep jeans police))
|
@@ -52,21 +52,21 @@ module ActiveSupport
|
|
52
52
|
# into a non-delimited single lowercase word when passed to +underscore+.
|
53
53
|
#
|
54
54
|
# acronym 'HTML'
|
55
|
-
# titleize 'html'
|
56
|
-
# camelize 'html'
|
57
|
-
# underscore 'MyHTML'
|
55
|
+
# titleize 'html' # => 'HTML'
|
56
|
+
# camelize 'html' # => 'HTML'
|
57
|
+
# underscore 'MyHTML' # => 'my_html'
|
58
58
|
#
|
59
59
|
# The acronym, however, must occur as a delimited unit and not be part of
|
60
60
|
# another word for conversions to recognize it:
|
61
61
|
#
|
62
62
|
# acronym 'HTTP'
|
63
|
-
# camelize 'my_http_delimited'
|
64
|
-
# camelize 'https'
|
65
|
-
# underscore 'HTTPS'
|
63
|
+
# camelize 'my_http_delimited' # => 'MyHTTPDelimited'
|
64
|
+
# camelize 'https' # => 'Https', not 'HTTPs'
|
65
|
+
# underscore 'HTTPS' # => 'http_s', not 'https'
|
66
66
|
#
|
67
67
|
# acronym 'HTTPS'
|
68
|
-
# camelize 'https'
|
69
|
-
# underscore 'HTTPS'
|
68
|
+
# camelize 'https' # => 'HTTPS'
|
69
|
+
# underscore 'HTTPS' # => 'https'
|
70
70
|
#
|
71
71
|
# Note: Acronyms that are passed to +pluralize+ will no longer be
|
72
72
|
# recognized, since the acronym will not occur as a delimited unit in the
|
@@ -74,25 +74,25 @@ module ActiveSupport
|
|
74
74
|
# form as an acronym as well:
|
75
75
|
#
|
76
76
|
# acronym 'API'
|
77
|
-
# camelize(pluralize('api'))
|
77
|
+
# camelize(pluralize('api')) # => 'Apis'
|
78
78
|
#
|
79
79
|
# acronym 'APIs'
|
80
|
-
# camelize(pluralize('api'))
|
80
|
+
# camelize(pluralize('api')) # => 'APIs'
|
81
81
|
#
|
82
82
|
# +acronym+ may be used to specify any word that contains an acronym or
|
83
83
|
# otherwise needs to maintain a non-standard capitalization. The only
|
84
84
|
# restriction is that the word must begin with a capital letter.
|
85
85
|
#
|
86
86
|
# acronym 'RESTful'
|
87
|
-
# underscore 'RESTful'
|
88
|
-
# underscore 'RESTfulController'
|
89
|
-
# titleize 'RESTfulController'
|
90
|
-
# camelize 'restful'
|
91
|
-
# camelize 'restful_controller'
|
87
|
+
# underscore 'RESTful' # => 'restful'
|
88
|
+
# underscore 'RESTfulController' # => 'restful_controller'
|
89
|
+
# titleize 'RESTfulController' # => 'RESTful Controller'
|
90
|
+
# camelize 'restful' # => 'RESTful'
|
91
|
+
# camelize 'restful_controller' # => 'RESTfulController'
|
92
92
|
#
|
93
93
|
# acronym 'McDonald'
|
94
|
-
# underscore 'McDonald'
|
95
|
-
# camelize 'mcdonald'
|
94
|
+
# underscore 'McDonald' # => 'mcdonald'
|
95
|
+
# camelize 'mcdonald' # => 'McDonald'
|
96
96
|
def acronym(word)
|
97
97
|
@acronyms[word.downcase] = word
|
98
98
|
@acronym_regex = /#{@acronyms.values.join("|")}/
|
@@ -154,13 +154,13 @@ module ActiveSupport
|
|
154
154
|
end
|
155
155
|
end
|
156
156
|
|
157
|
-
#
|
157
|
+
# Specifies words that are uncountable and should not be inflected.
|
158
158
|
#
|
159
159
|
# uncountable 'money'
|
160
160
|
# uncountable 'money', 'information'
|
161
161
|
# uncountable %w( money information rice )
|
162
162
|
def uncountable(*words)
|
163
|
-
|
163
|
+
@uncountables += words.flatten.map(&:downcase)
|
164
164
|
end
|
165
165
|
|
166
166
|
# Specifies a humanized form of a string by a regular expression rule or
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
require 'active_support/inflector/inflections'
|
4
3
|
require 'active_support/inflections'
|
5
4
|
|
6
5
|
module ActiveSupport
|
@@ -37,7 +36,7 @@ module ActiveSupport
|
|
37
36
|
# string.
|
38
37
|
#
|
39
38
|
# If passed an optional +locale+ parameter, the word will be
|
40
|
-
#
|
39
|
+
# singularized using rules defined for that language. By default,
|
41
40
|
# this parameter is set to <tt>:en</tt>.
|
42
41
|
#
|
43
42
|
# 'posts'.singularize # => "post"
|
@@ -73,7 +72,9 @@ module ActiveSupport
|
|
73
72
|
else
|
74
73
|
string = string.sub(/^(?:#{inflections.acronym_regex}(?=\b|[A-Z_])|\w)/) { $&.downcase }
|
75
74
|
end
|
76
|
-
string.gsub(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{inflections.acronyms[$2] || $2.capitalize}" }
|
75
|
+
string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{inflections.acronyms[$2] || $2.capitalize}" }
|
76
|
+
string.gsub!(/\//, '::')
|
77
|
+
string
|
77
78
|
end
|
78
79
|
|
79
80
|
# Makes an underscored, lowercase form from the expression in the string.
|
@@ -88,9 +89,9 @@ module ActiveSupport
|
|
88
89
|
#
|
89
90
|
# 'SSLError'.underscore.camelize # => "SslError"
|
90
91
|
def underscore(camel_cased_word)
|
91
|
-
|
92
|
-
word.gsub
|
93
|
-
word.gsub!(/(?:([A-Za-z\d])
|
92
|
+
return camel_cased_word unless camel_cased_word =~ /[A-Z-]|::/
|
93
|
+
word = camel_cased_word.to_s.gsub(/::/, '/')
|
94
|
+
word.gsub!(/(?:(?<=([A-Za-z\d]))|\b)(#{inflections.acronym_regex})(?=\b|[^a-z])/) { "#{$1 && '_'}#{$2.downcase}" }
|
94
95
|
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
|
95
96
|
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
96
97
|
word.tr!("-", "_")
|
@@ -98,20 +99,47 @@ module ActiveSupport
|
|
98
99
|
word
|
99
100
|
end
|
100
101
|
|
101
|
-
#
|
102
|
-
#
|
103
|
-
#
|
102
|
+
# Tweaks an attribute name for display to end users.
|
103
|
+
#
|
104
|
+
# Specifically, +humanize+ performs these transformations:
|
105
|
+
#
|
106
|
+
# * Applies human inflection rules to the argument.
|
107
|
+
# * Deletes leading underscores, if any.
|
108
|
+
# * Removes a "_id" suffix if present.
|
109
|
+
# * Replaces underscores with spaces, if any.
|
110
|
+
# * Downcases all words except acronyms.
|
111
|
+
# * Capitalizes the first word.
|
112
|
+
#
|
113
|
+
# The capitalization of the first word can be turned off by setting the
|
114
|
+
# +:capitalize+ option to false (default is true).
|
115
|
+
#
|
116
|
+
# humanize('employee_salary') # => "Employee salary"
|
117
|
+
# humanize('author_id') # => "Author"
|
118
|
+
# humanize('author_id', capitalize: false) # => "author"
|
119
|
+
# humanize('_id') # => "Id"
|
104
120
|
#
|
105
|
-
#
|
106
|
-
#
|
107
|
-
|
121
|
+
# If "SSL" was defined to be an acronym:
|
122
|
+
#
|
123
|
+
# humanize('ssl_error') # => "SSL error"
|
124
|
+
#
|
125
|
+
def humanize(lower_case_and_underscored_word, options = {})
|
108
126
|
result = lower_case_and_underscored_word.to_s.dup
|
127
|
+
|
109
128
|
inflections.humans.each { |(rule, replacement)| break if result.sub!(rule, replacement) }
|
110
|
-
|
129
|
+
|
130
|
+
result.sub!(/\A_+/, '')
|
131
|
+
result.sub!(/_id\z/, '')
|
111
132
|
result.tr!('_', ' ')
|
112
|
-
|
133
|
+
|
134
|
+
result.gsub!(/([a-z\d]*)/i) do |match|
|
113
135
|
"#{inflections.acronyms[match] || match.downcase}"
|
114
|
-
|
136
|
+
end
|
137
|
+
|
138
|
+
if options.fetch(:capitalize, true)
|
139
|
+
result.sub!(/\A\w/) { |match| match.upcase }
|
140
|
+
end
|
141
|
+
|
142
|
+
result
|
115
143
|
end
|
116
144
|
|
117
145
|
# Capitalizes all the words and replaces some characters in the string to
|
@@ -125,7 +153,7 @@ module ActiveSupport
|
|
125
153
|
# 'TheManWithoutAPast'.titleize # => "The Man Without A Past"
|
126
154
|
# 'raiders_of_the_lost_ark'.titleize # => "Raiders Of The Lost Ark"
|
127
155
|
def titleize(word)
|
128
|
-
humanize(underscore(word)).gsub(/\b(?<!['’`])[a-z]/) {
|
156
|
+
humanize(underscore(word)).gsub(/\b(?<!['’`])[a-z]/) { |match| match.capitalize }
|
129
157
|
end
|
130
158
|
|
131
159
|
# Create the name of a table like Rails does for models to table names. This
|
@@ -147,7 +175,7 @@ module ActiveSupport
|
|
147
175
|
#
|
148
176
|
# Singular names are not handled correctly:
|
149
177
|
#
|
150
|
-
# '
|
178
|
+
# 'calculus'.classify # => "Calculu"
|
151
179
|
def classify(table_name)
|
152
180
|
# strip out any leading schema name
|
153
181
|
camelize(singularize(table_name.to_s.sub(/.*\./, '')))
|
@@ -164,6 +192,8 @@ module ActiveSupport
|
|
164
192
|
#
|
165
193
|
# 'ActiveRecord::CoreExtensions::String::Inflections'.demodulize # => "Inflections"
|
166
194
|
# 'Inflections'.demodulize # => "Inflections"
|
195
|
+
# '::Inflections'.demodulize # => "Inflections"
|
196
|
+
# ''.demodulize # => ""
|
167
197
|
#
|
168
198
|
# See also +deconstantize+.
|
169
199
|
def demodulize(path)
|
@@ -185,7 +215,7 @@ module ActiveSupport
|
|
185
215
|
#
|
186
216
|
# See also +demodulize+.
|
187
217
|
def deconstantize(path)
|
188
|
-
path.to_s[0
|
218
|
+
path.to_s[0, path.rindex('::') || 0] # implementation based on the one in facets' Module#spacename
|
189
219
|
end
|
190
220
|
|
191
221
|
# Creates a foreign key name from a class name.
|
@@ -219,7 +249,12 @@ module ActiveSupport
|
|
219
249
|
# unknown.
|
220
250
|
def constantize(camel_cased_word)
|
221
251
|
names = camel_cased_word.split('::')
|
222
|
-
|
252
|
+
|
253
|
+
# Trigger a built-in NameError exception including the ill-formed constant in the message.
|
254
|
+
Object.const_get(camel_cased_word) if names.empty?
|
255
|
+
|
256
|
+
# Remove the first blank element in case of '::ClassName' notation.
|
257
|
+
names.shift if names.size > 1 && names.first.empty?
|
223
258
|
|
224
259
|
names.inject(Object) do |constant, name|
|
225
260
|
if constant == Object
|
@@ -229,8 +264,8 @@ module ActiveSupport
|
|
229
264
|
next candidate if constant.const_defined?(name, false)
|
230
265
|
next candidate unless Object.const_defined?(name)
|
231
266
|
|
232
|
-
# Go down the ancestors to check
|
233
|
-
#
|
267
|
+
# Go down the ancestors to check if it is owned directly. The check
|
268
|
+
# stops when we reach Object or the end of ancestors tree.
|
234
269
|
constant = constant.ancestors.inject do |const, ancestor|
|
235
270
|
break const if ancestor == Object
|
236
271
|
break ancestor if ancestor.const_defined?(name, false)
|
@@ -268,8 +303,8 @@ module ActiveSupport
|
|
268
303
|
def safe_constantize(camel_cased_word)
|
269
304
|
constantize(camel_cased_word)
|
270
305
|
rescue NameError => e
|
271
|
-
raise
|
272
|
-
e.name.to_s == camel_cased_word.to_s
|
306
|
+
raise if e.name && !(camel_cased_word.to_s.split("::").include?(e.name.to_s) ||
|
307
|
+
e.name.to_s == camel_cased_word.to_s)
|
273
308
|
rescue ArgumentError => e
|
274
309
|
raise unless e.message =~ /not missing constant #{const_regexp(camel_cased_word)}\!$/
|
275
310
|
end
|
@@ -313,10 +348,16 @@ module ActiveSupport
|
|
313
348
|
|
314
349
|
private
|
315
350
|
|
316
|
-
#
|
317
|
-
#
|
351
|
+
# Mounts a regular expression, returned as a string to ease interpolation,
|
352
|
+
# that will match part by part the given constant.
|
353
|
+
#
|
354
|
+
# const_regexp("Foo::Bar::Baz") # => "Foo(::Bar(::Baz)?)?"
|
355
|
+
# const_regexp("::") # => "::"
|
318
356
|
def const_regexp(camel_cased_word) #:nodoc:
|
319
357
|
parts = camel_cased_word.split("::")
|
358
|
+
|
359
|
+
return Regexp.escape(camel_cased_word) if parts.blank?
|
360
|
+
|
320
361
|
last = parts.pop
|
321
362
|
|
322
363
|
parts.reverse.inject(last) do |acc, part|
|
@@ -1,20 +1,30 @@
|
|
1
1
|
require 'active_support/core_ext/module/attribute_accessors'
|
2
2
|
require 'active_support/core_ext/module/delegation'
|
3
|
-
require '
|
3
|
+
require 'json'
|
4
4
|
|
5
5
|
module ActiveSupport
|
6
6
|
# Look for and parse json strings that look like ISO 8601 times.
|
7
7
|
mattr_accessor :parse_json_times
|
8
8
|
|
9
9
|
module JSON
|
10
|
+
# matches YAML-formatted dates
|
11
|
+
DATE_REGEX = /^(?:\d{4}-\d{2}-\d{2}|\d{4}-\d{1,2}-\d{1,2}[T \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?))$/
|
12
|
+
|
10
13
|
class << self
|
11
14
|
# Parses a JSON string (JavaScript Object Notation) into a hash.
|
12
|
-
# See www.json.org for more info.
|
15
|
+
# See http://www.json.org for more info.
|
13
16
|
#
|
14
17
|
# ActiveSupport::JSON.decode("{\"team\":\"rails\",\"players\":\"36\"}")
|
15
18
|
# => {"team" => "rails", "players" => "36"}
|
16
|
-
def decode(json, options ={})
|
17
|
-
|
19
|
+
def decode(json, options = {})
|
20
|
+
if options.present?
|
21
|
+
raise ArgumentError, "In Rails 4.1, ActiveSupport::JSON.decode no longer " \
|
22
|
+
"accepts an options hash for MultiJSON. MultiJSON reached its end of life " \
|
23
|
+
"and has been removed."
|
24
|
+
end
|
25
|
+
|
26
|
+
data = ::JSON.parse(json, quirks_mode: true)
|
27
|
+
|
18
28
|
if ActiveSupport.parse_json_times
|
19
29
|
convert_dates_from(data)
|
20
30
|
else
|
@@ -22,23 +32,6 @@ module ActiveSupport
|
|
22
32
|
end
|
23
33
|
end
|
24
34
|
|
25
|
-
def engine
|
26
|
-
MultiJson.adapter
|
27
|
-
end
|
28
|
-
alias :backend :engine
|
29
|
-
|
30
|
-
def engine=(name)
|
31
|
-
MultiJson.use(name)
|
32
|
-
end
|
33
|
-
alias :backend= :engine=
|
34
|
-
|
35
|
-
def with_backend(name)
|
36
|
-
old_backend, self.backend = backend, name
|
37
|
-
yield
|
38
|
-
ensure
|
39
|
-
self.backend = old_backend
|
40
|
-
end
|
41
|
-
|
42
35
|
# Returns the class of the error that will be raised when there is an
|
43
36
|
# error in decoding JSON. Using this method means you won't directly
|
44
37
|
# depend on the ActiveSupport's JSON implementation, in case it changes
|
@@ -50,7 +43,7 @@ module ActiveSupport
|
|
50
43
|
# Rails.logger.warn("Attempted to decode invalid JSON: #{some_string}")
|
51
44
|
# end
|
52
45
|
def parse_error
|
53
|
-
|
46
|
+
::JSON::ParserError
|
54
47
|
end
|
55
48
|
|
56
49
|
private
|