activesupport 4.0.13 → 4.1.0.beta1
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 +4 -4
- data/CHANGELOG.md +283 -508
- data/README.rdoc +1 -1
- data/lib/active_support.rb +7 -1
- data/lib/active_support/backtrace_cleaner.rb +5 -5
- data/lib/active_support/benchmarkable.rb +0 -10
- data/lib/active_support/cache.rb +62 -26
- data/lib/active_support/cache/file_store.rb +27 -22
- data/lib/active_support/cache/mem_cache_store.rb +2 -2
- data/lib/active_support/cache/memory_store.rb +1 -0
- data/lib/active_support/cache/strategy/local_cache.rb +3 -0
- data/lib/active_support/callbacks.rb +416 -245
- data/lib/active_support/concern.rb +13 -5
- data/lib/active_support/core_ext.rb +0 -1
- data/lib/active_support/core_ext/array.rb +0 -1
- data/lib/active_support/core_ext/array/access.rb +2 -0
- data/lib/active_support/core_ext/array/conversions.rb +2 -17
- data/lib/active_support/core_ext/array/grouping.rb +24 -12
- data/lib/active_support/core_ext/array/prepend_and_append.rb +2 -2
- data/lib/active_support/core_ext/class.rb +0 -1
- data/lib/active_support/core_ext/class/attribute.rb +1 -2
- data/lib/active_support/core_ext/class/attribute_accessors.rb +5 -169
- data/lib/active_support/core_ext/date/calculations.rb +10 -0
- data/lib/active_support/core_ext/date/conversions.rb +5 -6
- data/lib/active_support/core_ext/date/zones.rb +2 -33
- data/lib/active_support/core_ext/date_and_time/calculations.rb +30 -11
- data/lib/active_support/core_ext/date_and_time/zones.rb +41 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +12 -25
- data/lib/active_support/core_ext/date_time/conversions.rb +2 -0
- data/lib/active_support/core_ext/date_time/zones.rb +3 -21
- data/lib/active_support/core_ext/hash.rb +0 -1
- data/lib/active_support/core_ext/hash/conversions.rb +6 -3
- data/lib/active_support/core_ext/hash/deep_merge.rb +11 -22
- data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -0
- data/lib/active_support/core_ext/hash/keys.rb +27 -47
- data/lib/active_support/core_ext/kernel/reporting.rb +2 -6
- data/lib/active_support/core_ext/module.rb +1 -0
- 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 +14 -4
- 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 +11 -0
- data/lib/active_support/core_ext/numeric/time.rb +8 -0
- data/lib/active_support/core_ext/object.rb +1 -1
- data/lib/active_support/core_ext/object/blank.rb +1 -1
- data/lib/active_support/core_ext/object/deep_dup.rb +6 -6
- data/lib/active_support/core_ext/object/inclusion.rb +4 -15
- data/lib/active_support/core_ext/object/json.rb +197 -0
- data/lib/active_support/core_ext/object/to_json.rb +4 -26
- data/lib/active_support/core_ext/object/to_param.rb +58 -1
- data/lib/active_support/core_ext/object/to_query.rb +7 -56
- data/lib/active_support/core_ext/object/try.rb +1 -1
- data/lib/active_support/core_ext/range/each.rb +2 -1
- data/lib/active_support/core_ext/string/access.rb +31 -31
- data/lib/active_support/core_ext/string/conversions.rb +9 -8
- data/lib/active_support/core_ext/string/exclude.rb +3 -3
- data/lib/active_support/core_ext/string/filters.rb +14 -4
- data/lib/active_support/core_ext/string/inflections.rb +11 -9
- data/lib/active_support/core_ext/string/output_safety.rb +65 -24
- data/lib/active_support/core_ext/string/zones.rb +1 -0
- data/lib/active_support/core_ext/thread.rb +4 -4
- data/lib/active_support/core_ext/time/calculations.rb +10 -57
- data/lib/active_support/core_ext/time/conversions.rb +3 -1
- data/lib/active_support/core_ext/time/zones.rb +2 -21
- data/lib/active_support/dependencies.rb +29 -13
- data/lib/active_support/deprecation.rb +4 -4
- data/lib/active_support/deprecation/behaviors.rb +3 -3
- data/lib/active_support/duration.rb +5 -7
- data/lib/active_support/file_update_checker.rb +1 -1
- data/lib/active_support/hash_with_indifferent_access.rb +4 -9
- data/lib/active_support/i18n.rb +4 -4
- data/lib/active_support/i18n_railtie.rb +2 -6
- data/lib/active_support/inflections.rb +0 -1
- data/lib/active_support/inflector/inflections.rb +17 -17
- data/lib/active_support/inflector/methods.rb +34 -17
- data/lib/active_support/json/decoding.rb +14 -21
- data/lib/active_support/json/encoding.rb +113 -285
- data/lib/active_support/key_generator.rb +1 -1
- 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 +1 -1
- data/lib/active_support/message_encryptor.rb +3 -3
- data/lib/active_support/message_verifier.rb +6 -1
- data/lib/active_support/multibyte/chars.rb +1 -2
- data/lib/active_support/multibyte/unicode.rb +27 -39
- data/lib/active_support/notifications.rb +3 -3
- data/lib/active_support/notifications/instrumenter.rb +2 -1
- data/lib/active_support/number_helper.rb +20 -311
- 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 +21 -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 +62 -0
- data/lib/active_support/option_merger.rb +1 -1
- data/lib/active_support/ordered_hash.rb +0 -8
- data/lib/active_support/ordered_options.rb +8 -0
- data/lib/active_support/per_thread_registry.rb +9 -8
- data/lib/active_support/subscriber.rb +26 -3
- data/lib/active_support/test_case.rb +9 -10
- data/lib/active_support/testing/assertions.rb +0 -30
- data/lib/active_support/testing/autorun.rb +2 -2
- data/lib/active_support/testing/declarative.rb +18 -8
- data/lib/active_support/testing/isolation.rb +13 -65
- data/lib/active_support/testing/setup_and_teardown.rb +17 -2
- data/lib/active_support/testing/tagged_logging.rb +1 -1
- data/lib/active_support/testing/time_helpers.rb +55 -0
- data/lib/active_support/time_with_zone.rb +4 -4
- data/lib/active_support/values/time_zone.rb +18 -15
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/xml_mini.rb +2 -4
- metadata +71 -61
- 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/proc.rb +0 -17
- data/lib/active_support/core_ext/string/encoding.rb +0 -8
- data/lib/active_support/json/variable.rb +0 -18
- data/lib/active_support/testing/pending.rb +0 -14
@@ -16,7 +16,8 @@ class Time
|
|
16
16
|
:rfc822 => lambda { |time|
|
17
17
|
offset_format = time.formatted_offset(false)
|
18
18
|
time.strftime("%a, %d %b %Y %H:%M:%S #{offset_format}")
|
19
|
-
}
|
19
|
+
},
|
20
|
+
:iso8601 => lambda { |time| time.iso8601 }
|
20
21
|
}
|
21
22
|
|
22
23
|
# Converts to a formatted string. See DATE_FORMATS for builtin formats.
|
@@ -34,6 +35,7 @@ class Time
|
|
34
35
|
# time.to_formatted_s(:long) # => "January 18, 2007 06:10"
|
35
36
|
# time.to_formatted_s(:long_ordinal) # => "January 18th, 2007 06:10"
|
36
37
|
# time.to_formatted_s(:rfc822) # => "Thu, 18 Jan 2007 06:10:17 -0600"
|
38
|
+
# time.to_formatted_s(:iso8601) # => "2007-01-18T06:10:17-06:00"
|
37
39
|
#
|
38
40
|
# == Adding your own time formats to +to_formatted_s+
|
39
41
|
# You can add your own formats to the Time::DATE_FORMATS hash.
|
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'active_support/time_with_zone'
|
2
|
-
require 'active_support/core_ext/
|
2
|
+
require 'active_support/core_ext/date_and_time/zones'
|
3
3
|
|
4
4
|
class Time
|
5
|
+
include DateAndTime::Zones
|
5
6
|
class << self
|
6
7
|
attr_accessor :zone_default
|
7
8
|
|
@@ -74,24 +75,4 @@ class Time
|
|
74
75
|
find_zone!(time_zone) rescue nil
|
75
76
|
end
|
76
77
|
end
|
77
|
-
|
78
|
-
# Returns the simultaneous time in <tt>Time.zone</tt>.
|
79
|
-
#
|
80
|
-
# Time.zone = 'Hawaii' # => 'Hawaii'
|
81
|
-
# Time.utc(2000).in_time_zone # => Fri, 31 Dec 1999 14:00:00 HST -10:00
|
82
|
-
#
|
83
|
-
# This method is similar to Time#localtime, except that it uses <tt>Time.zone</tt> as the local zone
|
84
|
-
# instead of the operating system's time zone.
|
85
|
-
#
|
86
|
-
# You can also pass in a TimeZone instance or string that identifies a TimeZone as an argument,
|
87
|
-
# and the conversion will be based on that zone instead of <tt>Time.zone</tt>.
|
88
|
-
#
|
89
|
-
# Time.utc(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00
|
90
|
-
def in_time_zone(zone = ::Time.zone)
|
91
|
-
if zone
|
92
|
-
ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.find_zone!(zone))
|
93
|
-
else
|
94
|
-
self
|
95
|
-
end
|
96
|
-
end
|
97
78
|
end
|
@@ -176,14 +176,22 @@ module ActiveSupport #:nodoc:
|
|
176
176
|
end
|
177
177
|
|
178
178
|
def const_missing(const_name)
|
179
|
-
|
180
|
-
# case of anonymous modules we cannot even make the trade-off of
|
181
|
-
# assuming their name reflects the nesting. Resort to Object as
|
182
|
-
# the only meaningful guess we can make.
|
183
|
-
from_mod = anonymous? ? ::Object : self
|
179
|
+
from_mod = anonymous? ? guess_for_anonymous(const_name) : self
|
184
180
|
Dependencies.load_missing_constant(from_mod, const_name)
|
185
181
|
end
|
186
182
|
|
183
|
+
# Dependencies assumes the name of the module reflects the nesting (unless
|
184
|
+
# it can be proven that is not the case), and the path to the file that
|
185
|
+
# defines the constant. Anonymous modules cannot follow these conventions
|
186
|
+
# and we assume therefore the user wants to refer to a top-level constant.
|
187
|
+
def guess_for_anonymous(const_name)
|
188
|
+
if Object.const_defined?(const_name)
|
189
|
+
raise NameError, "#{const_name} cannot be autoloaded from an anonymous class or module"
|
190
|
+
else
|
191
|
+
Object
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
187
195
|
def unloadable(const_desc = self)
|
188
196
|
super(const_desc)
|
189
197
|
end
|
@@ -199,9 +207,19 @@ module ActiveSupport #:nodoc:
|
|
199
207
|
Dependencies.require_or_load(file_name)
|
200
208
|
end
|
201
209
|
|
210
|
+
# Interprets a file using <tt>mechanism</tt> and marks its defined
|
211
|
+
# constants as autoloaded. <tt>file_name</tt> can be either a string or
|
212
|
+
# respond to <tt>to_path</tt>.
|
213
|
+
#
|
214
|
+
# Use this method in code that absolutely needs a certain constant to be
|
215
|
+
# defined at that point. A typical use case is to make constant name
|
216
|
+
# resolution deterministic for constants with the same relative name in
|
217
|
+
# different namespaces whose evaluation would depend on load order
|
218
|
+
# otherwise.
|
202
219
|
def require_dependency(file_name, message = "No such file to load -- %s")
|
220
|
+
file_name = file_name.to_path if file_name.respond_to?(:to_path)
|
203
221
|
unless file_name.is_a?(String)
|
204
|
-
raise ArgumentError, "the file name must be a String -- you passed #{file_name.inspect}"
|
222
|
+
raise ArgumentError, "the file name must either be a String or implement #to_path -- you passed #{file_name.inspect}"
|
205
223
|
end
|
206
224
|
|
207
225
|
Dependencies.depend_on(file_name, message)
|
@@ -417,7 +435,7 @@ module ActiveSupport #:nodoc:
|
|
417
435
|
def load_file(path, const_paths = loadable_constants_for_path(path))
|
418
436
|
log_call path, const_paths
|
419
437
|
const_paths = [const_paths].compact unless const_paths.is_a? Array
|
420
|
-
parent_paths = const_paths.collect { |const_path| const_path[/.*(?=::)/] ||
|
438
|
+
parent_paths = const_paths.collect { |const_path| const_path[/.*(?=::)/] || ::Object }
|
421
439
|
|
422
440
|
result = nil
|
423
441
|
newly_defined_paths = new_constants_in(*parent_paths) do
|
@@ -446,8 +464,6 @@ module ActiveSupport #:nodoc:
|
|
446
464
|
raise ArgumentError, "A copy of #{from_mod} has been removed from the module tree but is still active!"
|
447
465
|
end
|
448
466
|
|
449
|
-
raise NameError.new("#{from_mod} is not missing constant #{const_name}!", const_name) if from_mod.const_defined?(const_name, false)
|
450
|
-
|
451
467
|
qualified_name = qualified_name_for from_mod, const_name
|
452
468
|
path_suffix = qualified_name.underscore
|
453
469
|
|
@@ -498,9 +514,9 @@ module ActiveSupport #:nodoc:
|
|
498
514
|
end
|
499
515
|
end
|
500
516
|
|
501
|
-
|
502
|
-
|
503
|
-
|
517
|
+
raise NameError,
|
518
|
+
"uninitialized constant #{qualified_name}",
|
519
|
+
caller.reject { |l| l.starts_with? __FILE__ }
|
504
520
|
end
|
505
521
|
|
506
522
|
# Remove the constants that have been autoloaded, and those that have been
|
@@ -635,7 +651,7 @@ module ActiveSupport #:nodoc:
|
|
635
651
|
when String then desc.sub(/^::/, '')
|
636
652
|
when Symbol then desc.to_s
|
637
653
|
when Module
|
638
|
-
desc.name
|
654
|
+
desc.name ||
|
639
655
|
raise(ArgumentError, "Anonymous modules have no name to be referenced by")
|
640
656
|
else raise TypeError, "Not a valid constant descriptor: #{desc.inspect}"
|
641
657
|
end
|
@@ -25,14 +25,14 @@ module ActiveSupport
|
|
25
25
|
include Reporting
|
26
26
|
include MethodWrapper
|
27
27
|
|
28
|
-
# The version the deprecated behavior will be removed, by default.
|
28
|
+
# The version number in which the deprecated behavior will be removed, by default.
|
29
29
|
attr_accessor :deprecation_horizon
|
30
30
|
|
31
|
-
# It accepts two parameters on initialization. The first is
|
32
|
-
# and the second is
|
31
|
+
# It accepts two parameters on initialization. The first is a version of library
|
32
|
+
# and the second is a library name
|
33
33
|
#
|
34
34
|
# ActiveSupport::Deprecation.new('2.0', 'MyLibrary')
|
35
|
-
def initialize(deprecation_horizon = '4.
|
35
|
+
def initialize(deprecation_horizon = '4.2', gem_name = 'Rails')
|
36
36
|
self.gem_name = gem_name
|
37
37
|
self.deprecation_horizon = deprecation_horizon
|
38
38
|
# By default, warnings are not silenced and debugging is off.
|
@@ -17,7 +17,7 @@ module ActiveSupport
|
|
17
17
|
$stderr.puts(message)
|
18
18
|
$stderr.puts callstack.join("\n ") if debug
|
19
19
|
},
|
20
|
-
|
20
|
+
|
21
21
|
log: ->(message, callstack) {
|
22
22
|
logger =
|
23
23
|
if defined?(Rails) && Rails.logger
|
@@ -29,12 +29,12 @@ module ActiveSupport
|
|
29
29
|
logger.warn message
|
30
30
|
logger.debug callstack.join("\n ") if debug
|
31
31
|
},
|
32
|
-
|
32
|
+
|
33
33
|
notify: ->(message, callstack) {
|
34
34
|
ActiveSupport::Notifications.instrument("deprecation.rails",
|
35
35
|
:message => message, :callstack => callstack)
|
36
36
|
},
|
37
|
-
|
37
|
+
|
38
38
|
silence: ->(message, callstack) {},
|
39
39
|
}
|
40
40
|
|
@@ -70,13 +70,11 @@ module ActiveSupport
|
|
70
70
|
alias :until :ago
|
71
71
|
|
72
72
|
def inspect #:nodoc:
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
"#{
|
77
|
-
|
78
|
-
parts = ["0 seconds"] if parts.empty?
|
79
|
-
parts.to_sentence(:locale => :en)
|
73
|
+
parts.
|
74
|
+
reduce(::Hash.new(0)) { |h,(l,r)| h[l] += r; h }.
|
75
|
+
sort_by {|unit, _ | [:years, :months, :days, :minutes, :seconds].index(unit)}.
|
76
|
+
map {|unit, val| "#{val} #{val == 1 ? unit.to_s.chop : unit.to_s}"}.
|
77
|
+
to_sentence(:locale => :en)
|
80
78
|
end
|
81
79
|
|
82
80
|
def as_json(options = nil) #:nodoc:
|
@@ -72,7 +72,6 @@ module ActiveSupport
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def self.new_from_hash_copying_default(hash)
|
75
|
-
hash = hash.to_hash
|
76
75
|
new(hash).tap do |new_hash|
|
77
76
|
new_hash.default = hash.default
|
78
77
|
end
|
@@ -126,7 +125,7 @@ module ActiveSupport
|
|
126
125
|
if other_hash.is_a? HashWithIndifferentAccess
|
127
126
|
super(other_hash)
|
128
127
|
else
|
129
|
-
other_hash.
|
128
|
+
other_hash.each_pair do |key, value|
|
130
129
|
if block_given? && key?(key)
|
131
130
|
value = yield(convert_key(key), self[key], value)
|
132
131
|
end
|
@@ -208,7 +207,7 @@ module ActiveSupport
|
|
208
207
|
# Replaces the contents of this hash with other_hash.
|
209
208
|
#
|
210
209
|
# h = { "a" => 100, "b" => 200 }
|
211
|
-
# h.replace({ "c" => 300, "d" => 400 })
|
210
|
+
# h.replace({ "c" => 300, "d" => 400 }) # => {"c"=>300, "d"=>400}
|
212
211
|
def replace(other_hash)
|
213
212
|
super(self.class.new_from_hash_copying_default(other_hash))
|
214
213
|
end
|
@@ -225,15 +224,11 @@ module ActiveSupport
|
|
225
224
|
undef :symbolize_keys!
|
226
225
|
undef :deep_symbolize_keys!
|
227
226
|
def symbolize_keys; to_hash.symbolize_keys! end
|
228
|
-
def deep_symbolize_keys; to_hash.deep_symbolize_keys end
|
227
|
+
def deep_symbolize_keys; to_hash.deep_symbolize_keys! end
|
229
228
|
def to_options!; self end
|
230
229
|
|
231
230
|
def select(*args, &block)
|
232
|
-
dup.tap {
|
233
|
-
end
|
234
|
-
|
235
|
-
def reject(*args, &block)
|
236
|
-
dup.tap { |hash| hash.reject!(*args, &block) }
|
231
|
+
dup.tap {|hash| hash.select!(*args, &block)}
|
237
232
|
end
|
238
233
|
|
239
234
|
# Convert to a regular hash with string keys.
|
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"
|
@@ -36,11 +36,7 @@ module I18n
|
|
36
36
|
# Avoid issues with setting the default_locale by disabling available locales
|
37
37
|
# check while configuring.
|
38
38
|
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
|
-
|
39
|
+
enforce_available_locales = I18n.enforce_available_locales unless I18n.enforce_available_locales.nil?
|
44
40
|
I18n.enforce_available_locales = false
|
45
41
|
|
46
42
|
app.config.i18n.each do |setting, value|
|
@@ -56,7 +52,7 @@ module I18n
|
|
56
52
|
|
57
53
|
init_fallbacks(fallbacks) if fallbacks && validate_fallbacks(fallbacks)
|
58
54
|
|
59
|
-
# Restore
|
55
|
+
# Restore avalable locales check so it will take place from now on.
|
60
56
|
I18n.enforce_available_locales = enforce_available_locales
|
61
57
|
|
62
58
|
reloader = ActiveSupport::FileUpdateChecker.new(I18n.load_path.dup){ I18n.reload! }
|
@@ -57,7 +57,6 @@ module ActiveSupport
|
|
57
57
|
inflect.irregular('child', 'children')
|
58
58
|
inflect.irregular('sex', 'sexes')
|
59
59
|
inflect.irregular('move', 'moves')
|
60
|
-
inflect.irregular('cow', 'kine')
|
61
60
|
inflect.irregular('zombie', 'zombies')
|
62
61
|
|
63
62
|
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("|")}/
|
@@ -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,8 +89,7 @@ module ActiveSupport
|
|
88
89
|
#
|
89
90
|
# 'SSLError'.underscore.camelize # => "SslError"
|
90
91
|
def underscore(camel_cased_word)
|
91
|
-
word = camel_cased_word.to_s.
|
92
|
-
word.gsub!('::', '/')
|
92
|
+
word = camel_cased_word.to_s.gsub('::', '/')
|
93
93
|
word.gsub!(/(?:([A-Za-z\d])|^)(#{inflections.acronym_regex})(?=\b|[^a-z])/) { "#{$1}#{$1 && '_'}#{$2.downcase}" }
|
94
94
|
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
|
95
95
|
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
@@ -98,20 +98,27 @@ module ActiveSupport
|
|
98
98
|
word
|
99
99
|
end
|
100
100
|
|
101
|
-
# Capitalizes the first word
|
102
|
-
# trailing
|
103
|
-
# output.
|
104
|
-
#
|
105
|
-
#
|
106
|
-
#
|
107
|
-
|
101
|
+
# Capitalizes the first word, turns underscores into spaces, and strips a
|
102
|
+
# trailing '_id' if present.
|
103
|
+
# Like +titleize+, this is meant for creating pretty output.
|
104
|
+
#
|
105
|
+
# The capitalization of the first word can be turned off by setting the
|
106
|
+
# optional parameter +capitalize+ to false.
|
107
|
+
# By default, this parameter is true.
|
108
|
+
#
|
109
|
+
# humanize('employee_salary') # => "Employee salary"
|
110
|
+
# humanize('author_id') # => "Author"
|
111
|
+
# humanize('author_id', capitalize: false) # => "author"
|
112
|
+
def humanize(lower_case_and_underscored_word, options = {})
|
108
113
|
result = lower_case_and_underscored_word.to_s.dup
|
109
114
|
inflections.humans.each { |(rule, replacement)| break if result.sub!(rule, replacement) }
|
110
115
|
result.gsub!(/_id$/, "")
|
111
116
|
result.tr!('_', ' ')
|
112
|
-
result.gsub(/([a-z\d]*)/i) { |match|
|
117
|
+
result.gsub!(/([a-z\d]*)/i) { |match|
|
113
118
|
"#{inflections.acronyms[match] || match.downcase}"
|
114
|
-
}
|
119
|
+
}
|
120
|
+
result.gsub!(/^\w/) { $&.upcase } if options.fetch(:capitalize, true)
|
121
|
+
result
|
115
122
|
end
|
116
123
|
|
117
124
|
# Capitalizes all the words and replaces some characters in the string to
|
@@ -185,7 +192,7 @@ module ActiveSupport
|
|
185
192
|
#
|
186
193
|
# See also +demodulize+.
|
187
194
|
def deconstantize(path)
|
188
|
-
path.to_s[0
|
195
|
+
path.to_s[0, path.rindex('::') || 0] # implementation based on the one in facets' Module#spacename
|
189
196
|
end
|
190
197
|
|
191
198
|
# Creates a foreign key name from a class name.
|
@@ -219,7 +226,12 @@ module ActiveSupport
|
|
219
226
|
# unknown.
|
220
227
|
def constantize(camel_cased_word)
|
221
228
|
names = camel_cased_word.split('::')
|
222
|
-
|
229
|
+
|
230
|
+
# Trigger a builtin NameError exception including the ill-formed constant in the message.
|
231
|
+
Object.const_get(camel_cased_word) if names.empty?
|
232
|
+
|
233
|
+
# Remove the first blank element in case of '::ClassName' notation.
|
234
|
+
names.shift if names.size > 1 && names.first.empty?
|
223
235
|
|
224
236
|
names.inject(Object) do |constant, name|
|
225
237
|
if constant == Object
|
@@ -314,9 +326,14 @@ module ActiveSupport
|
|
314
326
|
private
|
315
327
|
|
316
328
|
# Mount a regular expression that will match part by part of the constant.
|
317
|
-
#
|
329
|
+
#
|
330
|
+
# const_regexp("Foo::Bar::Baz") # => /Foo(::Bar(::Baz)?)?/
|
331
|
+
# const_regexp("::") # => /::/
|
318
332
|
def const_regexp(camel_cased_word) #:nodoc:
|
319
333
|
parts = camel_cased_word.split("::")
|
334
|
+
|
335
|
+
return Regexp.escape(camel_cased_word) if parts.blank?
|
336
|
+
|
320
337
|
last = parts.pop
|
321
338
|
|
322
339
|
parts.reverse.inject(last) do |acc, part|
|