activesupport 2.2.3 → 2.3.2

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.

Files changed (94) hide show
  1. data/CHANGELOG +128 -89
  2. data/lib/active_support.rb +31 -33
  3. data/lib/active_support/backtrace_cleaner.rb +72 -0
  4. data/lib/active_support/buffered_logger.rb +9 -7
  5. data/lib/active_support/cache.rb +13 -8
  6. data/lib/active_support/cache/drb_store.rb +2 -3
  7. data/lib/active_support/cache/mem_cache_store.rb +6 -1
  8. data/lib/active_support/cache/strategy/local_cache.rb +104 -0
  9. data/lib/active_support/callbacks.rb +20 -21
  10. data/lib/active_support/core_ext.rb +1 -1
  11. data/lib/active_support/core_ext/array.rb +2 -0
  12. data/lib/active_support/core_ext/array/conversions.rb +26 -13
  13. data/lib/active_support/core_ext/array/wrapper.rb +24 -0
  14. data/lib/active_support/core_ext/benchmark.rb +13 -6
  15. data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +14 -5
  16. data/lib/active_support/core_ext/class/attribute_accessors.rb +24 -24
  17. data/lib/active_support/core_ext/class/delegating_attributes.rb +20 -19
  18. data/lib/active_support/core_ext/class/inheritable_attributes.rb +34 -34
  19. data/lib/active_support/core_ext/date/conversions.rb +3 -3
  20. data/lib/active_support/core_ext/date_time/conversions.rb +1 -1
  21. data/lib/active_support/core_ext/enumerable.rb +9 -0
  22. data/lib/active_support/core_ext/exception.rb +12 -8
  23. data/lib/active_support/core_ext/file/atomic.rb +2 -2
  24. data/lib/active_support/core_ext/hash/conversions.rb +32 -54
  25. data/lib/active_support/core_ext/hash/indifferent_access.rb +6 -0
  26. data/lib/active_support/core_ext/hash/keys.rb +1 -1
  27. data/lib/active_support/core_ext/hash/slice.rb +8 -1
  28. data/lib/active_support/core_ext/logger.rb +8 -6
  29. data/lib/active_support/core_ext/module/aliasing.rb +3 -3
  30. data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +4 -4
  31. data/lib/active_support/core_ext/module/attribute_accessors.rb +24 -24
  32. data/lib/active_support/core_ext/module/delegation.rb +29 -3
  33. data/lib/active_support/core_ext/module/synchronization.rb +5 -5
  34. data/lib/active_support/core_ext/object/conversions.rb +2 -1
  35. data/lib/active_support/core_ext/object/misc.rb +16 -0
  36. data/lib/active_support/core_ext/range/conversions.rb +1 -1
  37. data/lib/active_support/core_ext/rexml.rb +29 -24
  38. data/lib/active_support/core_ext/string/inflections.rb +3 -3
  39. data/lib/active_support/core_ext/time/calculations.rb +1 -2
  40. data/lib/active_support/core_ext/time/conversions.rb +1 -1
  41. data/lib/active_support/core_ext/try.rb +36 -0
  42. data/lib/active_support/dependencies.rb +18 -14
  43. data/lib/active_support/deprecation.rb +10 -57
  44. data/lib/active_support/duration.rb +3 -1
  45. data/lib/active_support/inflections.rb +1 -0
  46. data/lib/active_support/inflector.rb +16 -7
  47. data/lib/active_support/json/decoding.rb +21 -3
  48. data/lib/active_support/json/encoders/date.rb +1 -1
  49. data/lib/active_support/json/encoders/date_time.rb +1 -1
  50. data/lib/active_support/json/encoders/hash.rb +10 -11
  51. data/lib/active_support/json/encoders/time.rb +1 -1
  52. data/lib/active_support/json/encoding.rb +23 -29
  53. data/lib/active_support/locale/en.yml +3 -2
  54. data/lib/active_support/memoizable.rb +61 -43
  55. data/lib/active_support/message_encryptor.rb +70 -0
  56. data/lib/active_support/message_verifier.rb +46 -0
  57. data/lib/active_support/multibyte.rb +6 -30
  58. data/lib/active_support/multibyte/chars.rb +30 -9
  59. data/lib/active_support/multibyte/unicode_database.rb +4 -4
  60. data/lib/active_support/option_merger.rb +7 -1
  61. data/lib/active_support/ordered_hash.rb +75 -27
  62. data/lib/active_support/secure_random.rb +8 -6
  63. data/lib/active_support/test_case.rb +32 -17
  64. data/lib/active_support/testing/{core_ext/test/unit/assertions.rb → assertions.rb} +13 -20
  65. data/lib/active_support/testing/declarative.rb +21 -0
  66. data/lib/active_support/testing/deprecation.rb +55 -0
  67. data/lib/active_support/testing/performance.rb +1 -1
  68. data/lib/active_support/testing/setup_and_teardown.rb +57 -86
  69. data/lib/active_support/time_with_zone.rb +8 -6
  70. data/lib/active_support/values/time_zone.rb +1 -0
  71. data/lib/active_support/vendor.rb +6 -11
  72. data/lib/active_support/vendor/i18n-0.1.3/MIT-LICENSE +20 -0
  73. data/lib/active_support/vendor/i18n-0.1.3/README.textile +20 -0
  74. data/lib/active_support/vendor/i18n-0.1.3/Rakefile +5 -0
  75. data/lib/active_support/vendor/i18n-0.1.3/i18n.gemspec +27 -0
  76. data/lib/active_support/vendor/{i18n-0.0.1 → i18n-0.1.3/lib}/i18n.rb +42 -37
  77. data/lib/active_support/vendor/{i18n-0.0.1 → i18n-0.1.3/lib}/i18n/backend/simple.rb +37 -39
  78. data/lib/active_support/vendor/{i18n-0.0.1 → i18n-0.1.3/lib}/i18n/exceptions.rb +3 -3
  79. data/lib/active_support/vendor/i18n-0.1.3/test/all.rb +5 -0
  80. data/lib/active_support/vendor/i18n-0.1.3/test/i18n_exceptions_test.rb +100 -0
  81. data/lib/active_support/vendor/i18n-0.1.3/test/i18n_test.rb +125 -0
  82. data/lib/active_support/vendor/i18n-0.1.3/test/locale/en.rb +1 -0
  83. data/lib/active_support/vendor/i18n-0.1.3/test/locale/en.yml +3 -0
  84. data/lib/active_support/vendor/i18n-0.1.3/test/simple_backend_test.rb +568 -0
  85. data/lib/active_support/vendor/{memcache-client-1.5.1 → memcache-client-1.6.5}/memcache.rb +381 -295
  86. data/lib/active_support/version.rb +2 -2
  87. data/lib/active_support/xml_mini.rb +31 -0
  88. data/lib/active_support/xml_mini/libxml.rb +133 -0
  89. data/lib/active_support/xml_mini/nokogiri.rb +77 -0
  90. data/lib/active_support/xml_mini/rexml.rb +108 -0
  91. metadata +85 -14
  92. data/lib/active_support/multibyte/utils.rb +0 -61
  93. data/lib/active_support/testing/core_ext/test.rb +0 -6
  94. data/lib/active_support/vendor/xml-simple-1.0.11/xmlsimple.rb +0 -1021
@@ -21,41 +21,39 @@
21
21
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  #++
23
23
 
24
- require 'active_support/vendor'
25
- require 'active_support/basic_object'
26
- require 'active_support/inflector'
27
- require 'active_support/callbacks'
24
+ module ActiveSupport
25
+ def self.load_all!
26
+ [Dependencies, Deprecation, Gzip, MessageVerifier, Multibyte, SecureRandom, TimeWithZone]
27
+ end
28
+
29
+ autoload :BacktraceCleaner, 'active_support/backtrace_cleaner'
30
+ autoload :Base64, 'active_support/base64'
31
+ autoload :BasicObject, 'active_support/basic_object'
32
+ autoload :BufferedLogger, 'active_support/buffered_logger'
33
+ autoload :Cache, 'active_support/cache'
34
+ autoload :Callbacks, 'active_support/callbacks'
35
+ autoload :Deprecation, 'active_support/deprecation'
36
+ autoload :Duration, 'active_support/duration'
37
+ autoload :Gzip, 'active_support/gzip'
38
+ autoload :Inflector, 'active_support/inflector'
39
+ autoload :Memoizable, 'active_support/memoizable'
40
+ autoload :MessageEncryptor, 'active_support/message_encryptor'
41
+ autoload :MessageVerifier, 'active_support/message_verifier'
42
+ autoload :Multibyte, 'active_support/multibyte'
43
+ autoload :OptionMerger, 'active_support/option_merger'
44
+ autoload :OrderedHash, 'active_support/ordered_hash'
45
+ autoload :OrderedOptions, 'active_support/ordered_options'
46
+ autoload :Rescuable, 'active_support/rescuable'
47
+ autoload :SecureRandom, 'active_support/secure_random'
48
+ autoload :StringInquirer, 'active_support/string_inquirer'
49
+ autoload :TimeWithZone, 'active_support/time_with_zone'
50
+ autoload :TimeZone, 'active_support/values/time_zone'
51
+ autoload :XmlMini, 'active_support/xml_mini'
52
+ end
28
53
 
54
+ require 'active_support/vendor'
29
55
  require 'active_support/core_ext'
30
-
31
- require 'active_support/buffered_logger'
32
-
33
- require 'active_support/gzip'
34
- require 'active_support/cache'
35
-
36
56
  require 'active_support/dependencies'
37
- require 'active_support/deprecation'
38
-
39
- require 'active_support/ordered_hash'
40
- require 'active_support/ordered_options'
41
- require 'active_support/option_merger'
42
-
43
- require 'active_support/memoizable'
44
- require 'active_support/string_inquirer'
45
-
46
- require 'active_support/values/time_zone'
47
- require 'active_support/duration'
48
-
49
57
  require 'active_support/json'
50
58
 
51
- require 'active_support/multibyte'
52
-
53
- require 'active_support/base64'
54
-
55
- require 'active_support/time_with_zone'
56
-
57
- require 'active_support/secure_random'
58
-
59
- require 'active_support/rescuable'
60
-
61
- I18n.load_path << File.dirname(__FILE__) + '/active_support/locale/en.yml'
59
+ I18n.load_path << "#{File.dirname(__FILE__)}/active_support/locale/en.yml"
@@ -0,0 +1,72 @@
1
+ module ActiveSupport
2
+ # Many backtraces include too much information that's not relevant for the context. This makes it hard to find the signal
3
+ # in the backtrace and adds debugging time. With a BacktraceCleaner, you can setup filters and silencers for your particular
4
+ # context, so only the relevant lines are included.
5
+ #
6
+ # If you need to reconfigure an existing BacktraceCleaner, like the one in Rails, to show as much as possible, you can always
7
+ # call BacktraceCleaner#remove_silencers!
8
+ #
9
+ # Example:
10
+ #
11
+ # bc = BacktraceCleaner.new
12
+ # bc.add_filter { |line| line.gsub(Rails.root, '') }
13
+ # bc.add_silencer { |line| line =~ /mongrel|rubygems/ }
14
+ # bc.clean(exception.backtrace) # will strip the Rails.root prefix and skip any lines from mongrel or rubygems
15
+ #
16
+ # Inspired by the Quiet Backtrace gem by Thoughtbot.
17
+ class BacktraceCleaner
18
+ def initialize
19
+ @filters, @silencers = [], []
20
+ end
21
+
22
+ # Returns the backtrace after all filters and silencers has been run against it. Filters run first, then silencers.
23
+ def clean(backtrace)
24
+ silence(filter(backtrace))
25
+ end
26
+
27
+ # Adds a filter from the block provided. Each line in the backtrace will be mapped against this filter.
28
+ #
29
+ # Example:
30
+ #
31
+ # # Will turn "/my/rails/root/app/models/person.rb" into "/app/models/person.rb"
32
+ # backtrace_cleaner.add_filter { |line| line.gsub(Rails.root, '') }
33
+ def add_filter(&block)
34
+ @filters << block
35
+ end
36
+
37
+ # Adds a silencer from the block provided. If the silencer returns true for a given line, it'll be excluded from the
38
+ # clean backtrace.
39
+ #
40
+ # Example:
41
+ #
42
+ # # Will reject all lines that include the word "mongrel", like "/gems/mongrel/server.rb" or "/app/my_mongrel_server/rb"
43
+ # backtrace_cleaner.add_silencer { |line| line =~ /mongrel/ }
44
+ def add_silencer(&block)
45
+ @silencers << block
46
+ end
47
+
48
+ # Will remove all silencers, but leave in the filters. This is useful if your context of debugging suddenly expands as
49
+ # you suspect a bug in the libraries you use.
50
+ def remove_silencers!
51
+ @silencers = []
52
+ end
53
+
54
+
55
+ private
56
+ def filter(backtrace)
57
+ @filters.each do |f|
58
+ backtrace = backtrace.map { |line| f.call(line) }
59
+ end
60
+
61
+ backtrace
62
+ end
63
+
64
+ def silence(backtrace)
65
+ @silencers.each do |s|
66
+ backtrace = backtrace.reject { |line| s.call(line) }
67
+ end
68
+
69
+ backtrace
70
+ end
71
+ end
72
+ end
@@ -13,6 +13,8 @@ module ActiveSupport
13
13
 
14
14
  MAX_BUFFER_SIZE = 1000
15
15
 
16
+ ##
17
+ # :singleton-method:
16
18
  # Set to false to disable the silencer
17
19
  cattr_accessor :silencer
18
20
  self.silencer = true
@@ -66,13 +68,13 @@ module ActiveSupport
66
68
 
67
69
  for severity in Severity.constants
68
70
  class_eval <<-EOT, __FILE__, __LINE__
69
- def #{severity.downcase}(message = nil, progname = nil, &block)
70
- add(#{severity}, message, progname, &block)
71
- end
72
-
73
- def #{severity.downcase}?
74
- #{severity} >= @level
75
- end
71
+ def #{severity.downcase}(message = nil, progname = nil, &block) # def debug(message = nil, progname = nil, &block)
72
+ add(#{severity}, message, progname, &block) # add(DEBUG, message, progname, &block)
73
+ end # end
74
+ #
75
+ def #{severity.downcase}? # def debug?
76
+ #{severity} >= @level # DEBUG >= @level
77
+ end # end
76
78
  EOT
77
79
  end
78
80
 
@@ -3,6 +3,17 @@ require 'benchmark'
3
3
  module ActiveSupport
4
4
  # See ActiveSupport::Cache::Store for documentation.
5
5
  module Cache
6
+ autoload :FileStore, 'active_support/cache/file_store'
7
+ autoload :MemoryStore, 'active_support/cache/memory_store'
8
+ autoload :SynchronizedMemoryStore, 'active_support/cache/synchronized_memory_store'
9
+ autoload :DRbStore, 'active_support/cache/drb_store'
10
+ autoload :MemCacheStore, 'active_support/cache/mem_cache_store'
11
+ autoload :CompressedMemCacheStore, 'active_support/cache/compressed_mem_cache_store'
12
+
13
+ module Strategy
14
+ autoload :LocalCache, 'active_support/cache/strategy/local_cache'
15
+ end
16
+
6
17
  # Creates a new CacheStore object according to the given options.
7
18
  #
8
19
  # If no arguments are passed to this method, then a new
@@ -136,13 +147,13 @@ module ActiveSupport
136
147
  log("miss", key, options)
137
148
 
138
149
  value = nil
139
- seconds = Benchmark.realtime { value = yield }
150
+ ms = Benchmark.ms { value = yield }
140
151
 
141
152
  @logger_off = true
142
153
  write(key, value, options)
143
154
  @logger_off = false
144
155
 
145
- log("write (will save #{'%.2f' % (seconds * 1000)}ms)", key, nil)
156
+ log('write (will save %.2fms)' % ms, key, nil)
146
157
 
147
158
  value
148
159
  end
@@ -215,9 +226,3 @@ module ActiveSupport
215
226
  end
216
227
  end
217
228
  end
218
-
219
- require 'active_support/cache/file_store'
220
- require 'active_support/cache/memory_store'
221
- require 'active_support/cache/drb_store'
222
- require 'active_support/cache/mem_cache_store'
223
- require 'active_support/cache/compressed_mem_cache_store'
@@ -1,15 +1,14 @@
1
- require 'drb'
2
-
3
1
  module ActiveSupport
4
2
  module Cache
5
3
  class DRbStore < MemoryStore #:nodoc:
6
4
  attr_reader :address
7
5
 
8
6
  def initialize(address = 'druby://localhost:9192')
7
+ require 'drb' unless defined?(DRbObject)
9
8
  super()
10
9
  @address = address
11
10
  @data = DRbObject.new(nil, address)
12
11
  end
13
12
  end
14
13
  end
15
- end
14
+ end
@@ -13,6 +13,7 @@ module ActiveSupport
13
13
  # server goes down, then MemCacheStore will ignore it until it goes back
14
14
  # online.
15
15
  # - Time-based expiry support. See #write and the +:expires_in+ option.
16
+ # - Per-request in memory cache for all communication with the MemCache server(s).
16
17
  class MemCacheStore < Store
17
18
  module Response # :nodoc:
18
19
  STORED = "STORED\r\n"
@@ -38,6 +39,8 @@ module ActiveSupport
38
39
  addresses = ["localhost"] if addresses.empty?
39
40
  @addresses = addresses
40
41
  @data = MemCache.new(addresses, options)
42
+
43
+ extend Strategy::LocalCache
41
44
  end
42
45
 
43
46
  def read(key, options = nil) # :nodoc:
@@ -80,6 +83,7 @@ module ActiveSupport
80
83
  def exist?(key, options = nil) # :nodoc:
81
84
  # Doesn't call super, cause exist? in memcache is in fact a read
82
85
  # But who cares? Reading is very fast anyway
86
+ # Local cache is checked first, if it doesn't know then memcache itself is read from
83
87
  !read(key, options).nil?
84
88
  end
85
89
 
@@ -94,7 +98,6 @@ module ActiveSupport
94
98
 
95
99
  def decrement(key, amount = 1) # :nodoc:
96
100
  log("decrement", key, amount)
97
-
98
101
  response = @data.decr(key, amount)
99
102
  response == Response::NOT_FOUND ? nil : response
100
103
  rescue MemCache::MemCacheError
@@ -102,6 +105,8 @@ module ActiveSupport
102
105
  end
103
106
 
104
107
  def delete_matched(matcher, options = nil) # :nodoc:
108
+ # don't do any local caching at present, just pass
109
+ # through and let the error happen
105
110
  super
106
111
  raise "Not supported by Memcache"
107
112
  end
@@ -0,0 +1,104 @@
1
+ module ActiveSupport
2
+ module Cache
3
+ module Strategy
4
+ module LocalCache
5
+ # this allows caching of the fact that there is nothing in the remote cache
6
+ NULL = 'remote_cache_store:null'
7
+
8
+ def with_local_cache
9
+ Thread.current[thread_local_key] = MemoryStore.new
10
+ yield
11
+ ensure
12
+ Thread.current[thread_local_key] = nil
13
+ end
14
+
15
+ def middleware
16
+ @middleware ||= begin
17
+ klass = Class.new
18
+ klass.class_eval(<<-EOS, __FILE__, __LINE__)
19
+ def initialize(app)
20
+ @app = app
21
+ end
22
+
23
+ def call(env)
24
+ Thread.current[:#{thread_local_key}] = MemoryStore.new
25
+ @app.call(env)
26
+ ensure
27
+ Thread.current[:#{thread_local_key}] = nil
28
+ end
29
+ EOS
30
+ klass
31
+ end
32
+ end
33
+
34
+ def read(key, options = nil)
35
+ value = local_cache && local_cache.read(key)
36
+ if value == NULL
37
+ nil
38
+ elsif value.nil?
39
+ value = super
40
+ local_cache.write(key, value || NULL) if local_cache
41
+ value
42
+ else
43
+ # forcing the value to be immutable
44
+ value.duplicable? ? value.dup : value
45
+ end
46
+ end
47
+
48
+ def write(key, value, options = nil)
49
+ value = value.to_s if respond_to?(:raw?) && raw?(options)
50
+ local_cache.write(key, value || NULL) if local_cache
51
+ super
52
+ end
53
+
54
+ def delete(key, options = nil)
55
+ local_cache.write(key, NULL) if local_cache
56
+ super
57
+ end
58
+
59
+ def exist(key, options = nil)
60
+ value = local_cache.read(key) if local_cache
61
+ if value == NULL
62
+ false
63
+ elsif value
64
+ true
65
+ else
66
+ super
67
+ end
68
+ end
69
+
70
+ def increment(key, amount = 1)
71
+ if value = super
72
+ local_cache.write(key, value.to_s) if local_cache
73
+ value
74
+ else
75
+ nil
76
+ end
77
+ end
78
+
79
+ def decrement(key, amount = 1)
80
+ if value = super
81
+ local_cache.write(key, value.to_s) if local_cache
82
+ value
83
+ else
84
+ nil
85
+ end
86
+ end
87
+
88
+ def clear
89
+ local_cache.clear if local_cache
90
+ super
91
+ end
92
+
93
+ private
94
+ def thread_local_key
95
+ @thread_local_key ||= "#{self.class.name.underscore}_local_cache".gsub("/", "_").to_sym
96
+ end
97
+
98
+ def local_cache
99
+ Thread.current[thread_local_key]
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -192,13 +192,8 @@ module ActiveSupport
192
192
  end
193
193
 
194
194
  def should_run_callback?(*args)
195
- if options[:if]
196
- evaluate_method(options[:if], *args)
197
- elsif options[:unless]
198
- !evaluate_method(options[:unless], *args)
199
- else
200
- true
201
- end
195
+ [options[:if]].flatten.compact.all? { |a| evaluate_method(a, *args) } &&
196
+ ![options[:unless]].flatten.compact.any? { |a| evaluate_method(a, *args) }
202
197
  end
203
198
  end
204
199
 
@@ -210,20 +205,24 @@ module ActiveSupport
210
205
  def define_callbacks(*callbacks)
211
206
  callbacks.each do |callback|
212
207
  class_eval <<-"end_eval"
213
- def self.#{callback}(*methods, &block)
214
- callbacks = CallbackChain.build(:#{callback}, *methods, &block)
215
- (@#{callback}_callbacks ||= CallbackChain.new).concat callbacks
216
- end
217
-
218
- def self.#{callback}_callback_chain
219
- @#{callback}_callbacks ||= CallbackChain.new
220
-
221
- if superclass.respond_to?(:#{callback}_callback_chain)
222
- CallbackChain.new(superclass.#{callback}_callback_chain + @#{callback}_callbacks)
223
- else
224
- @#{callback}_callbacks
225
- end
226
- end
208
+ def self.#{callback}(*methods, &block) # def self.before_save(*methods, &block)
209
+ callbacks = CallbackChain.build(:#{callback}, *methods, &block) # callbacks = CallbackChain.build(:before_save, *methods, &block)
210
+ @#{callback}_callbacks ||= CallbackChain.new # @before_save_callbacks ||= CallbackChain.new
211
+ @#{callback}_callbacks.concat callbacks # @before_save_callbacks.concat callbacks
212
+ end # end
213
+ #
214
+ def self.#{callback}_callback_chain # def self.before_save_callback_chain
215
+ @#{callback}_callbacks ||= CallbackChain.new # @before_save_callbacks ||= CallbackChain.new
216
+ #
217
+ if superclass.respond_to?(:#{callback}_callback_chain) # if superclass.respond_to?(:before_save_callback_chain)
218
+ CallbackChain.new( # CallbackChain.new(
219
+ superclass.#{callback}_callback_chain + # superclass.before_save_callback_chain +
220
+ @#{callback}_callbacks # @before_save_callbacks
221
+ ) # )
222
+ else # else
223
+ @#{callback}_callbacks # @before_save_callbacks
224
+ end # end
225
+ end # end
227
226
  end_eval
228
227
  end
229
228
  end
@@ -1,4 +1,4 @@
1
1
  Dir[File.dirname(__FILE__) + "/core_ext/*.rb"].sort.each do |path|
2
- filename = File.basename(path)
2
+ filename = File.basename(path, '.rb')
3
3
  require "active_support/core_ext/#{filename}"
4
4
  end