activesupport 5.0.0.beta1.1 → 5.0.0.beta2
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 +79 -45
- data/MIT-LICENSE +2 -2
- data/lib/active_support.rb +1 -1
- data/lib/active_support/cache.rb +13 -12
- data/lib/active_support/cache/file_store.rb +9 -3
- data/lib/active_support/concurrency/share_lock.rb +37 -19
- data/lib/active_support/core_ext/hash/conversions.rb +2 -0
- data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -6
- data/lib/active_support/core_ext/module/deprecation.rb +2 -2
- data/lib/active_support/core_ext/numeric/conversions.rb +8 -1
- data/lib/active_support/core_ext/string/output_safety.rb +3 -4
- data/lib/active_support/core_ext/time/zones.rb +17 -1
- data/lib/active_support/dependencies/interlock.rb +3 -3
- data/lib/active_support/deprecation.rb +1 -1
- data/lib/active_support/deprecation/behaviors.rb +2 -0
- data/lib/active_support/deprecation/method_wrappers.rb +3 -3
- data/lib/active_support/gem_version.rb +1 -1
- data/lib/active_support/hash_with_indifferent_access.rb +18 -6
- data/lib/active_support/inflector/methods.rb +1 -1
- data/lib/active_support/locale/en.yml +2 -0
- data/lib/active_support/logger.rb +26 -4
- data/lib/active_support/logger_silence.rb +23 -3
- data/lib/active_support/multibyte/unicode.rb +38 -13
- data/lib/active_support/notifications/instrumenter.rb +1 -0
- data/lib/active_support/number_helper.rb +10 -0
- data/lib/active_support/number_helper/number_to_currency_converter.rb +3 -5
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +1 -1
- data/lib/active_support/ordered_hash.rb +1 -1
- data/lib/active_support/test_case.rb +0 -10
- metadata +4 -4
- data/lib/active_support/testing/composite_filter.rb +0 -54
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: feeceb08e3de4f23beb469414fac32aa949de4ca
|
4
|
+
data.tar.gz: ed224db38f3a6524c78cd4833484eb93d4a4cc4f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2714c0f5258a1d8678f750cf4ec835f033db1a999652e439f958b5077d1b10bbec05323366393b2b7db06bcc049f01a4111e2a7aa8a82f7dd236523254bb586d
|
7
|
+
data.tar.gz: 5dca3370c49f9d30af666064201f536cec39a49c2864fb3ccbaf56a1ab9c42fe0de7e6baca81b669873ed41471367a83271d338ccb8ace0f29aae812a051a4b4
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,41 @@
|
|
1
|
-
## Rails 5.0.0.
|
1
|
+
## Rails 5.0.0.beta2 (February 01, 2016) ##
|
2
|
+
|
3
|
+
* Change number_to_currency behavior for checking negativity.
|
4
|
+
|
5
|
+
Used `to_f.negative` instead of using `to_f.phase` for checking negativity
|
6
|
+
of a number in number_to_currency helper.
|
7
|
+
This change works same for all cases except when number is "-0.0".
|
8
|
+
|
9
|
+
-0.0.to_f.negative? => false
|
10
|
+
-0.0.to_f.phase? => 3.14
|
11
|
+
|
12
|
+
This change reverts changes from https://github.com/rails/rails/pull/6512.
|
13
|
+
But it should be acceptable as we could not find any currency which
|
14
|
+
supports negative zeros.
|
15
|
+
|
16
|
+
*Prathamesh Sonpatki*, *Rafael Mendonça França*
|
17
|
+
|
18
|
+
* Match `HashWithIndifferentAccess#default`'s behaviour with `Hash#default`.
|
19
|
+
|
20
|
+
*David Cornu*
|
21
|
+
|
22
|
+
* Adds `:exception_object` key to `ActiveSupport::Notifications::Instrumenter`
|
23
|
+
payload when an exception is raised.
|
24
|
+
|
25
|
+
Adds new key/value pair to payload when an exception is raised:
|
26
|
+
e.g. `:exception_object => #<RuntimeError: FAIL>`.
|
27
|
+
|
28
|
+
*Ryan T. Hosford*
|
29
|
+
|
30
|
+
* Support extended grapheme clusters and UAX 29.
|
31
|
+
|
32
|
+
*Adam Roben*
|
33
|
+
|
34
|
+
* Add petabyte and exabyte numeric conversion.
|
2
35
|
|
3
|
-
*
|
36
|
+
*Akshay Vishnoi*
|
4
37
|
|
38
|
+
## Rails 5.0.0.beta1 (December 18, 2015) ##
|
5
39
|
|
6
40
|
* Add thread_m/cattr_accessor/reader/writer suite of methods for declaring class and module variables that live per-thread.
|
7
41
|
This makes it easy to declare per-thread globals that are encapsulated. Note: This is a sharp edge. A wild proliferation
|
@@ -10,44 +44,44 @@
|
|
10
44
|
Here's an example of a simple event tracking system where the object being tracked needs not pass a creator that it
|
11
45
|
doesn't need itself along:
|
12
46
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
19
|
-
|
20
|
-
class ApplicationController < ActiveController::Base
|
21
|
-
before_action :set_current
|
22
|
-
after_action { Current.reset }
|
23
|
-
|
24
|
-
private
|
25
|
-
def set_current
|
26
|
-
Current.account = Account.find(params[:account_id])
|
27
|
-
Current.user = Current.account.users.find(params[:user_id])
|
47
|
+
module Current
|
48
|
+
thread_mattr_accessor :account
|
49
|
+
thread_mattr_accessor :user
|
50
|
+
|
51
|
+
def self.reset() self.account = self.user = nil end
|
28
52
|
end
|
29
|
-
end
|
30
53
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
54
|
+
class ApplicationController < ActionController::Base
|
55
|
+
before_action :set_current
|
56
|
+
after_action { Current.reset }
|
57
|
+
|
58
|
+
private
|
59
|
+
def set_current
|
60
|
+
Current.account = Account.find(params[:account_id])
|
61
|
+
Current.user = Current.account.users.find(params[:user_id])
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class MessagesController < ApplicationController
|
66
|
+
def create
|
67
|
+
@message = Message.create!(message_params)
|
68
|
+
end
|
44
69
|
end
|
45
|
-
end
|
46
70
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
71
|
+
class Message < ApplicationRecord
|
72
|
+
has_many :events
|
73
|
+
after_create :track_created
|
74
|
+
|
75
|
+
private
|
76
|
+
def track_created
|
77
|
+
events.create! origin: self, action: :create
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class Event < ApplicationRecord
|
82
|
+
belongs_to :creator, class_name: 'User'
|
83
|
+
before_validation { self.creator ||= Current.user }
|
84
|
+
end
|
51
85
|
|
52
86
|
*DHH*
|
53
87
|
|
@@ -61,9 +95,9 @@
|
|
61
95
|
|
62
96
|
*Yuichiro Kaneko*
|
63
97
|
|
64
|
-
* `ActiveSupport::Cache::Store#namespaced_key`,
|
65
|
-
`ActiveSupport::Cache::MemCachedStore#escape_key`, and
|
66
|
-
`ActiveSupport::Cache::FileStore#key_file_path`
|
98
|
+
* `ActiveSupport::Cache::Store#namespaced_key`,
|
99
|
+
`ActiveSupport::Cache::MemCachedStore#escape_key`, and
|
100
|
+
`ActiveSupport::Cache::FileStore#key_file_path`
|
67
101
|
are deprecated and replaced with `normalize_key` that now calls `super`.
|
68
102
|
|
69
103
|
`ActiveSupport::Cache::LocaleCache#set_cache_value` is deprecated and replaced with `write_cache_value`.
|
@@ -122,7 +156,7 @@
|
|
122
156
|
|
123
157
|
*Konstantinos Rousis*
|
124
158
|
|
125
|
-
* Handle invalid UTF-8 strings when HTML escaping
|
159
|
+
* Handle invalid UTF-8 strings when HTML escaping.
|
126
160
|
|
127
161
|
Use `ActiveSupport::Multibyte::Unicode.tidy_bytes` to handle invalid UTF-8
|
128
162
|
strings in `ERB::Util.unwrapped_html_escape` and `ERB::Util.html_escape_once`.
|
@@ -163,7 +197,7 @@
|
|
163
197
|
|
164
198
|
* Short-circuit `blank?` on date and time values since they are never blank.
|
165
199
|
|
166
|
-
Fixes #21657
|
200
|
+
Fixes #21657.
|
167
201
|
|
168
202
|
*Andrew White*
|
169
203
|
|
@@ -201,7 +235,7 @@
|
|
201
235
|
* ActiveSupport::HashWithIndifferentAccess `select` and `reject` will now return
|
202
236
|
enumerator if called without block.
|
203
237
|
|
204
|
-
Fixes #20095
|
238
|
+
Fixes #20095.
|
205
239
|
|
206
240
|
*Bernard Potocki*
|
207
241
|
|
@@ -215,11 +249,11 @@
|
|
215
249
|
|
216
250
|
*Simon Eskildsen*
|
217
251
|
|
218
|
-
* Fix setting `default_proc` on `HashWithIndifferentAccess#dup
|
252
|
+
* Fix setting `default_proc` on `HashWithIndifferentAccess#dup`.
|
219
253
|
|
220
254
|
*Simon Eskildsen*
|
221
255
|
|
222
|
-
* Fix a range of values for parameters of the Time#change
|
256
|
+
* Fix a range of values for parameters of the Time#change.
|
223
257
|
|
224
258
|
*Nikolay Kondratyev*
|
225
259
|
|
@@ -231,7 +265,7 @@
|
|
231
265
|
*Kevin Deisz*
|
232
266
|
|
233
267
|
* Add a bang version to `ActiveSupport::OrderedOptions` get methods which will raise
|
234
|
-
an `KeyError` if the value is `.blank
|
268
|
+
an `KeyError` if the value is `.blank?`.
|
235
269
|
|
236
270
|
Before:
|
237
271
|
|
data/MIT-LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c) 2005-
|
1
|
+
Copyright (c) 2005-2016 David Heinemeier Hansson
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
a copy of this software and associated documentation files (the
|
@@ -17,4 +17,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
17
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
18
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
19
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/lib/active_support.rb
CHANGED
data/lib/active_support/cache.rb
CHANGED
@@ -255,10 +255,11 @@ module ActiveSupport
|
|
255
255
|
# end
|
256
256
|
# end
|
257
257
|
#
|
258
|
-
# #
|
259
|
-
# #
|
260
|
-
#
|
261
|
-
# #
|
258
|
+
# cache.fetch('foo') # => "original value"
|
259
|
+
# sleep 10 # First thread extended the life of cache by another 10 seconds
|
260
|
+
# cache.fetch('foo') # => "new value 1"
|
261
|
+
# val_1 # => "new value 1"
|
262
|
+
# val_2 # => "original value"
|
262
263
|
#
|
263
264
|
# Other options will be handled by the specific cache store implementation.
|
264
265
|
# Internally, #fetch calls #read_entry, and calls #write_entry on a cache
|
@@ -278,18 +279,18 @@ module ActiveSupport
|
|
278
279
|
options = merged_options(options)
|
279
280
|
key = normalize_key(name, options)
|
280
281
|
|
282
|
+
entry = nil
|
281
283
|
instrument(:read, name, options) do |payload|
|
282
284
|
cached_entry = read_entry(key, options) unless options[:force]
|
283
|
-
payload[:super_operation] = :fetch if payload
|
284
285
|
entry = handle_expired_entry(cached_entry, key, options)
|
286
|
+
payload[:super_operation] = :fetch if payload
|
287
|
+
payload[:hit] = !!entry if payload
|
288
|
+
end
|
285
289
|
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
payload[:hit] = false if payload
|
291
|
-
save_block_result_to_cache(name, options) { |_name| yield _name }
|
292
|
-
end
|
290
|
+
if entry
|
291
|
+
get_entry_value(entry, name, options)
|
292
|
+
else
|
293
|
+
save_block_result_to_cache(name, options) { |_name| yield _name }
|
293
294
|
end
|
294
295
|
else
|
295
296
|
read(name, options)
|
@@ -17,6 +17,7 @@ module ActiveSupport
|
|
17
17
|
FILENAME_MAX_SIZE = 228 # max filename size on file system is 255, minus room for timestamp and random characters appended by Tempfile (used by atomic write)
|
18
18
|
FILEPATH_MAX_SIZE = 900 # max is 1024, plus some room
|
19
19
|
EXCLUDED_DIRS = ['.', '..'].freeze
|
20
|
+
GITKEEP_FILES = ['.gitkeep', '.keep'].freeze
|
20
21
|
|
21
22
|
def initialize(cache_path, options = nil)
|
22
23
|
super(options)
|
@@ -24,10 +25,10 @@ module ActiveSupport
|
|
24
25
|
end
|
25
26
|
|
26
27
|
# Deletes all items from the cache. In this case it deletes all the entries in the specified
|
27
|
-
# file store directory except for .gitkeep. Be careful which directory is specified in your
|
28
|
+
# file store directory except for .keep or .gitkeep. Be careful which directory is specified in your
|
28
29
|
# config file when using +FileStore+ because everything in that directory will be deleted.
|
29
30
|
def clear(options = nil)
|
30
|
-
root_dirs =
|
31
|
+
root_dirs = exclude_from(cache_path, EXCLUDED_DIRS + GITKEEP_FILES)
|
31
32
|
FileUtils.rm_r(root_dirs.collect{|f| File.join(cache_path, f)})
|
32
33
|
rescue Errno::ENOENT
|
33
34
|
end
|
@@ -154,7 +155,7 @@ module ActiveSupport
|
|
154
155
|
# Delete empty directories in the cache.
|
155
156
|
def delete_empty_directories(dir)
|
156
157
|
return if File.realpath(dir) == File.realpath(cache_path)
|
157
|
-
if
|
158
|
+
if exclude_from(dir, EXCLUDED_DIRS).empty?
|
158
159
|
Dir.delete(dir) rescue nil
|
159
160
|
delete_empty_directories(File.dirname(dir))
|
160
161
|
end
|
@@ -193,6 +194,11 @@ module ActiveSupport
|
|
193
194
|
end
|
194
195
|
end
|
195
196
|
end
|
197
|
+
|
198
|
+
# Exclude entries from source directory
|
199
|
+
def exclude_from(source, excludes)
|
200
|
+
Dir.entries(source).reject { |f| excludes.include?(f) }
|
201
|
+
end
|
196
202
|
end
|
197
203
|
end
|
198
204
|
end
|
@@ -48,17 +48,11 @@ module ActiveSupport
|
|
48
48
|
def start_exclusive(purpose: nil, compatible: [], no_wait: false)
|
49
49
|
synchronize do
|
50
50
|
unless @exclusive_thread == Thread.current
|
51
|
-
if
|
51
|
+
if busy_for_exclusive?(purpose)
|
52
52
|
return false if no_wait
|
53
53
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
begin
|
58
|
-
@cv.wait_while { busy?(purpose) }
|
59
|
-
ensure
|
60
|
-
@waiting.delete Thread.current
|
61
|
-
@sharing[Thread.current] = loose_shares if loose_shares
|
54
|
+
yield_shares(purpose, compatible) do
|
55
|
+
@cv.wait_while { busy_for_exclusive?(purpose) }
|
62
56
|
end
|
63
57
|
end
|
64
58
|
@exclusive_thread = Thread.current
|
@@ -71,22 +65,26 @@ module ActiveSupport
|
|
71
65
|
|
72
66
|
# Relinquish the exclusive lock. Must only be called by the thread
|
73
67
|
# that called start_exclusive (and currently holds the lock).
|
74
|
-
def stop_exclusive
|
68
|
+
def stop_exclusive(compatible: [])
|
75
69
|
synchronize do
|
76
70
|
raise "invalid unlock" if @exclusive_thread != Thread.current
|
77
71
|
|
78
72
|
@exclusive_depth -= 1
|
79
73
|
if @exclusive_depth == 0
|
80
74
|
@exclusive_thread = nil
|
81
|
-
|
75
|
+
|
76
|
+
yield_shares(nil, compatible) do
|
77
|
+
@cv.broadcast
|
78
|
+
@cv.wait_while { @exclusive_thread || eligible_waiters?(compatible) }
|
79
|
+
end
|
82
80
|
end
|
83
81
|
end
|
84
82
|
end
|
85
83
|
|
86
|
-
def start_sharing
|
84
|
+
def start_sharing(purpose: :share)
|
87
85
|
synchronize do
|
88
|
-
if @
|
89
|
-
@cv.wait_while {
|
86
|
+
if @sharing[Thread.current] == 0 && @exclusive_thread != Thread.current && busy_for_sharing?(purpose)
|
87
|
+
@cv.wait_while { busy_for_sharing?(purpose) }
|
90
88
|
end
|
91
89
|
@sharing[Thread.current] += 1
|
92
90
|
end
|
@@ -109,12 +107,12 @@ module ActiveSupport
|
|
109
107
|
# the block.
|
110
108
|
#
|
111
109
|
# See +start_exclusive+ for other options.
|
112
|
-
def exclusive(purpose: nil, compatible: [], no_wait: false)
|
110
|
+
def exclusive(purpose: nil, compatible: [], after_compatible: [], no_wait: false)
|
113
111
|
if start_exclusive(purpose: purpose, compatible: compatible, no_wait: no_wait)
|
114
112
|
begin
|
115
113
|
yield
|
116
114
|
ensure
|
117
|
-
stop_exclusive
|
115
|
+
stop_exclusive(compatible: after_compatible)
|
118
116
|
end
|
119
117
|
end
|
120
118
|
end
|
@@ -132,11 +130,31 @@ module ActiveSupport
|
|
132
130
|
private
|
133
131
|
|
134
132
|
# Must be called within synchronize
|
135
|
-
def
|
136
|
-
(
|
137
|
-
@waiting.any? { |k, v| k != Thread.current && !v.include?(purpose) } ||
|
133
|
+
def busy_for_exclusive?(purpose)
|
134
|
+
busy_for_sharing?(purpose) ||
|
138
135
|
@sharing.size > (@sharing[Thread.current] > 0 ? 1 : 0)
|
139
136
|
end
|
137
|
+
|
138
|
+
def busy_for_sharing?(purpose)
|
139
|
+
(@exclusive_thread && @exclusive_thread != Thread.current) ||
|
140
|
+
@waiting.any? { |t, (_, c)| t != Thread.current && !c.include?(purpose) }
|
141
|
+
end
|
142
|
+
|
143
|
+
def eligible_waiters?(compatible)
|
144
|
+
@waiting.any? { |t, (p, _)| compatible.include?(p) && @waiting.all? { |t2, (_, c2)| t == t2 || c2.include?(p) } }
|
145
|
+
end
|
146
|
+
|
147
|
+
def yield_shares(purpose, compatible)
|
148
|
+
loose_shares = @sharing.delete(Thread.current)
|
149
|
+
@waiting[Thread.current] = [purpose, compatible] if loose_shares
|
150
|
+
|
151
|
+
begin
|
152
|
+
yield
|
153
|
+
ensure
|
154
|
+
@waiting.delete Thread.current
|
155
|
+
@sharing[Thread.current] = loose_shares if loose_shares
|
156
|
+
end
|
157
|
+
end
|
140
158
|
end
|
141
159
|
end
|
142
160
|
end
|
@@ -138,6 +138,8 @@ end
|
|
138
138
|
|
139
139
|
module ActiveSupport
|
140
140
|
class XMLConverter # :nodoc:
|
141
|
+
# Raised if the XML contains attributes with type="yaml" or
|
142
|
+
# type="symbol". Read Hash#from_xml for more details.
|
141
143
|
class DisallowedType < StandardError
|
142
144
|
def initialize(type)
|
143
145
|
super "Disallowed type attribute: #{type.inspect}"
|
@@ -49,7 +49,7 @@ class Module
|
|
49
49
|
# include HairColors
|
50
50
|
# end
|
51
51
|
#
|
52
|
-
# Person.hair_colors # => [:brown, :black, :blonde, :red]
|
52
|
+
# Person.new.hair_colors # => [:brown, :black, :blonde, :red]
|
53
53
|
def mattr_reader(*syms)
|
54
54
|
options = syms.extract_options!
|
55
55
|
syms.each do |sym|
|
@@ -105,7 +105,7 @@ class Module
|
|
105
105
|
#
|
106
106
|
# Also, you can pass a block to set up the attribute with a default value.
|
107
107
|
#
|
108
|
-
#
|
108
|
+
# module HairColors
|
109
109
|
# mattr_writer :hair_colors do
|
110
110
|
# [:brown, :black, :blonde, :red]
|
111
111
|
# end
|
@@ -150,8 +150,8 @@ class Module
|
|
150
150
|
# include HairColors
|
151
151
|
# end
|
152
152
|
#
|
153
|
-
#
|
154
|
-
#
|
153
|
+
# HairColors.hair_colors = [:brown, :black, :blonde, :red]
|
154
|
+
# HairColors.hair_colors # => [:brown, :black, :blonde, :red]
|
155
155
|
# Person.new.hair_colors # => [:brown, :black, :blonde, :red]
|
156
156
|
#
|
157
157
|
# If a subclass changes the value then that would also change the value for
|
@@ -161,8 +161,8 @@ class Module
|
|
161
161
|
# class Male < Person
|
162
162
|
# end
|
163
163
|
#
|
164
|
-
# Male.hair_colors << :blue
|
165
|
-
# Person.hair_colors # => [:brown, :black, :blonde, :red, :blue]
|
164
|
+
# Male.new.hair_colors << :blue
|
165
|
+
# Person.new.hair_colors # => [:brown, :black, :blonde, :red, :blue]
|
166
166
|
#
|
167
167
|
# To opt out of the instance writer method, pass <tt>instance_writer: false</tt>.
|
168
168
|
# To opt out of the instance reader method, pass <tt>instance_reader: false</tt>.
|
@@ -13,8 +13,8 @@ class Module
|
|
13
13
|
#
|
14
14
|
# class MyLib::Deprecator
|
15
15
|
# def deprecation_warning(deprecated_method_name, message, caller_backtrace = nil)
|
16
|
-
#
|
17
|
-
#
|
16
|
+
# message = "#{deprecated_method_name} is deprecated and will be removed from MyLibrary | #{message}"
|
17
|
+
# Kernel.warn message
|
18
18
|
# end
|
19
19
|
# end
|
20
20
|
def deprecate(*method_names)
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'active_support/core_ext/big_decimal/conversions'
|
2
2
|
require 'active_support/number_helper'
|
3
|
+
require 'active_support/core_ext/module/deprecation'
|
3
4
|
|
4
5
|
module ActiveSupport::NumericWithFormat
|
5
6
|
|
@@ -75,6 +76,8 @@ module ActiveSupport::NumericWithFormat
|
|
75
76
|
# 1234567.to_s(:human_size) # => 1.18 MB
|
76
77
|
# 1234567890.to_s(:human_size) # => 1.15 GB
|
77
78
|
# 1234567890123.to_s(:human_size) # => 1.12 TB
|
79
|
+
# 1234567890123456.to_s(:human_size) # => 1.1 PB
|
80
|
+
# 1234567890123456789.to_s(:human_size) # => 1.07 EB
|
78
81
|
# 1234567.to_s(:human_size, precision: 2) # => 1.2 MB
|
79
82
|
# 483989.to_s(:human_size, precision: 2) # => 470 KB
|
80
83
|
# 1234567.to_s(:human_size, precision: 2, separator: ',') # => 1,2 MB
|
@@ -117,7 +120,11 @@ module ActiveSupport::NumericWithFormat
|
|
117
120
|
when :human_size
|
118
121
|
return ActiveSupport::NumberHelper.number_to_human_size(self, options)
|
119
122
|
else
|
120
|
-
|
123
|
+
if is_a?(Float) || format.is_a?(Symbol)
|
124
|
+
super()
|
125
|
+
else
|
126
|
+
super
|
127
|
+
end
|
121
128
|
end
|
122
129
|
end
|
123
130
|
|
@@ -5,7 +5,6 @@ class ERB
|
|
5
5
|
module Util
|
6
6
|
HTML_ESCAPE = { '&' => '&', '>' => '>', '<' => '<', '"' => '"', "'" => ''' }
|
7
7
|
JSON_ESCAPE = { '&' => '\u0026', '>' => '\u003e', '<' => '\u003c', "\u2028" => '\u2028', "\u2029" => '\u2029' }
|
8
|
-
HTML_ESCAPE_REGEXP = /[&"'><]/
|
9
8
|
HTML_ESCAPE_ONCE_REGEXP = /["><']|&(?!([a-zA-Z]+|(#\d+)|(#[xX][\dA-Fa-f]+));)/
|
10
9
|
JSON_ESCAPE_REGEXP = /[\u2028\u2029&><]/u
|
11
10
|
|
@@ -37,7 +36,7 @@ class ERB
|
|
37
36
|
if s.html_safe?
|
38
37
|
s
|
39
38
|
else
|
40
|
-
ActiveSupport::Multibyte::Unicode.tidy_bytes(s)
|
39
|
+
CGI.escapeHTML(ActiveSupport::Multibyte::Unicode.tidy_bytes(s))
|
41
40
|
end
|
42
41
|
end
|
43
42
|
module_function :unwrapped_html_escape
|
@@ -142,6 +141,7 @@ module ActiveSupport #:nodoc:
|
|
142
141
|
alias_method :original_concat, :concat
|
143
142
|
private :original_concat
|
144
143
|
|
144
|
+
# Raised when <tt>ActiveSupport::SafeBuffer#safe_concat</tt> is called on unsafe buffers.
|
145
145
|
class SafeConcatError < StandardError
|
146
146
|
def initialize
|
147
147
|
super 'Could not concatenate to the buffer because it is not html safe.'
|
@@ -243,8 +243,7 @@ module ActiveSupport #:nodoc:
|
|
243
243
|
private
|
244
244
|
|
245
245
|
def html_escape_interpolated_argument(arg)
|
246
|
-
(!html_safe? || arg.html_safe?) ? arg :
|
247
|
-
arg.to_s.gsub(ERB::Util::HTML_ESCAPE_REGEXP, ERB::Util::HTML_ESCAPE)
|
246
|
+
(!html_safe? || arg.html_safe?) ? arg : CGI.escapeHTML(arg.to_s)
|
248
247
|
end
|
249
248
|
end
|
250
249
|
end
|
@@ -40,7 +40,23 @@ class Time
|
|
40
40
|
Thread.current[:time_zone] = find_zone!(time_zone)
|
41
41
|
end
|
42
42
|
|
43
|
-
# Allows override of <tt>Time.zone</tt> locally inside supplied block;
|
43
|
+
# Allows override of <tt>Time.zone</tt> locally inside supplied block;
|
44
|
+
# resets <tt>Time.zone</tt> to existing value when done.
|
45
|
+
#
|
46
|
+
# class ApplicationController < ActionController::Base
|
47
|
+
# around_action :set_time_zone
|
48
|
+
#
|
49
|
+
# private
|
50
|
+
#
|
51
|
+
# def set_time_zone
|
52
|
+
# Time.use_zone(current_user.timezone) { yield }
|
53
|
+
# end
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# NOTE: This won't affect any <tt>ActiveSupport::TimeWithZone</tt>
|
57
|
+
# objects that have already been created, e.g. any model timestamp
|
58
|
+
# attributes that have been read before the block will remain in
|
59
|
+
# the application's default timezone.
|
44
60
|
def use_zone(time_zone)
|
45
61
|
new_zone = find_zone!(time_zone)
|
46
62
|
begin
|
@@ -8,13 +8,13 @@ module ActiveSupport #:nodoc:
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def loading
|
11
|
-
@lock.exclusive(purpose: :load, compatible: [:load]) do
|
11
|
+
@lock.exclusive(purpose: :load, compatible: [:load], after_compatible: [:load]) do
|
12
12
|
yield
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
16
|
def unloading
|
17
|
-
@lock.exclusive(purpose: :unload, compatible: [:load, :unload]) do
|
17
|
+
@lock.exclusive(purpose: :unload, compatible: [:load, :unload], after_compatible: [:load, :unload]) do
|
18
18
|
yield
|
19
19
|
end
|
20
20
|
end
|
@@ -24,7 +24,7 @@ module ActiveSupport #:nodoc:
|
|
24
24
|
# concurrent activity, return immediately (without executing the
|
25
25
|
# block) instead of waiting.
|
26
26
|
def attempt_unloading
|
27
|
-
@lock.exclusive(purpose: :unload, compatible: [:load, :unload], no_wait: true) do
|
27
|
+
@lock.exclusive(purpose: :unload, compatible: [:load, :unload], after_compatible: [:load, :unload], no_wait: true) do
|
28
28
|
yield
|
29
29
|
end
|
30
30
|
end
|
@@ -32,7 +32,7 @@ module ActiveSupport
|
|
32
32
|
# and the second is a library name
|
33
33
|
#
|
34
34
|
# ActiveSupport::Deprecation.new('2.0', 'MyLibrary')
|
35
|
-
def initialize(deprecation_horizon = '5.
|
35
|
+
def initialize(deprecation_horizon = '5.1', 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.
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require "active_support/notifications"
|
2
2
|
|
3
3
|
module ActiveSupport
|
4
|
+
# Raised when <tt>ActiveSupport::Deprecation::Behavior#behavior</tt> is set with <tt>:raise</tt>.
|
5
|
+
# You would set <tt>:raise</tt>, as a behaviour to raise errors and proactively report exceptions from deprecations.
|
4
6
|
class DeprecationException < StandardError
|
5
7
|
end
|
6
8
|
|
@@ -21,15 +21,15 @@ module ActiveSupport
|
|
21
21
|
# # => [:aaa, :bbb, :ccc]
|
22
22
|
#
|
23
23
|
# Fred.aaa
|
24
|
-
# # DEPRECATION WARNING: aaa is deprecated and will be removed from Rails 5.
|
24
|
+
# # DEPRECATION WARNING: aaa is deprecated and will be removed from Rails 5.1. (called from irb_binding at (irb):10)
|
25
25
|
# # => nil
|
26
26
|
#
|
27
27
|
# Fred.bbb
|
28
|
-
# # DEPRECATION WARNING: bbb is deprecated and will be removed from Rails 5.
|
28
|
+
# # DEPRECATION WARNING: bbb is deprecated and will be removed from Rails 5.1 (use zzz instead). (called from irb_binding at (irb):11)
|
29
29
|
# # => nil
|
30
30
|
#
|
31
31
|
# Fred.ccc
|
32
|
-
# # DEPRECATION WARNING: ccc is deprecated and will be removed from Rails 5.
|
32
|
+
# # DEPRECATION WARNING: ccc is deprecated and will be removed from Rails 5.1 (use Bar#ccc instead). (called from irb_binding at (irb):12)
|
33
33
|
# # => nil
|
34
34
|
#
|
35
35
|
# Passing in a custom deprecator:
|
@@ -68,12 +68,10 @@ module ActiveSupport
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
-
def default(
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
super
|
76
|
-
end
|
71
|
+
def default(*args)
|
72
|
+
key = args.first
|
73
|
+
args[0] = key.to_s if key.is_a?(Symbol)
|
74
|
+
super(*args)
|
77
75
|
end
|
78
76
|
|
79
77
|
def self.new_from_hash_copying_default(hash)
|
@@ -159,6 +157,20 @@ module ActiveSupport
|
|
159
157
|
alias_method :has_key?, :key?
|
160
158
|
alias_method :member?, :key?
|
161
159
|
|
160
|
+
|
161
|
+
# Same as <tt>Hash#[]</tt> where the key passed as argument can be
|
162
|
+
# either a string or a symbol:
|
163
|
+
#
|
164
|
+
# counters = ActiveSupport::HashWithIndifferentAccess.new
|
165
|
+
# counters[:foo] = 1
|
166
|
+
#
|
167
|
+
# counters['foo'] # => 1
|
168
|
+
# counters[:foo] # => 1
|
169
|
+
# counters[:zoo] # => nil
|
170
|
+
def [](key)
|
171
|
+
super(convert_key(key))
|
172
|
+
end
|
173
|
+
|
162
174
|
# Same as <tt>Hash#fetch</tt> where the key passed as argument can be
|
163
175
|
# either a string or a symbol:
|
164
176
|
#
|
@@ -173,7 +173,7 @@ module ActiveSupport
|
|
173
173
|
#
|
174
174
|
# Singular names are not handled correctly:
|
175
175
|
#
|
176
|
-
# classify('calculus') # => "
|
176
|
+
# classify('calculus') # => "Calculus"
|
177
177
|
def classify(table_name)
|
178
178
|
# strip out any leading schema name
|
179
179
|
camelize(singularize(table_name.to_s.sub(/.*\./, ''.freeze)))
|
@@ -5,18 +5,27 @@ module ActiveSupport
|
|
5
5
|
class Logger < ::Logger
|
6
6
|
include LoggerSilence
|
7
7
|
|
8
|
-
|
8
|
+
# Returns true if the logger destination matches one of the sources
|
9
|
+
#
|
10
|
+
# logger = Logger.new(STDOUT)
|
11
|
+
# ActiveSupport::Logger.logger_outputs_to?(logger, STDOUT)
|
12
|
+
# # => true
|
13
|
+
def self.logger_outputs_to?(logger, *sources)
|
14
|
+
logdev = logger.instance_variable_get("@logdev")
|
15
|
+
logger_source = logdev.dev if logdev.respond_to?(:dev)
|
16
|
+
sources.any? { |source| source == logger_source }
|
17
|
+
end
|
9
18
|
|
10
19
|
# Broadcasts logs to multiple loggers.
|
11
20
|
def self.broadcast(logger) # :nodoc:
|
12
21
|
Module.new do
|
13
22
|
define_method(:add) do |*args, &block|
|
14
|
-
logger.add(*args, &block)
|
23
|
+
logger.add(*args, &block)
|
15
24
|
super(*args, &block)
|
16
25
|
end
|
17
26
|
|
18
27
|
define_method(:<<) do |x|
|
19
|
-
logger << x
|
28
|
+
logger << x
|
20
29
|
super(x)
|
21
30
|
end
|
22
31
|
|
@@ -45,7 +54,20 @@ module ActiveSupport
|
|
45
54
|
def initialize(*args)
|
46
55
|
super
|
47
56
|
@formatter = SimpleFormatter.new
|
48
|
-
|
57
|
+
after_initialize if respond_to? :after_initialize
|
58
|
+
end
|
59
|
+
|
60
|
+
def add(severity, message = nil, progname = nil, &block)
|
61
|
+
return true if @logdev.nil? || (severity || UNKNOWN) < level
|
62
|
+
super
|
63
|
+
end
|
64
|
+
|
65
|
+
Logger::Severity.constants.each do |severity|
|
66
|
+
class_eval(<<-EOT, __FILE__, __LINE__ + 1)
|
67
|
+
def #{severity.downcase}? # def debug?
|
68
|
+
Logger::#{severity} >= level # DEBUG >= level
|
69
|
+
end # end
|
70
|
+
EOT
|
49
71
|
end
|
50
72
|
|
51
73
|
# Simple formatter which only displays the message.
|
@@ -1,25 +1,45 @@
|
|
1
1
|
require 'active_support/concern'
|
2
2
|
require 'active_support/core_ext/module/attribute_accessors'
|
3
|
+
require 'concurrent'
|
3
4
|
|
4
5
|
module LoggerSilence
|
5
6
|
extend ActiveSupport::Concern
|
6
7
|
|
7
8
|
included do
|
8
9
|
cattr_accessor :silencer
|
10
|
+
attr_reader :local_levels
|
9
11
|
self.silencer = true
|
10
12
|
end
|
11
13
|
|
14
|
+
def after_initialize
|
15
|
+
@local_levels = Concurrent::Map.new(:initial_capacity => 2)
|
16
|
+
end
|
17
|
+
|
18
|
+
def local_log_id
|
19
|
+
Thread.current.__id__
|
20
|
+
end
|
21
|
+
|
22
|
+
def level
|
23
|
+
local_levels[local_log_id] || super
|
24
|
+
end
|
25
|
+
|
12
26
|
# Silences the logger for the duration of the block.
|
13
27
|
def silence(temporary_level = Logger::ERROR)
|
14
28
|
if silencer
|
15
29
|
begin
|
16
|
-
|
30
|
+
old_local_level = local_levels[local_log_id]
|
31
|
+
local_levels[local_log_id] = temporary_level
|
32
|
+
|
17
33
|
yield self
|
18
34
|
ensure
|
19
|
-
|
35
|
+
if old_local_level
|
36
|
+
local_levels[local_log_id] = old_local_level
|
37
|
+
else
|
38
|
+
local_levels.delete(local_log_id)
|
39
|
+
end
|
20
40
|
end
|
21
41
|
else
|
22
42
|
yield self
|
23
43
|
end
|
24
44
|
end
|
25
|
-
end
|
45
|
+
end
|
@@ -87,19 +87,44 @@ module ActiveSupport
|
|
87
87
|
pos += 1
|
88
88
|
previous = codepoints[pos-1]
|
89
89
|
current = codepoints[pos]
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
)
|
102
|
-
|
90
|
+
|
91
|
+
should_break =
|
92
|
+
# GB3. CR X LF
|
93
|
+
if previous == database.boundary[:cr] and current == database.boundary[:lf]
|
94
|
+
false
|
95
|
+
# GB4. (Control|CR|LF) ÷
|
96
|
+
elsif previous and in_char_class?(previous, [:control,:cr,:lf])
|
97
|
+
true
|
98
|
+
# GB5. ÷ (Control|CR|LF)
|
99
|
+
elsif in_char_class?(current, [:control,:cr,:lf])
|
100
|
+
true
|
101
|
+
# GB6. L X (L|V|LV|LVT)
|
102
|
+
elsif database.boundary[:l] === previous and in_char_class?(current, [:l,:v,:lv,:lvt])
|
103
|
+
false
|
104
|
+
# GB7. (LV|V) X (V|T)
|
105
|
+
elsif in_char_class?(previous, [:lv,:v]) and in_char_class?(current, [:v,:t])
|
106
|
+
false
|
107
|
+
# GB8. (LVT|T) X (T)
|
108
|
+
elsif in_char_class?(previous, [:lvt,:t]) and database.boundary[:t] === current
|
109
|
+
false
|
110
|
+
# GB8a. Regional_Indicator X Regional_Indicator
|
111
|
+
elsif database.boundary[:regional_indicator] === previous and database.boundary[:regional_indicator] === current
|
112
|
+
false
|
113
|
+
# GB9. X Extend
|
114
|
+
elsif database.boundary[:extend] === current
|
115
|
+
false
|
116
|
+
# GB9a. X SpacingMark
|
117
|
+
elsif database.boundary[:spacingmark] === current
|
118
|
+
false
|
119
|
+
# GB9b. Prepend X
|
120
|
+
elsif database.boundary[:prepend] === previous
|
121
|
+
false
|
122
|
+
# GB10. Any ÷ Any
|
123
|
+
else
|
124
|
+
true
|
125
|
+
end
|
126
|
+
|
127
|
+
if should_break
|
103
128
|
unpacked << codepoints[marker..pos-1]
|
104
129
|
marker = pos
|
105
130
|
end
|
@@ -47,6 +47,14 @@ module ActiveSupport
|
|
47
47
|
# Formats a +number+ into a currency string (e.g., $13.65). You
|
48
48
|
# can customize the format in the +options+ hash.
|
49
49
|
#
|
50
|
+
# The currency unit and number formatting of the current locale will be used
|
51
|
+
# unless otherwise specified in the provided options. No currency conversion
|
52
|
+
# is performed. If the user is given a way to change their locale, they will
|
53
|
+
# also be able to change the relative value of the currency displayed with
|
54
|
+
# this helper. If your application will ever support multiple locales, you
|
55
|
+
# may want to specify a constant <tt>:locale</tt> option or consider
|
56
|
+
# using a library capable of currency conversion.
|
57
|
+
#
|
50
58
|
# ==== Options
|
51
59
|
#
|
52
60
|
# * <tt>:locale</tt> - Sets the locale to be used for formatting
|
@@ -235,6 +243,8 @@ module ActiveSupport
|
|
235
243
|
# number_to_human_size(1234567) # => 1.18 MB
|
236
244
|
# number_to_human_size(1234567890) # => 1.15 GB
|
237
245
|
# number_to_human_size(1234567890123) # => 1.12 TB
|
246
|
+
# number_to_human_size(1234567890123456) # => 1.1 PB
|
247
|
+
# number_to_human_size(1234567890123456789) # => 1.07 EB
|
238
248
|
# number_to_human_size(1234567, precision: 2) # => 1.2 MB
|
239
249
|
# number_to_human_size(483989, precision: 2) # => 470 KB
|
240
250
|
# number_to_human_size(1234567, precision: 2, separator: ',') # => 1,2 MB
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_support/core_ext/numeric/inquiry'
|
2
|
+
|
1
3
|
module ActiveSupport
|
2
4
|
module NumberHelper
|
3
5
|
class NumberToCurrencyConverter < NumberConverter # :nodoc:
|
@@ -7,7 +9,7 @@ module ActiveSupport
|
|
7
9
|
number = self.number.to_s.strip
|
8
10
|
format = options[:format]
|
9
11
|
|
10
|
-
if
|
12
|
+
if number.to_f.negative?
|
11
13
|
format = options[:negative_format]
|
12
14
|
number = absolute_value(number)
|
13
15
|
end
|
@@ -18,10 +20,6 @@ module ActiveSupport
|
|
18
20
|
|
19
21
|
private
|
20
22
|
|
21
|
-
def is_negative?(number)
|
22
|
-
number.to_f.phase != 0
|
23
|
-
end
|
24
|
-
|
25
23
|
def absolute_value(number)
|
26
24
|
number.respond_to?(:abs) ? number.abs : number.sub(/\A-/, '')
|
27
25
|
end
|
@@ -5,7 +5,7 @@ YAML.add_builtin_type("omap") do |type, val|
|
|
5
5
|
end
|
6
6
|
|
7
7
|
module ActiveSupport
|
8
|
-
# <tt>ActiveSupport::OrderedHash</tt> implements a hash that preserves
|
8
|
+
# DEPRECATED: <tt>ActiveSupport::OrderedHash</tt> implements a hash that preserves
|
9
9
|
# insertion order.
|
10
10
|
#
|
11
11
|
# oh = ActiveSupport::OrderedHash.new
|
@@ -9,7 +9,6 @@ require 'active_support/testing/isolation'
|
|
9
9
|
require 'active_support/testing/constant_lookup'
|
10
10
|
require 'active_support/testing/time_helpers'
|
11
11
|
require 'active_support/testing/file_fixtures'
|
12
|
-
require 'active_support/testing/composite_filter'
|
13
12
|
require 'active_support/core_ext/kernel/reporting'
|
14
13
|
|
15
14
|
module ActiveSupport
|
@@ -39,15 +38,6 @@ module ActiveSupport
|
|
39
38
|
def test_order
|
40
39
|
ActiveSupport.test_order ||= :random
|
41
40
|
end
|
42
|
-
|
43
|
-
def run(reporter, options = {})
|
44
|
-
if options[:patterns] && options[:patterns].any? { |p| p =~ /:\d+/ }
|
45
|
-
options[:filter] = \
|
46
|
-
Testing::CompositeFilter.new(self, options[:filter], options[:patterns])
|
47
|
-
end
|
48
|
-
|
49
|
-
super
|
50
|
-
end
|
51
41
|
end
|
52
42
|
|
53
43
|
alias_method :method_name, :name
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activesupport
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.0.0.
|
4
|
+
version: 5.0.0.beta2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-01
|
11
|
+
date: 2016-02-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: i18n
|
@@ -312,7 +312,6 @@ files:
|
|
312
312
|
- lib/active_support/test_case.rb
|
313
313
|
- lib/active_support/testing/assertions.rb
|
314
314
|
- lib/active_support/testing/autorun.rb
|
315
|
-
- lib/active_support/testing/composite_filter.rb
|
316
315
|
- lib/active_support/testing/constant_lookup.rb
|
317
316
|
- lib/active_support/testing/declarative.rb
|
318
317
|
- lib/active_support/testing/deprecation.rb
|
@@ -357,9 +356,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
357
356
|
version: 1.3.1
|
358
357
|
requirements: []
|
359
358
|
rubyforge_project:
|
360
|
-
rubygems_version: 2.5.
|
359
|
+
rubygems_version: 2.5.2
|
361
360
|
signing_key:
|
362
361
|
specification_version: 4
|
363
362
|
summary: A toolkit of support libraries and Ruby core extensions extracted from the
|
364
363
|
Rails framework.
|
365
364
|
test_files: []
|
365
|
+
has_rdoc:
|
@@ -1,54 +0,0 @@
|
|
1
|
-
require 'method_source'
|
2
|
-
|
3
|
-
module ActiveSupport
|
4
|
-
module Testing
|
5
|
-
class CompositeFilter # :nodoc:
|
6
|
-
def initialize(runnable, filter, patterns)
|
7
|
-
@runnable = runnable
|
8
|
-
@filters = [ derive_regexp(filter), *derive_line_filters(patterns) ].compact
|
9
|
-
end
|
10
|
-
|
11
|
-
def ===(method)
|
12
|
-
@filters.any? { |filter| filter === method }
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
16
|
-
def derive_regexp(filter)
|
17
|
-
filter =~ %r%/(.*)/% ? Regexp.new($1) : filter
|
18
|
-
end
|
19
|
-
|
20
|
-
def derive_line_filters(patterns)
|
21
|
-
patterns.map do |file_and_line|
|
22
|
-
file, line = file_and_line.split(':')
|
23
|
-
Filter.new(@runnable, file, line) if file
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
class Filter # :nodoc:
|
28
|
-
def initialize(runnable, file, line)
|
29
|
-
@runnable, @file = runnable, File.expand_path(file)
|
30
|
-
@line = line.to_i if line
|
31
|
-
end
|
32
|
-
|
33
|
-
def ===(method)
|
34
|
-
return unless @runnable.method_defined?(method)
|
35
|
-
|
36
|
-
if @line
|
37
|
-
test_file, test_range = definition_for(@runnable.instance_method(method))
|
38
|
-
test_file == @file && test_range.include?(@line)
|
39
|
-
else
|
40
|
-
@runnable.instance_method(method).source_location.first == @file
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
private
|
45
|
-
def definition_for(method)
|
46
|
-
file, start_line = method.source_location
|
47
|
-
end_line = method.source.count("\n") + start_line - 1
|
48
|
-
|
49
|
-
return file, start_line..end_line
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|