activesupport 3.1.12 → 3.2.0.rc1
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.md +1539 -30
- data/README.rdoc +2 -2
- data/lib/active_support.rb +1 -1
- data/lib/active_support/benchmarkable.rb +13 -18
- data/lib/active_support/buffered_logger.rb +43 -55
- data/lib/active_support/cache.rb +109 -115
- data/lib/active_support/cache/file_store.rb +6 -17
- data/lib/active_support/cache/mem_cache_store.rb +10 -2
- data/lib/active_support/cache/null_store.rb +44 -0
- data/lib/active_support/cache/strategy/local_cache.rb +2 -2
- data/lib/active_support/callbacks.rb +38 -35
- data/lib/active_support/concern.rb +5 -10
- data/lib/active_support/core_ext/array.rb +1 -0
- data/lib/active_support/core_ext/array/access.rb +1 -1
- data/lib/active_support/core_ext/array/prepend_and_append.rb +7 -0
- data/lib/active_support/core_ext/array/wrap.rb +1 -1
- data/lib/active_support/core_ext/class.rb +0 -1
- data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -2
- data/lib/active_support/core_ext/date/calculations.rb +37 -14
- data/lib/active_support/core_ext/date/freeze.rb +6 -4
- data/lib/active_support/core_ext/date_time/calculations.rb +1 -1
- data/lib/active_support/core_ext/enumerable.rb +25 -8
- data/lib/active_support/core_ext/file/atomic.rb +1 -2
- data/lib/active_support/core_ext/hash/conversions.rb +7 -25
- data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -1
- data/lib/active_support/core_ext/io.rb +15 -0
- data/lib/active_support/core_ext/kernel.rb +0 -1
- data/lib/active_support/core_ext/kernel/agnostics.rb +2 -2
- data/lib/active_support/core_ext/kernel/debugger.rb +1 -7
- data/lib/active_support/core_ext/module.rb +2 -2
- data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -2
- data/lib/active_support/core_ext/module/delegation.rb +32 -21
- data/lib/active_support/core_ext/module/qualified_const.rb +64 -0
- data/lib/active_support/core_ext/module/reachable.rb +1 -3
- data/lib/active_support/core_ext/module/synchronization.rb +2 -0
- data/lib/active_support/core_ext/object/blank.rb +14 -2
- data/lib/active_support/core_ext/object/inclusion.rb +17 -7
- data/lib/active_support/core_ext/object/to_json.rb +2 -2
- data/lib/active_support/core_ext/range/conversions.rb +1 -1
- data/lib/active_support/core_ext/string/conversions.rb +2 -2
- data/lib/active_support/core_ext/string/inflections.rb +44 -6
- data/lib/active_support/core_ext/string/multibyte.rb +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +22 -25
- data/lib/active_support/core_ext/time/calculations.rb +66 -12
- data/lib/active_support/dependencies.rb +51 -52
- data/lib/active_support/file_update_checker.rb +100 -15
- data/lib/active_support/hash_with_indifferent_access.rb +5 -1
- data/lib/active_support/i18n.rb +1 -1
- data/lib/active_support/i18n_railtie.rb +9 -4
- data/lib/active_support/inflections.rb +3 -3
- data/lib/active_support/inflector/inflections.rb +53 -92
- data/lib/active_support/inflector/methods.rb +173 -9
- data/lib/active_support/json/decoding.rb +3 -17
- data/lib/active_support/json/encoding.rb +11 -14
- data/lib/active_support/memoizable.rb +12 -1
- data/lib/active_support/message_encryptor.rb +52 -20
- data/lib/active_support/message_verifier.rb +15 -4
- data/lib/active_support/notifications.rb +87 -14
- data/lib/active_support/notifications/instrumenter.rb +1 -2
- data/lib/active_support/ordered_hash.rb +7 -3
- data/lib/active_support/tagged_logging.rb +63 -0
- data/lib/active_support/testing/assertions.rb +1 -1
- data/lib/active_support/testing/mochaing.rb +2 -2
- data/lib/active_support/testing/performance/ruby.rb +1 -1
- data/lib/active_support/testing/setup_and_teardown.rb +4 -12
- data/lib/active_support/time_with_zone.rb +6 -3
- data/lib/active_support/values/time_zone.rb +3 -7
- data/lib/active_support/version.rb +3 -3
- data/lib/active_support/xml_mini.rb +3 -3
- data/lib/active_support/xml_mini/jdom.rb +4 -10
- metadata +28 -21
- checksums.yaml +0 -7
- data/lib/active_support/cache/compressed_mem_cache_store.rb +0 -13
- data/lib/active_support/cache/synchronized_memory_store.rb +0 -11
- data/lib/active_support/core_ext/class/inheritable_attributes.rb +0 -178
- data/lib/active_support/core_ext/kernel/requires.rb +0 -28
- data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +0 -31
- data/lib/active_support/secure_random.rb +0 -6
@@ -1,3 +1,6 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'active_support/core_ext/string/encoding'
|
3
|
+
|
1
4
|
class Object
|
2
5
|
# An object is blank if it's false, empty, or a whitespace string.
|
3
6
|
# For example, "", " ", +nil+, [], and {} are all blank.
|
@@ -22,7 +25,7 @@ class Object
|
|
22
25
|
# <tt>object.presence</tt> is equivalent to <tt>object.present? ? object : nil</tt>.
|
23
26
|
#
|
24
27
|
# This is handy for any representation of objects where blank is the same
|
25
|
-
# as not present at all.
|
28
|
+
# as not present at all. For example, this simplifies a common check for
|
26
29
|
# HTTP POST/query parameters:
|
27
30
|
#
|
28
31
|
# state = params[:state] if params[:state].present?
|
@@ -86,14 +89,23 @@ class Hash
|
|
86
89
|
end
|
87
90
|
|
88
91
|
class String
|
92
|
+
# 0x3000: fullwidth whitespace
|
93
|
+
NON_WHITESPACE_REGEXP = %r![^\s#{[0x3000].pack("U")}]!
|
94
|
+
|
89
95
|
# A string is blank if it's empty or contains whitespaces only:
|
90
96
|
#
|
91
97
|
# "".blank? # => true
|
92
98
|
# " ".blank? # => true
|
99
|
+
# " ".blank? # => true
|
93
100
|
# " something here ".blank? # => false
|
94
101
|
#
|
95
102
|
def blank?
|
96
|
-
|
103
|
+
# 1.8 does not takes [:space:] properly
|
104
|
+
if encoding_aware?
|
105
|
+
self !~ /[^[:space:]]/
|
106
|
+
else
|
107
|
+
self !~ NON_WHITESPACE_REGEXP
|
108
|
+
end
|
97
109
|
end
|
98
110
|
end
|
99
111
|
|
@@ -1,15 +1,25 @@
|
|
1
1
|
class Object
|
2
|
-
# Returns true if this object is included in the argument. Argument must be
|
3
|
-
# any object which responds to +#include
|
2
|
+
# Returns true if this object is included in the argument(s). Argument must be
|
3
|
+
# any object which responds to +#include?+ or optionally, multiple arguments can be passed in. Usage:
|
4
4
|
#
|
5
5
|
# characters = ["Konata", "Kagami", "Tsukasa"]
|
6
6
|
# "Konata".in?(characters) # => true
|
7
|
+
#
|
8
|
+
# character = "Konata"
|
9
|
+
# character.in?("Konata", "Kagami", "Tsukasa") # => true
|
7
10
|
#
|
8
|
-
# This will throw an ArgumentError if
|
11
|
+
# This will throw an ArgumentError if a single argument is passed in and it doesn't respond
|
9
12
|
# to +#include?+.
|
10
|
-
def in?(
|
11
|
-
|
12
|
-
|
13
|
-
|
13
|
+
def in?(*args)
|
14
|
+
if args.length > 1
|
15
|
+
args.include? self
|
16
|
+
else
|
17
|
+
another_object = args.first
|
18
|
+
if another_object.respond_to? :include?
|
19
|
+
another_object.include? self
|
20
|
+
else
|
21
|
+
raise ArgumentError.new("The single parameter passed to #in? must respond to #include?")
|
22
|
+
end
|
23
|
+
end
|
14
24
|
end
|
15
25
|
end
|
@@ -10,10 +10,10 @@ end
|
|
10
10
|
# several cases (for instance, the JSON implementation for Hash does not work) with inheritance
|
11
11
|
# and consequently classes as ActiveSupport::OrderedHash cannot be serialized to json.
|
12
12
|
[Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass].each do |klass|
|
13
|
-
klass.class_eval
|
13
|
+
klass.class_eval do
|
14
14
|
# Dumps object in JSON (JavaScript Object Notation). See www.json.org for more info.
|
15
15
|
def to_json(options = nil)
|
16
16
|
ActiveSupport::JSON.encode(self, options)
|
17
17
|
end
|
18
|
-
|
18
|
+
end
|
19
19
|
end
|
@@ -35,9 +35,9 @@ class String
|
|
35
35
|
# Form can be either :utc (default) or :local.
|
36
36
|
def to_time(form = :utc)
|
37
37
|
return nil if self.blank?
|
38
|
-
d = ::Date._parse(self, false).values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction).map { |arg| arg || 0 }
|
38
|
+
d = ::Date._parse(self, false).values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset).map { |arg| arg || 0 }
|
39
39
|
d[6] *= 1000000
|
40
|
-
::Time.send("#{form}_time", *d)
|
40
|
+
::Time.send("#{form}_time", *d[0..6]) - d[7]
|
41
41
|
end
|
42
42
|
|
43
43
|
def to_date
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'active_support/inflector/methods'
|
2
|
-
require 'active_support/inflector/inflections'
|
3
2
|
require 'active_support/inflector/transliterate'
|
4
3
|
|
5
4
|
# String inflections define new methods on the String class to transform names for different purposes.
|
@@ -10,14 +9,25 @@ require 'active_support/inflector/transliterate'
|
|
10
9
|
class String
|
11
10
|
# Returns the plural form of the word in the string.
|
12
11
|
#
|
12
|
+
# If the optional parameter +count+ is specified,
|
13
|
+
# the singular form will be returned if <tt>count == 1</tt>.
|
14
|
+
# For any other value of +count+ the plural will be returned.
|
15
|
+
#
|
16
|
+
# ==== Examples
|
13
17
|
# "post".pluralize # => "posts"
|
14
18
|
# "octopus".pluralize # => "octopi"
|
15
19
|
# "sheep".pluralize # => "sheep"
|
16
20
|
# "words".pluralize # => "words"
|
17
21
|
# "the blue mailman".pluralize # => "the blue mailmen"
|
18
22
|
# "CamelOctopus".pluralize # => "CamelOctopi"
|
19
|
-
|
20
|
-
|
23
|
+
# "apple".pluralize(1) # => "apple"
|
24
|
+
# "apple".pluralize(2) # => "apples"
|
25
|
+
def pluralize(count = nil)
|
26
|
+
if count == 1
|
27
|
+
self
|
28
|
+
else
|
29
|
+
ActiveSupport::Inflector.pluralize(self)
|
30
|
+
end
|
21
31
|
end
|
22
32
|
|
23
33
|
# The reverse of +pluralize+, returns the singular form of a word in a string.
|
@@ -34,15 +44,28 @@ class String
|
|
34
44
|
|
35
45
|
# +constantize+ tries to find a declared constant with the name specified
|
36
46
|
# in the string. It raises a NameError when the name is not in CamelCase
|
37
|
-
# or is not initialized.
|
47
|
+
# or is not initialized. See ActiveSupport::Inflector.constantize
|
38
48
|
#
|
39
49
|
# Examples
|
40
|
-
# "Module".constantize
|
41
|
-
# "Class".constantize
|
50
|
+
# "Module".constantize # => Module
|
51
|
+
# "Class".constantize # => Class
|
52
|
+
# "blargle".constantize # => NameError: wrong constant name blargle
|
42
53
|
def constantize
|
43
54
|
ActiveSupport::Inflector.constantize(self)
|
44
55
|
end
|
45
56
|
|
57
|
+
# +safe_constantize+ tries to find a declared constant with the name specified
|
58
|
+
# in the string. It returns nil when the name is not in CamelCase
|
59
|
+
# or is not initialized. See ActiveSupport::Inflector.safe_constantize
|
60
|
+
#
|
61
|
+
# Examples
|
62
|
+
# "Module".safe_constantize # => Module
|
63
|
+
# "Class".safe_constantize # => Class
|
64
|
+
# "blargle".safe_constantize # => nil
|
65
|
+
def safe_constantize
|
66
|
+
ActiveSupport::Inflector.safe_constantize(self)
|
67
|
+
end
|
68
|
+
|
46
69
|
# By default, +camelize+ converts strings to UpperCamelCase. If the argument to camelize
|
47
70
|
# is set to <tt>:lower</tt> then camelize produces lowerCamelCase.
|
48
71
|
#
|
@@ -94,10 +117,25 @@ class String
|
|
94
117
|
#
|
95
118
|
# "ActiveRecord::CoreExtensions::String::Inflections".demodulize # => "Inflections"
|
96
119
|
# "Inflections".demodulize # => "Inflections"
|
120
|
+
#
|
121
|
+
# See also +deconstantize+.
|
97
122
|
def demodulize
|
98
123
|
ActiveSupport::Inflector.demodulize(self)
|
99
124
|
end
|
100
125
|
|
126
|
+
# Removes the rightmost segment from the constant expression in the string.
|
127
|
+
#
|
128
|
+
# "Net::HTTP".deconstantize # => "Net"
|
129
|
+
# "::Net::HTTP".deconstantize # => "::Net"
|
130
|
+
# "String".deconstantize # => ""
|
131
|
+
# "::String".deconstantize # => ""
|
132
|
+
# "".deconstantize # => ""
|
133
|
+
#
|
134
|
+
# See also +demodulize+.
|
135
|
+
def deconstantize
|
136
|
+
ActiveSupport::Inflector.deconstantize(self)
|
137
|
+
end
|
138
|
+
|
101
139
|
# Replaces special characters in a string so that it may be used as part of a 'pretty' URL.
|
102
140
|
#
|
103
141
|
# ==== Examples
|
@@ -3,10 +3,11 @@ require 'active_support/core_ext/kernel/singleton_class'
|
|
3
3
|
|
4
4
|
class ERB
|
5
5
|
module Util
|
6
|
-
HTML_ESCAPE = { '&' => '&', '>' => '>', '<' => '<', '"' => '"'
|
6
|
+
HTML_ESCAPE = { '&' => '&', '>' => '>', '<' => '<', '"' => '"' }
|
7
7
|
JSON_ESCAPE = { '&' => '\u0026', '>' => '\u003E', '<' => '\u003C' }
|
8
8
|
|
9
|
-
|
9
|
+
# Detect whether 1.9 can transcode with XML escaping.
|
10
|
+
if '"><&""' == ('><&"'.encode('utf-8', :xml => :attr) rescue false)
|
10
11
|
# A utility method for escaping HTML tag characters.
|
11
12
|
# This method is also aliased as <tt>h</tt>.
|
12
13
|
#
|
@@ -21,7 +22,7 @@ class ERB
|
|
21
22
|
if s.html_safe?
|
22
23
|
s
|
23
24
|
else
|
24
|
-
s.
|
25
|
+
s.encode(s.encoding, :xml => :attr)[1...-1].html_safe
|
25
26
|
end
|
26
27
|
end
|
27
28
|
else
|
@@ -30,7 +31,7 @@ class ERB
|
|
30
31
|
if s.html_safe?
|
31
32
|
s
|
32
33
|
else
|
33
|
-
s.gsub(/[&"
|
34
|
+
s.gsub(/[&"><]/n) { |special| HTML_ESCAPE[special] }.html_safe
|
34
35
|
end
|
35
36
|
end
|
36
37
|
end
|
@@ -97,39 +98,29 @@ module ActiveSupport #:nodoc:
|
|
97
98
|
end
|
98
99
|
end
|
99
100
|
|
100
|
-
def
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
new_safe_buffer = super
|
105
|
-
new_safe_buffer.instance_eval { @html_safe = true }
|
106
|
-
new_safe_buffer
|
107
|
-
else
|
108
|
-
to_str[*args]
|
109
|
-
end
|
101
|
+
def[](*args)
|
102
|
+
new_safe_buffer = super
|
103
|
+
new_safe_buffer.instance_eval { @dirty = false }
|
104
|
+
new_safe_buffer
|
110
105
|
end
|
111
106
|
|
112
107
|
def safe_concat(value)
|
113
|
-
raise SafeConcatError
|
108
|
+
raise SafeConcatError if dirty?
|
114
109
|
original_concat(value)
|
115
110
|
end
|
116
111
|
|
117
112
|
def initialize(*)
|
118
|
-
@
|
113
|
+
@dirty = false
|
119
114
|
super
|
120
115
|
end
|
121
116
|
|
122
117
|
def initialize_copy(other)
|
123
118
|
super
|
124
|
-
@
|
125
|
-
end
|
126
|
-
|
127
|
-
def clone_empty
|
128
|
-
self[0, 0]
|
119
|
+
@dirty = other.dirty?
|
129
120
|
end
|
130
121
|
|
131
122
|
def concat(value)
|
132
|
-
if
|
123
|
+
if dirty? || value.html_safe?
|
133
124
|
super(value)
|
134
125
|
else
|
135
126
|
super(ERB::Util.h(value))
|
@@ -142,7 +133,7 @@ module ActiveSupport #:nodoc:
|
|
142
133
|
end
|
143
134
|
|
144
135
|
def html_safe?
|
145
|
-
|
136
|
+
!dirty?
|
146
137
|
end
|
147
138
|
|
148
139
|
def to_s
|
@@ -162,7 +153,7 @@ module ActiveSupport #:nodoc:
|
|
162
153
|
to_str.to_yaml(*args)
|
163
154
|
end
|
164
155
|
|
165
|
-
|
156
|
+
UNSAFE_STRING_METHODS.each do |unsafe_method|
|
166
157
|
if 'String'.respond_to?(unsafe_method)
|
167
158
|
class_eval <<-EOT, __FILE__, __LINE__ + 1
|
168
159
|
def #{unsafe_method}(*args, &block) # def capitalize(*args, &block)
|
@@ -170,12 +161,18 @@ module ActiveSupport #:nodoc:
|
|
170
161
|
end # end
|
171
162
|
|
172
163
|
def #{unsafe_method}!(*args) # def capitalize!(*args)
|
173
|
-
@
|
164
|
+
@dirty = true # @dirty = true
|
174
165
|
super # super
|
175
166
|
end # end
|
176
167
|
EOT
|
177
168
|
end
|
178
169
|
end
|
170
|
+
|
171
|
+
protected
|
172
|
+
|
173
|
+
def dirty?
|
174
|
+
@dirty
|
175
|
+
end
|
179
176
|
end
|
180
177
|
end
|
181
178
|
|
@@ -161,27 +161,46 @@ class Time
|
|
161
161
|
months_since(1)
|
162
162
|
end
|
163
163
|
|
164
|
-
# Returns
|
165
|
-
def
|
166
|
-
|
167
|
-
|
164
|
+
# Returns number of days to start of this week, week starts on start_day (default is :monday).
|
165
|
+
def days_to_week_start(start_day = :monday)
|
166
|
+
start_day_number = DAYS_INTO_WEEK[start_day]
|
167
|
+
current_day_number = wday != 0 ? wday - 1 : 6
|
168
|
+
days_span = current_day_number - start_day_number
|
169
|
+
days_span >= 0 ? days_span : 7 + days_span
|
170
|
+
end
|
171
|
+
|
172
|
+
# Returns a new Time representing the "start" of this week, week starts on start_day (default is :monday, i.e. Monday, 0:00).
|
173
|
+
def beginning_of_week(start_day = :monday)
|
174
|
+
days_to_start = days_to_week_start(start_day)
|
175
|
+
(self - days_to_start.days).midnight
|
168
176
|
end
|
169
|
-
alias :monday :beginning_of_week
|
170
177
|
alias :at_beginning_of_week :beginning_of_week
|
171
178
|
|
172
|
-
# Returns a new
|
173
|
-
|
174
|
-
|
175
|
-
|
179
|
+
# Returns a new +Date+/+DateTime+ representing the start of this week. Week is
|
180
|
+
# assumed to start on a Monday. +DateTime+ objects have their time set to 0:00.
|
181
|
+
def monday
|
182
|
+
beginning_of_week
|
183
|
+
end
|
184
|
+
|
185
|
+
# Returns a new Time representing the end of this week, week starts on start_day (default is :monday, i.e. end of Sunday).
|
186
|
+
def end_of_week(start_day = :monday)
|
187
|
+
days_to_end = 6 - days_to_week_start(start_day)
|
188
|
+
(self + days_to_end.days).end_of_day
|
176
189
|
end
|
177
190
|
alias :at_end_of_week :end_of_week
|
178
191
|
|
179
|
-
# Returns a new
|
192
|
+
# Returns a new +Date+/+DateTime+ representing the end of this week. Week is
|
193
|
+
# assumed to start on a Monday. +DateTime+ objects have their time set to 23:59:59.
|
194
|
+
def sunday
|
195
|
+
end_of_week
|
196
|
+
end
|
197
|
+
|
198
|
+
# Returns a new Time representing the start of the given day in the previous week (default is :monday).
|
180
199
|
def prev_week(day = :monday)
|
181
200
|
ago(1.week).beginning_of_week.since(DAYS_INTO_WEEK[day].day).change(:hour => 0)
|
182
201
|
end
|
183
202
|
|
184
|
-
# Returns a new Time representing the start of the given day in next week (default is
|
203
|
+
# Returns a new Time representing the start of the given day in next week (default is :monday).
|
185
204
|
def next_week(day = :monday)
|
186
205
|
since(1.week).beginning_of_week.since(DAYS_INTO_WEEK[day].day).change(:hour => 0)
|
187
206
|
end
|
@@ -227,7 +246,7 @@ class Time
|
|
227
246
|
end
|
228
247
|
alias :at_end_of_quarter :end_of_quarter
|
229
248
|
|
230
|
-
# Returns
|
249
|
+
# Returns a new Time representing the start of the year (1st of january, 0:00)
|
231
250
|
def beginning_of_year
|
232
251
|
change(:month => 1, :day => 1, :hour => 0)
|
233
252
|
end
|
@@ -249,6 +268,31 @@ class Time
|
|
249
268
|
advance(:days => 1)
|
250
269
|
end
|
251
270
|
|
271
|
+
# Returns a Range representing the whole day of the current time.
|
272
|
+
def all_day
|
273
|
+
beginning_of_day..end_of_day
|
274
|
+
end
|
275
|
+
|
276
|
+
# Returns a Range representing the whole week of the current time.
|
277
|
+
def all_week
|
278
|
+
beginning_of_week..end_of_week
|
279
|
+
end
|
280
|
+
|
281
|
+
# Returns a Range representing the whole month of the current time.
|
282
|
+
def all_month
|
283
|
+
beginning_of_month..end_of_month
|
284
|
+
end
|
285
|
+
|
286
|
+
# Returns a Range representing the whole quarter of the current time.
|
287
|
+
def all_quarter
|
288
|
+
beginning_of_quarter..end_of_quarter
|
289
|
+
end
|
290
|
+
|
291
|
+
# Returns a Range representing the whole year of the current time.
|
292
|
+
def all_year
|
293
|
+
beginning_of_year..end_of_year
|
294
|
+
end
|
295
|
+
|
252
296
|
def plus_with_duration(other) #:nodoc:
|
253
297
|
if ActiveSupport::Duration === other
|
254
298
|
other.since(self)
|
@@ -287,4 +331,14 @@ class Time
|
|
287
331
|
end
|
288
332
|
alias_method :compare_without_coercion, :<=>
|
289
333
|
alias_method :<=>, :compare_with_coercion
|
334
|
+
|
335
|
+
# Layers additional behavior on Time#eql? so that ActiveSupport::TimeWithZone instances
|
336
|
+
# can be eql? to an equivalent Time
|
337
|
+
def eql_with_coercion(other)
|
338
|
+
# if other is an ActiveSupport::TimeWithZone, coerce a Time instance from it so we can do eql? comparison
|
339
|
+
other = other.comparable_time if other.respond_to?(:comparable_time)
|
340
|
+
eql_without_coercion(other)
|
341
|
+
end
|
342
|
+
alias_method :eql_without_coercion, :eql?
|
343
|
+
alias_method :eql?, :eql_with_coercion
|
290
344
|
end
|
@@ -5,7 +5,7 @@ require 'active_support/core_ext/module/aliasing'
|
|
5
5
|
require 'active_support/core_ext/module/attribute_accessors'
|
6
6
|
require 'active_support/core_ext/module/introspection'
|
7
7
|
require 'active_support/core_ext/module/anonymous'
|
8
|
-
require 'active_support/core_ext/module/
|
8
|
+
require 'active_support/core_ext/module/qualified_const'
|
9
9
|
require 'active_support/core_ext/object/blank'
|
10
10
|
require 'active_support/core_ext/load_error'
|
11
11
|
require 'active_support/core_ext/name_error'
|
@@ -71,14 +71,24 @@ module ActiveSupport #:nodoc:
|
|
71
71
|
#
|
72
72
|
# This is handled by walking back up the watch stack and adding the constants
|
73
73
|
# found by child.rb to the list of original constants in parent.rb
|
74
|
-
class WatchStack
|
74
|
+
class WatchStack
|
75
|
+
include Enumerable
|
76
|
+
|
75
77
|
# @watching is a stack of lists of constants being watched. For instance,
|
76
78
|
# if parent.rb is autoloaded, the stack will look like [[Object]]. If parent.rb
|
77
79
|
# then requires namespace/child.rb, the stack will look like [[Object], [Namespace]].
|
78
80
|
|
79
81
|
def initialize
|
80
82
|
@watching = []
|
81
|
-
|
83
|
+
@stack = Hash.new { |h,k| h[k] = [] }
|
84
|
+
end
|
85
|
+
|
86
|
+
def each(&block)
|
87
|
+
@stack.each(&block)
|
88
|
+
end
|
89
|
+
|
90
|
+
def watching?
|
91
|
+
!@watching.empty?
|
82
92
|
end
|
83
93
|
|
84
94
|
# return a list of new constants found since the last call to watch_namespaces
|
@@ -89,7 +99,7 @@ module ActiveSupport #:nodoc:
|
|
89
99
|
@watching.last.each do |namespace|
|
90
100
|
# Retrieve the constants that were present under the namespace when watch_namespaces
|
91
101
|
# was originally called
|
92
|
-
original_constants =
|
102
|
+
original_constants = @stack[namespace].last
|
93
103
|
|
94
104
|
mod = Inflector.constantize(namespace) if Dependencies.qualified_const_defined?(namespace)
|
95
105
|
next unless mod.is_a?(Module)
|
@@ -102,7 +112,7 @@ module ActiveSupport #:nodoc:
|
|
102
112
|
# element of self[Object] will be an Array of the constants that were present
|
103
113
|
# before parent.rb was required. The second element will be an Array of the
|
104
114
|
# constants that were present before child.rb was required.
|
105
|
-
|
115
|
+
@stack[namespace].each do |namespace_constants|
|
106
116
|
namespace_constants.concat(new_constants)
|
107
117
|
end
|
108
118
|
|
@@ -126,13 +136,14 @@ module ActiveSupport #:nodoc:
|
|
126
136
|
Inflector.constantize(module_name).local_constant_names : []
|
127
137
|
|
128
138
|
watching << module_name
|
129
|
-
|
139
|
+
@stack[module_name] << original_constants
|
130
140
|
end
|
131
141
|
@watching << watching
|
132
142
|
end
|
133
143
|
|
144
|
+
private
|
134
145
|
def pop_modules(modules)
|
135
|
-
modules.each { |mod|
|
146
|
+
modules.each { |mod| @stack[mod].pop }
|
136
147
|
end
|
137
148
|
end
|
138
149
|
|
@@ -219,8 +230,8 @@ module ActiveSupport #:nodoc:
|
|
219
230
|
end
|
220
231
|
|
221
232
|
def load_dependency(file)
|
222
|
-
if Dependencies.load?
|
223
|
-
Dependencies.new_constants_in(Object) { yield }
|
233
|
+
if Dependencies.load? && ActiveSupport::Dependencies.constant_watch_stack.watching?
|
234
|
+
Dependencies.new_constants_in(Object) { yield }
|
224
235
|
else
|
225
236
|
yield
|
226
237
|
end
|
@@ -229,13 +240,13 @@ module ActiveSupport #:nodoc:
|
|
229
240
|
raise
|
230
241
|
end
|
231
242
|
|
232
|
-
def load(file,
|
243
|
+
def load(file, wrap = false)
|
233
244
|
result = false
|
234
245
|
load_dependency(file) { result = super }
|
235
246
|
result
|
236
247
|
end
|
237
248
|
|
238
|
-
def require(file
|
249
|
+
def require(file)
|
239
250
|
result = false
|
240
251
|
load_dependency(file) { result = super }
|
241
252
|
result
|
@@ -358,12 +369,13 @@ module ActiveSupport #:nodoc:
|
|
358
369
|
end
|
359
370
|
|
360
371
|
# Is the provided constant path defined?
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
372
|
+
if Module.method(:const_defined?).arity == 1
|
373
|
+
def qualified_const_defined?(path)
|
374
|
+
Object.qualified_const_defined?(path.sub(/^::/, ''))
|
375
|
+
end
|
376
|
+
else
|
377
|
+
def qualified_const_defined?(path)
|
378
|
+
Object.qualified_const_defined?(path.sub(/^::/, ''), false)
|
367
379
|
end
|
368
380
|
end
|
369
381
|
|
@@ -422,7 +434,8 @@ module ActiveSupport #:nodoc:
|
|
422
434
|
end
|
423
435
|
|
424
436
|
def load_once_path?(path)
|
425
|
-
|
437
|
+
# to_s works around a ruby1.9 issue where #starts_with?(Pathname) will always return false
|
438
|
+
autoload_once_paths.any? { |base| path.starts_with? base.to_s }
|
426
439
|
end
|
427
440
|
|
428
441
|
# Attempt to autoload the provided module name by searching for a directory
|
@@ -525,7 +538,7 @@ module ActiveSupport #:nodoc:
|
|
525
538
|
|
526
539
|
class ClassCache
|
527
540
|
def initialize
|
528
|
-
@store = Hash.new
|
541
|
+
@store = Hash.new
|
529
542
|
end
|
530
543
|
|
531
544
|
def empty?
|
@@ -536,40 +549,24 @@ module ActiveSupport #:nodoc:
|
|
536
549
|
@store.key?(key)
|
537
550
|
end
|
538
551
|
|
539
|
-
def
|
540
|
-
return unless key.respond_to?(:name)
|
541
|
-
|
542
|
-
raise(ArgumentError, 'anonymous classes cannot be cached') if key.name.blank?
|
543
|
-
|
544
|
-
@store[key.name] = value
|
545
|
-
end
|
546
|
-
|
547
|
-
def [](key)
|
552
|
+
def get(key)
|
548
553
|
key = key.name if key.respond_to?(:name)
|
549
|
-
|
550
|
-
@store[key]
|
554
|
+
@store[key] ||= Inflector.constantize(key)
|
551
555
|
end
|
552
|
-
alias :
|
553
|
-
|
554
|
-
class Getter # :nodoc:
|
555
|
-
def initialize(name)
|
556
|
-
@name = name
|
557
|
-
end
|
556
|
+
alias :[] :get
|
558
557
|
|
559
|
-
|
560
|
-
|
558
|
+
def safe_get(key)
|
559
|
+
key = key.name if key.respond_to?(:name)
|
560
|
+
@store[key] || begin
|
561
|
+
klass = Inflector.safe_constantize(key)
|
562
|
+
@store[key] = klass
|
561
563
|
end
|
562
|
-
deprecate :get
|
563
564
|
end
|
564
565
|
|
565
|
-
def
|
566
|
-
self
|
567
|
-
|
568
|
-
|
569
|
-
deprecate :new
|
570
|
-
|
571
|
-
def store(name)
|
572
|
-
self[name] = name
|
566
|
+
def store(klass)
|
567
|
+
return self unless klass.respond_to?(:name)
|
568
|
+
raise(ArgumentError, 'anonymous classes cannot be cached') if klass.name.empty?
|
569
|
+
@store[klass.name] = klass
|
573
570
|
self
|
574
571
|
end
|
575
572
|
|
@@ -580,21 +577,23 @@ module ActiveSupport #:nodoc:
|
|
580
577
|
|
581
578
|
Reference = ClassCache.new
|
582
579
|
|
583
|
-
def ref(name)
|
584
|
-
Reference.new(name)
|
585
|
-
end
|
586
|
-
deprecate :ref
|
587
|
-
|
588
580
|
# Store a reference to a class +klass+.
|
589
581
|
def reference(klass)
|
590
582
|
Reference.store klass
|
591
583
|
end
|
592
584
|
|
593
585
|
# Get the reference for class named +name+.
|
586
|
+
# Raises an exception if referenced class does not exist.
|
594
587
|
def constantize(name)
|
595
588
|
Reference.get(name)
|
596
589
|
end
|
597
590
|
|
591
|
+
# Get the reference for class named +name+ if one exists.
|
592
|
+
# Otherwise returns nil.
|
593
|
+
def safe_constantize(name)
|
594
|
+
Reference.safe_get(name)
|
595
|
+
end
|
596
|
+
|
598
597
|
# Determine if the given constant has been automatically loaded.
|
599
598
|
def autoloaded?(desc)
|
600
599
|
# No name => anonymous module.
|