activesupport 4.0.0.beta1 → 4.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +47 -0
- data/README.rdoc +2 -2
- data/lib/active_support/cache.rb +62 -49
- data/lib/active_support/cache/file_store.rb +2 -2
- data/lib/active_support/cache/strategy/local_cache.rb +48 -37
- data/lib/active_support/callbacks.rb +27 -8
- data/lib/active_support/core_ext.rb +2 -2
- data/lib/active_support/core_ext/array/conversions.rb +5 -3
- data/lib/active_support/core_ext/array/uniq_by.rb +2 -2
- data/lib/active_support/core_ext/benchmark.rb +7 -0
- data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -0
- data/lib/active_support/core_ext/class/attribute.rb +31 -27
- data/lib/active_support/core_ext/class/attribute_accessors.rb +2 -2
- data/lib/active_support/core_ext/date_and_time/calculations.rb +6 -6
- data/lib/active_support/core_ext/module/delegation.rb +50 -24
- data/lib/active_support/core_ext/module/deprecation.rb +2 -2
- data/lib/active_support/core_ext/string.rb +0 -1
- data/lib/active_support/core_ext/string/conversions.rb +6 -8
- data/lib/active_support/core_ext/string/filters.rb +1 -1
- data/lib/active_support/core_ext/string/indent.rb +1 -1
- data/lib/active_support/core_ext/string/inflections.rb +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +2 -2
- data/lib/active_support/hash_with_indifferent_access.rb +2 -2
- data/lib/active_support/key_generator.rb +1 -1
- data/lib/active_support/log_subscriber.rb +9 -46
- data/lib/active_support/message_encryptor.rb +9 -9
- data/lib/active_support/message_verifier.rb +3 -3
- data/lib/active_support/notifications.rb +22 -1
- data/lib/active_support/notifications/instrumenter.rb +2 -2
- data/lib/active_support/number_helper.rb +3 -2
- data/lib/active_support/per_thread_registry.rb +52 -0
- data/lib/active_support/subscriber.rb +93 -0
- data/lib/active_support/testing/constant_lookup.rb +2 -0
- data/lib/active_support/time_with_zone.rb +2 -0
- data/lib/active_support/values/time_zone.rb +5 -3
- data/lib/active_support/version.rb +7 -6
- data/lib/active_support/xml_mini/jdom.rb +6 -0
- data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
- data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
- metadata +14 -7
- data/lib/active_support/core_ext/string/xchar.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 787831cae30c98f2e6f3e06b1ac405a5c5597861
|
4
|
+
data.tar.gz: 34441857e5037fdaa192293f732de973fa362f22
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2af16317b996dfcdef387e1e8c68fc488b80d85329339c71f640faf69212fb308b2f24723a6134911eddc9358bf87a194363f7bab0997d05ec574ec8345b645e
|
7
|
+
data.tar.gz: c5ea3235e50432543c82825c40e44d34e765d7bb94c5c3b586a179b015f21df62c8fc18458cdb2a63430a6a66db8f72eb58ca68c72000527462241059cf5c2ca
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,52 @@
|
|
1
|
+
## Rails 4.0.0 (unreleased) ##
|
2
|
+
|
3
|
+
* Fix skipping of filters defined by objects in `ActiveSupport::Callbacks::Callback`.
|
4
|
+
|
5
|
+
*Ben McRedmond*
|
6
|
+
|
7
|
+
* An `ActiveSupport::Subscriber` class has been extracted from
|
8
|
+
`ActiveSupport::LogSubscriber`, allowing you to use the event attachment
|
9
|
+
API for other kinds of subscribers.
|
10
|
+
|
11
|
+
*Daniel Schierbeck*
|
12
|
+
|
13
|
+
* `Class#class_attribute` accepts an `instance_predicate` option which
|
14
|
+
defaults to `true`. If set to `false` the predicate method will not
|
15
|
+
be defined.
|
16
|
+
|
17
|
+
*Agis Anastasopoulos*
|
18
|
+
|
19
|
+
* `fast_xs` support has been removed. Use `String#encode(xml: :attr)`.
|
20
|
+
|
21
|
+
* `ActiveSupport::Notifications::Instrumenter#instrument` should
|
22
|
+
yield its payload.
|
23
|
+
|
24
|
+
*stopdropandrew*
|
25
|
+
|
26
|
+
* `ActiveSupport::TimeWithZone` raises `NoMethodError` in proper context.
|
27
|
+
Fixes #9772.
|
28
|
+
|
29
|
+
*Yves Senn*
|
30
|
+
|
31
|
+
* Fix deletion of empty directories in `ActiveSupport::Cache::FileStore`.
|
32
|
+
|
33
|
+
*Charles Jones*
|
34
|
+
|
1
35
|
## Rails 4.0.0.beta1 (February 25, 2013) ##
|
2
36
|
|
37
|
+
* Improve singularizing a singular for multiple cases.
|
38
|
+
Fixes #2608 #1825 #2395.
|
39
|
+
|
40
|
+
Example:
|
41
|
+
|
42
|
+
# Before
|
43
|
+
'address'.singularize # => 'addres'
|
44
|
+
|
45
|
+
# After
|
46
|
+
'address'.singularize # => 'address'
|
47
|
+
|
48
|
+
*Mark McSpadden*
|
49
|
+
|
3
50
|
* Prevent `DateTime#change` from truncating the second fraction, when seconds
|
4
51
|
do not need to be changed.
|
5
52
|
|
data/README.rdoc
CHANGED
@@ -12,7 +12,7 @@ The latest version of Active Support can be installed with RubyGems:
|
|
12
12
|
|
13
13
|
% [sudo] gem install activesupport
|
14
14
|
|
15
|
-
Source code can be downloaded as part of the Rails project on GitHub
|
15
|
+
Source code can be downloaded as part of the Rails project on GitHub:
|
16
16
|
|
17
17
|
* https://github.com/rails/rails/tree/master/activesupport
|
18
18
|
|
@@ -26,7 +26,7 @@ Active Support is released under the MIT license:
|
|
26
26
|
|
27
27
|
== Support
|
28
28
|
|
29
|
-
API documentation is at
|
29
|
+
API documentation is at:
|
30
30
|
|
31
31
|
* http://api.rubyonrails.org
|
32
32
|
|
data/lib/active_support/cache.rb
CHANGED
@@ -56,16 +56,7 @@ module ActiveSupport
|
|
56
56
|
|
57
57
|
case store
|
58
58
|
when Symbol
|
59
|
-
|
60
|
-
store_class =
|
61
|
-
begin
|
62
|
-
require "active_support/cache/#{store}"
|
63
|
-
rescue LoadError => e
|
64
|
-
raise "Could not find cache store adapter for #{store} (#{e})"
|
65
|
-
else
|
66
|
-
ActiveSupport::Cache.const_get(store_class_name)
|
67
|
-
end
|
68
|
-
store_class.new(*parameters)
|
59
|
+
retrieve_store_class(store).new(*parameters)
|
69
60
|
when nil
|
70
61
|
ActiveSupport::Cache::MemoryStore.new
|
71
62
|
else
|
@@ -73,6 +64,18 @@ module ActiveSupport
|
|
73
64
|
end
|
74
65
|
end
|
75
66
|
|
67
|
+
# Expands out the +key+ argument into a key that can be used for the
|
68
|
+
# cache store. Optionally accepts a namespace, and all keys will be
|
69
|
+
# scoped within that namespace.
|
70
|
+
#
|
71
|
+
# If the +key+ argument provided is an array, or responds to +to_a+, then
|
72
|
+
# each of elements in the array will be turned into parameters/keys and
|
73
|
+
# concatenated into a single key. For example:
|
74
|
+
#
|
75
|
+
# expand_cache_key([:foo, :bar]) # => "foo/bar"
|
76
|
+
# expand_cache_key([:foo, :bar], "namespace") # => "namespace/foo/bar"
|
77
|
+
#
|
78
|
+
# The +key+ argument can also respond to +cache_key+ or +to_param+.
|
76
79
|
def expand_cache_key(key, namespace = nil)
|
77
80
|
expanded_cache_key = namespace ? "#{namespace}/" : ""
|
78
81
|
|
@@ -94,6 +97,16 @@ module ActiveSupport
|
|
94
97
|
else key.to_param
|
95
98
|
end.to_s
|
96
99
|
end
|
100
|
+
|
101
|
+
# Obtains the specified cache store class, given the name of the +store+.
|
102
|
+
# Raises an error when the store class cannot be found.
|
103
|
+
def retrieve_store_class(store)
|
104
|
+
require "active_support/cache/#{store}"
|
105
|
+
rescue LoadError => e
|
106
|
+
raise "Could not find cache store adapter for #{store} (#{e})"
|
107
|
+
else
|
108
|
+
ActiveSupport::Cache.const_get(store.to_s.camelize)
|
109
|
+
end
|
97
110
|
end
|
98
111
|
|
99
112
|
# An abstract cache store class. There are multiple cache store
|
@@ -344,7 +357,7 @@ module ActiveSupport
|
|
344
357
|
# Options are passed to the underlying cache implementation.
|
345
358
|
def write(name, value, options = nil)
|
346
359
|
options = merged_options(options)
|
347
|
-
instrument(:write, name, options) do
|
360
|
+
instrument(:write, name, options) do
|
348
361
|
entry = Entry.new(value, options)
|
349
362
|
write_entry(namespaced_key(name, options), entry, options)
|
350
363
|
end
|
@@ -355,7 +368,7 @@ module ActiveSupport
|
|
355
368
|
# Options are passed to the underlying cache implementation.
|
356
369
|
def delete(name, options = nil)
|
357
370
|
options = merged_options(options)
|
358
|
-
instrument(:delete, name) do
|
371
|
+
instrument(:delete, name) do
|
359
372
|
delete_entry(namespaced_key(name, options), options)
|
360
373
|
end
|
361
374
|
end
|
@@ -365,7 +378,7 @@ module ActiveSupport
|
|
365
378
|
# Options are passed to the underlying cache implementation.
|
366
379
|
def exist?(name, options = nil)
|
367
380
|
options = merged_options(options)
|
368
|
-
instrument(:exist?, name) do
|
381
|
+
instrument(:exist?, name) do
|
369
382
|
entry = read_entry(namespaced_key(name, options), options)
|
370
383
|
entry && !entry.expired?
|
371
384
|
end
|
@@ -522,7 +535,7 @@ module ActiveSupport
|
|
522
535
|
def handle_expired_entry(entry, key, options)
|
523
536
|
if entry && entry.expired?
|
524
537
|
race_ttl = options[:race_condition_ttl].to_i
|
525
|
-
if race_ttl && (Time.now - entry.expires_at <= race_ttl)
|
538
|
+
if race_ttl && (Time.now.to_f - entry.expires_at <= race_ttl)
|
526
539
|
# When an entry has :race_condition_ttl defined, put the stale entry back into the cache
|
527
540
|
# for a brief period while the entry is begin recalculated.
|
528
541
|
entry.expires_at = Time.now + race_ttl
|
@@ -562,38 +575,38 @@ module ActiveSupport
|
|
562
575
|
# +:compress+, +:compress_threshold+, and +:expires_in+.
|
563
576
|
def initialize(value, options = {})
|
564
577
|
if should_compress?(value, options)
|
565
|
-
@
|
566
|
-
@
|
578
|
+
@value = compress(value)
|
579
|
+
@compressed = true
|
567
580
|
else
|
568
|
-
@
|
569
|
-
end
|
570
|
-
if expires_in = options[:expires_in]
|
571
|
-
@x = (Time.now + expires_in).to_i
|
581
|
+
@value = value
|
572
582
|
end
|
583
|
+
@created_at = Time.now.to_f
|
584
|
+
@expires_in = options[:expires_in]
|
585
|
+
@expires_in = @expires_in.to_f if @expires_in
|
573
586
|
end
|
574
587
|
|
575
588
|
def value
|
576
|
-
|
577
|
-
compressed? ? uncompress(@
|
589
|
+
convert_version_4beta1_entry! if defined?(@v)
|
590
|
+
compressed? ? uncompress(@value) : @value
|
578
591
|
end
|
579
592
|
|
580
593
|
# Check if the entry is expired. The +expires_in+ parameter can override
|
581
594
|
# the value set when the entry was created.
|
582
595
|
def expired?
|
583
|
-
|
584
|
-
|
585
|
-
@x && @x < Time.now.to_i
|
586
|
-
else
|
587
|
-
false
|
588
|
-
end
|
596
|
+
convert_version_4beta1_entry! if defined?(@value)
|
597
|
+
@expires_in && @created_at + @expires_in <= Time.now.to_f
|
589
598
|
end
|
590
599
|
|
591
600
|
def expires_at
|
592
|
-
|
601
|
+
@expires_in ? @created_at + @expires_in : nil
|
593
602
|
end
|
594
603
|
|
595
604
|
def expires_at=(value)
|
596
|
-
|
605
|
+
if value
|
606
|
+
@expires_in = value.to_f - @created_at
|
607
|
+
else
|
608
|
+
@expires_in = nil
|
609
|
+
end
|
597
610
|
end
|
598
611
|
|
599
612
|
# Returns the size of the cached value. This could be less than
|
@@ -606,9 +619,9 @@ module ActiveSupport
|
|
606
619
|
when NilClass
|
607
620
|
0
|
608
621
|
when String
|
609
|
-
@
|
622
|
+
@value.bytesize
|
610
623
|
else
|
611
|
-
@s = Marshal.dump(@
|
624
|
+
@s = Marshal.dump(@value).bytesize
|
612
625
|
end
|
613
626
|
end
|
614
627
|
end
|
@@ -616,12 +629,12 @@ module ActiveSupport
|
|
616
629
|
# Duplicate the value in a class. This is used by cache implementations that don't natively
|
617
630
|
# serialize entries to protect against accidental cache modifications.
|
618
631
|
def dup_value!
|
619
|
-
|
620
|
-
if @
|
621
|
-
if @
|
622
|
-
@
|
632
|
+
convert_version_4beta1_entry! if defined?(@v)
|
633
|
+
if @value && !compressed? && !(@value.is_a?(Numeric) || @value == true || @value == false)
|
634
|
+
if @value.is_a?(String)
|
635
|
+
@value = @value.dup
|
623
636
|
else
|
624
|
-
@
|
637
|
+
@value = Marshal.load(Marshal.dump(@value))
|
625
638
|
end
|
626
639
|
end
|
627
640
|
end
|
@@ -637,7 +650,7 @@ module ActiveSupport
|
|
637
650
|
end
|
638
651
|
|
639
652
|
def compressed?
|
640
|
-
defined?(@
|
653
|
+
defined?(@compressed) ? @compressed : false
|
641
654
|
end
|
642
655
|
|
643
656
|
def compress(value)
|
@@ -650,19 +663,19 @@ module ActiveSupport
|
|
650
663
|
|
651
664
|
# The internals of this method changed between Rails 3.x and 4.0. This method provides the glue
|
652
665
|
# to ensure that cache entries created under the old version still work with the new class definition.
|
653
|
-
def
|
654
|
-
if defined?(@
|
655
|
-
@
|
656
|
-
remove_instance_variable(:@
|
666
|
+
def convert_version_4beta1_entry!
|
667
|
+
if defined?(@v)
|
668
|
+
@value = @v
|
669
|
+
remove_instance_variable(:@v)
|
657
670
|
end
|
658
|
-
if defined?(@
|
659
|
-
@
|
660
|
-
remove_instance_variable(:@
|
671
|
+
if defined?(@c)
|
672
|
+
@compressed = @c
|
673
|
+
remove_instance_variable(:@c)
|
661
674
|
end
|
662
|
-
if defined?(@
|
663
|
-
@
|
664
|
-
|
665
|
-
remove_instance_variable(:@
|
675
|
+
if defined?(@x) && @x
|
676
|
+
@created_at ||= Time.now.to_f
|
677
|
+
@expires_in = @x - @created_at
|
678
|
+
remove_instance_variable(:@x)
|
666
679
|
end
|
667
680
|
end
|
668
681
|
end
|
@@ -150,9 +150,9 @@ module ActiveSupport
|
|
150
150
|
|
151
151
|
# Delete empty directories in the cache.
|
152
152
|
def delete_empty_directories(dir)
|
153
|
-
return if dir == cache_path
|
153
|
+
return if File.realpath(dir) == File.realpath(cache_path)
|
154
154
|
if Dir.entries(dir).reject {|f| EXCLUDED_DIRS.include?(f)}.empty?
|
155
|
-
|
155
|
+
Dir.delete(dir) rescue nil
|
156
156
|
delete_empty_directories(File.dirname(dir))
|
157
157
|
end
|
158
158
|
end
|
@@ -8,6 +8,23 @@ module ActiveSupport
|
|
8
8
|
# duration of a block. Repeated calls to the cache for the same key will hit the
|
9
9
|
# in-memory cache for faster access.
|
10
10
|
module LocalCache
|
11
|
+
# Class for storing and registering the local caches.
|
12
|
+
class LocalCacheRegistry # :nodoc:
|
13
|
+
extend ActiveSupport::PerThreadRegistry
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@registry = {}
|
17
|
+
end
|
18
|
+
|
19
|
+
def cache_for(local_cache_key)
|
20
|
+
@registry[local_cache_key]
|
21
|
+
end
|
22
|
+
|
23
|
+
def set_cache_for(local_cache_key, value)
|
24
|
+
@registry[local_cache_key] = value
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
11
28
|
# Simple memory backed cache. This cache is not thread safe and is intended only
|
12
29
|
# for serving as a temporary memory cache for a single thread.
|
13
30
|
class LocalStore < Store
|
@@ -41,24 +58,18 @@ module ActiveSupport
|
|
41
58
|
|
42
59
|
# Use a local cache for the duration of block.
|
43
60
|
def with_local_cache
|
44
|
-
|
45
|
-
begin
|
46
|
-
Thread.current[thread_local_key] = LocalStore.new
|
47
|
-
yield
|
48
|
-
ensure
|
49
|
-
Thread.current[thread_local_key] = save_val
|
50
|
-
end
|
61
|
+
use_temporary_local_cache(LocalStore.new) { yield }
|
51
62
|
end
|
52
63
|
|
53
64
|
#--
|
54
65
|
# This class wraps up local storage for middlewares. Only the middleware method should
|
55
66
|
# construct them.
|
56
67
|
class Middleware # :nodoc:
|
57
|
-
attr_reader :name, :
|
68
|
+
attr_reader :name, :local_cache_key
|
58
69
|
|
59
|
-
def initialize(name,
|
70
|
+
def initialize(name, local_cache_key)
|
60
71
|
@name = name
|
61
|
-
@
|
72
|
+
@local_cache_key = local_cache_key
|
62
73
|
@app = nil
|
63
74
|
end
|
64
75
|
|
@@ -68,10 +79,10 @@ module ActiveSupport
|
|
68
79
|
end
|
69
80
|
|
70
81
|
def call(env)
|
71
|
-
|
82
|
+
LocalCacheRegistry.set_cache_for(local_cache_key, LocalStore.new)
|
72
83
|
@app.call(env)
|
73
84
|
ensure
|
74
|
-
|
85
|
+
LocalCacheRegistry.set_cache_for(local_cache_key, nil)
|
75
86
|
end
|
76
87
|
end
|
77
88
|
|
@@ -80,7 +91,7 @@ module ActiveSupport
|
|
80
91
|
def middleware
|
81
92
|
@middleware ||= Middleware.new(
|
82
93
|
"ActiveSupport::Cache::Strategy::LocalCache",
|
83
|
-
|
94
|
+
local_cache_key)
|
84
95
|
end
|
85
96
|
|
86
97
|
def clear(options = nil) # :nodoc:
|
@@ -95,29 +106,13 @@ module ActiveSupport
|
|
95
106
|
|
96
107
|
def increment(name, amount = 1, options = nil) # :nodoc:
|
97
108
|
value = bypass_local_cache{super}
|
98
|
-
|
99
|
-
local_cache.mute do
|
100
|
-
if value
|
101
|
-
local_cache.write(name, value, options)
|
102
|
-
else
|
103
|
-
local_cache.delete(name, options)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
109
|
+
increment_or_decrement(value, name, amount, options)
|
107
110
|
value
|
108
111
|
end
|
109
112
|
|
110
113
|
def decrement(name, amount = 1, options = nil) # :nodoc:
|
111
114
|
value = bypass_local_cache{super}
|
112
|
-
|
113
|
-
local_cache.mute do
|
114
|
-
if value
|
115
|
-
local_cache.write(name, value, options)
|
116
|
-
else
|
117
|
-
local_cache.delete(name, options)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
115
|
+
increment_or_decrement(value, name, amount, options)
|
121
116
|
value
|
122
117
|
end
|
123
118
|
|
@@ -146,21 +141,37 @@ module ActiveSupport
|
|
146
141
|
end
|
147
142
|
|
148
143
|
private
|
149
|
-
def
|
150
|
-
|
144
|
+
def increment_or_decrement(value, name, amount, options)
|
145
|
+
if local_cache
|
146
|
+
local_cache.mute do
|
147
|
+
if value
|
148
|
+
local_cache.write(name, value, options)
|
149
|
+
else
|
150
|
+
local_cache.delete(name, options)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def local_cache_key
|
157
|
+
@local_cache_key ||= "#{self.class.name.underscore}_local_cache_#{object_id}".gsub(/[\/-]/, '_').to_sym
|
151
158
|
end
|
152
159
|
|
153
160
|
def local_cache
|
154
|
-
|
161
|
+
LocalCacheRegistry.cache_for(local_cache_key)
|
155
162
|
end
|
156
163
|
|
157
164
|
def bypass_local_cache
|
158
|
-
|
165
|
+
use_temporary_local_cache(nil) { yield }
|
166
|
+
end
|
167
|
+
|
168
|
+
def use_temporary_local_cache(temporary_cache)
|
169
|
+
save_cache = LocalCacheRegistry.cache_for(local_cache_key)
|
159
170
|
begin
|
160
|
-
|
171
|
+
LocalCacheRegistry.set_cache_for(local_cache_key, temporary_cache)
|
161
172
|
yield
|
162
173
|
ensure
|
163
|
-
|
174
|
+
LocalCacheRegistry.set_cache_for(local_cache_key, save_cache)
|
164
175
|
end
|
165
176
|
end
|
166
177
|
end
|