From 133925804f24d716a3836698dbe5a7d8b30de0b5 Mon Sep 17 00:00:00 2001 From: "Michael S. Klishin" Date: Sun, 28 Dec 2008 11:26:57 +0300 Subject: Introduce minimalistic package for ActiveSupport. To simplify using of ActiveSupport in 3rd party libraries, a simple way to require only minimum of commonly used extensions (multibyte, inflections, array and hash extensions, #blank?, and a few others) is needed. For exactly this reason some out-of-Rails-space libraries adopted Extlib, originally from DataMapper. To keep it 2067% backwards compatible, and still available to everyone even in 2.x releases, active_support/minimalistic.rb was added. Use it like this: gem 'active_support', '>=2.3' require 'active_support/minimalistic' instead of require 'activesupport' Right now this package with RubyGems uses about 10 megs of RAM (10.01 or so). It can be further slimmed down though, once we simplify multibyte implementation that right now uses advanced accessors from Module extensions. To compare RAM usage with previous ActiveSupport versions and Extlib, at the time of writing, see http://gist.github.com/40401. --- .../lib/active_support/core_ext/string/multibyte.rb | 6 +++++- activesupport/lib/active_support/minimalistic.rb | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 activesupport/lib/active_support/minimalistic.rb (limited to 'activesupport') diff --git a/activesupport/lib/active_support/core_ext/string/multibyte.rb b/activesupport/lib/active_support/core_ext/string/multibyte.rb index a4caa83b74..8f8f0968fd 100644 --- a/activesupport/lib/active_support/core_ext/string/multibyte.rb +++ b/activesupport/lib/active_support/core_ext/string/multibyte.rb @@ -55,7 +55,11 @@ module ActiveSupport #:nodoc: unless '1.8.7 and later'.respond_to?(:chars) def chars - ActiveSupport::Deprecation.warn('String#chars has been deprecated in favor of String#mb_chars.', caller) + # FIXME: + # ActiveSupport::Deprecation refers to RAILS_ENV + # and is a show stopper for 3rd party applications + # that only want ActiveSupport + ActiveSupport::Deprecation.warn('String#chars has been deprecated in favor of String#mb_chars.', caller) if defined?(ActiveSupport::Deprecation) mb_chars end end diff --git a/activesupport/lib/active_support/minimalistic.rb b/activesupport/lib/active_support/minimalistic.rb new file mode 100644 index 0000000000..ecb5de9eaa --- /dev/null +++ b/activesupport/lib/active_support/minimalistic.rb @@ -0,0 +1,15 @@ +$LOAD_PATH.unshift File.dirname(__FILE__) + +require "core_ext/blank" +# whole object.rb pulls up rare used introspection extensions +require "core_ext/object/metaclass" +require 'core_ext/array' +require 'core_ext/hash' +require 'core_ext/module/attribute_accessors' +require 'multibyte' +require 'core_ext/string/multibyte' +require 'core_ext/string/inflections' + +class String + include ActiveSupport::CoreExtensions::String::Multibyte +end -- cgit v1.2.3 From d77deb89d54b18c662ae3de103802e4d7a9d7d08 Mon Sep 17 00:00:00 2001 From: "Michael S. Klishin" Date: Sun, 28 Dec 2008 13:21:10 +0300 Subject: Annotated metaprogramming code across ActiveSupport --- .../lib/active_support/buffered_logger.rb | 16 +++--- activesupport/lib/active_support/callbacks.rb | 28 +++++------ .../core_ext/class/attribute_accessors.rb | 46 ++++++++--------- .../core_ext/class/delegating_attributes.rb | 42 ++++++++-------- .../core_ext/class/inheritable_attributes.rb | 58 +++++++++++----------- .../core_ext/module/attribute_accessors.rb | 46 ++++++++--------- activesupport/lib/active_support/core_ext/proc.rb | 6 +-- .../active_support/core_ext/string/multibyte.rb | 6 ++- activesupport/lib/active_support/deprecation.rb | 12 +++-- activesupport/lib/active_support/memoizable.rb | 52 +++++++++---------- activesupport/lib/active_support/minimalistic.rb | 15 ++++++ .../active_support/multibyte/unicode_database.rb | 10 ++-- activesupport/lib/active_support/time_with_zone.rb | 8 +-- 13 files changed, 183 insertions(+), 162 deletions(-) create mode 100644 activesupport/lib/active_support/minimalistic.rb (limited to 'activesupport') diff --git a/activesupport/lib/active_support/buffered_logger.rb b/activesupport/lib/active_support/buffered_logger.rb index 445d8edf47..568c596f91 100644 --- a/activesupport/lib/active_support/buffered_logger.rb +++ b/activesupport/lib/active_support/buffered_logger.rb @@ -67,14 +67,14 @@ module ActiveSupport end for severity in Severity.constants - class_eval <<-EOT, __FILE__, __LINE__ - def #{severity.downcase}(message = nil, progname = nil, &block) - add(#{severity}, message, progname, &block) - end - - def #{severity.downcase}? - #{severity} >= @level - end + class_eval <<-EOT, __FILE__, __LINE__ + 1 + def #{severity.downcase}(message = nil, progname = nil, &block) # def debug(message = nil, progname = nil, &block) + add(#{severity}, message, progname, &block) # add(DEBUG, message, progname, &block) + end # end + + def #{severity.downcase}? # def debug? + #{severity} >= @level # DEBUG >= @level + end # end EOT end diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb index 5cdcaf5ad1..aabf0a0895 100644 --- a/activesupport/lib/active_support/callbacks.rb +++ b/activesupport/lib/active_support/callbacks.rb @@ -209,21 +209,21 @@ module ActiveSupport module ClassMethods def define_callbacks(*callbacks) callbacks.each do |callback| - class_eval <<-"end_eval" - def self.#{callback}(*methods, &block) - callbacks = CallbackChain.build(:#{callback}, *methods, &block) - (@#{callback}_callbacks ||= CallbackChain.new).concat callbacks - end + class_eval <<-"end_eval", __FILE__, __LINE__ + 1 + def self.#{callback}(*methods, &block) # def self.validate_on_create(*methods, &block) + callbacks = CallbackChain.build(:#{callback}, *methods, &block) # callbacks = CallbackChain.build(:validate_on_create, *methods, &block) + (@#{callback}_callbacks ||= CallbackChain.new).concat callbacks # (@validate_on_create_callbacks ||= CallbackChain.new).concat callbacks + end # end - def self.#{callback}_callback_chain - @#{callback}_callbacks ||= CallbackChain.new - - if superclass.respond_to?(:#{callback}_callback_chain) - CallbackChain.new(superclass.#{callback}_callback_chain + @#{callback}_callbacks) - else - @#{callback}_callbacks - end - end + def self.#{callback}_callback_chain # def self.validate_on_create_callback_chain + @#{callback}_callbacks ||= CallbackChain.new # @validate_on_create_callbacks ||= CallbackChain.new + # + if superclass.respond_to?(:#{callback}_callback_chain) # if superclass.respond_to?(:validate_on_create_callback_chain) + CallbackChain.new(superclass.#{callback}_callback_chain + @#{callback}_callbacks) # CallbackChain.new(superclass.validate_on_create_callback_chain + @validate_on_create_callbacks) + else # else + @#{callback}_callbacks # @validate_on_create_callbacks + end # end + end # end end_eval end end diff --git a/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb index 186ca69c05..6b2ac8b38b 100644 --- a/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb +++ b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb @@ -10,18 +10,18 @@ class Class def cattr_reader(*syms) syms.flatten.each do |sym| next if sym.is_a?(Hash) - class_eval(<<-EOS, __FILE__, __LINE__) - unless defined? @@#{sym} - @@#{sym} = nil - end + class_eval(<<-EOS, __FILE__, __LINE__ + 1) + unless defined? @@#{sym} # unless defined @@property + @@#{sym} = nil # @@property = nil + end # end - def self.#{sym} - @@#{sym} - end + def self.#{sym} # def self.property + @@#{sym} # @@property + end # end - def #{sym} - @@#{sym} - end + def #{sym} # def property + @@#{sym} # @@property + end # end EOS end end @@ -29,19 +29,19 @@ class Class def cattr_writer(*syms) options = syms.extract_options! syms.flatten.each do |sym| - class_eval(<<-EOS, __FILE__, __LINE__) - unless defined? @@#{sym} - @@#{sym} = nil - end - - def self.#{sym}=(obj) - @@#{sym} = obj - end - - #{" - def #{sym}=(obj) - @@#{sym} = obj - end + class_eval(<<-EOS, __FILE__, __LINE__ + 1) + unless defined? @@#{sym} # unless defined? @@property + @@#{sym} = nil # @@property = nil + end # end + + def self.#{sym}=(obj) # def self.property=(obj) + @@#{sym} = obj # @@property + end # end + + #{" + def #{sym}=(obj) # def property=(obj) + @@#{sym} = obj # @@property = obj + end # end " unless options[:instance_writer] == false } EOS end diff --git a/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb b/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb index 368317df9b..3b093a9a65 100644 --- a/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb +++ b/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb @@ -8,33 +8,33 @@ class Class def superclass_delegating_reader(*names) class_name_to_stop_searching_on = self.superclass.name.blank? ? "Object" : self.superclass.name names.each do |name| - class_eval <<-EOS - def self.#{name} - if defined?(@#{name}) - @#{name} - elsif superclass < #{class_name_to_stop_searching_on} && superclass.respond_to?(:#{name}) - superclass.#{name} - end - end - def #{name} - self.class.#{name} - end - def self.#{name}? - !!#{name} - end - def #{name}? - !!#{name} - end + class_eval(<<-EOS, __FILE__, __LINE__ + 1) + def self.#{name} # def self.property + if defined?(@#{name}) # if defined?(@property) + @#{name} # @property + elsif superclass < #{class_name_to_stop_searching_on} && superclass.respond_to?(:#{name}) # elseif superclass < Object && superclass.respond_to?(:property) + superclass.#{name} # superclass.property + end # end + end # end + def #{name} # def property + self.class.#{name} # self.class.property + end # end + def self.#{name}? # def self.property? + !!#{name} # !!property + end # end + def #{name}? # def property? + !!#{name} # !!property + end # end EOS end end def superclass_delegating_writer(*names) names.each do |name| - class_eval <<-EOS - def self.#{name}=(value) - @#{name} = value - end + class_eval(<<-EOS, __FILE__, __LINE__ + 1) + def self.#{name}=(value) # def self.property=(value) + @#{name} = value # @property = value + end # end EOS end end diff --git a/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb b/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb index e6143a274b..8d0233ce9a 100644 --- a/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb +++ b/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb @@ -10,14 +10,14 @@ class Class # :nodoc: def class_inheritable_reader(*syms) syms.each do |sym| next if sym.is_a?(Hash) - class_eval <<-EOS - def self.#{sym} - read_inheritable_attribute(:#{sym}) - end - - def #{sym} - self.class.#{sym} - end + class_eval(<<-EOS, __FILE__, __LINE__ + 1) + def self.#{sym} # def self.after_add + read_inheritable_attribute(:#{sym}) # read_inheritable_attribute(:after_add) + end # end + + def #{sym} # def after_add + self.class.#{sym} # self.class.after_add + end # end EOS end end @@ -25,15 +25,15 @@ class Class # :nodoc: def class_inheritable_writer(*syms) options = syms.extract_options! syms.each do |sym| - class_eval <<-EOS - def self.#{sym}=(obj) - write_inheritable_attribute(:#{sym}, obj) - end + class_eval(<<-EOS, __FILE__, __LINE__ + 1) + def self.#{sym}=(obj) # def self.property=(obj) + write_inheritable_attribute(:#{sym}, obj) # write_inheritable_attribute(:property, obj) + end # end #{" - def #{sym}=(obj) - self.class.#{sym} = obj - end + def #{sym}=(obj) # def property=(obj) + self.class.#{sym} = obj # self.class.property = obj + end # end " unless options[:instance_writer] == false } EOS end @@ -42,15 +42,15 @@ class Class # :nodoc: def class_inheritable_array_writer(*syms) options = syms.extract_options! syms.each do |sym| - class_eval <<-EOS - def self.#{sym}=(obj) - write_inheritable_array(:#{sym}, obj) - end + class_eval(<<-EOS, __FILE__, __LINE__ + 1) + def self.#{sym}=(obj) # def self.property=(obj) + write_inheritable_array(:#{sym}, obj) # write_inheritable_array(:property, obj) + end # end #{" - def #{sym}=(obj) - self.class.#{sym} = obj - end + def #{sym}=(obj) # def property=(obj) + self.class.#{sym} = obj # self.class.property = obj + end # end " unless options[:instance_writer] == false } EOS end @@ -59,15 +59,15 @@ class Class # :nodoc: def class_inheritable_hash_writer(*syms) options = syms.extract_options! syms.each do |sym| - class_eval <<-EOS - def self.#{sym}=(obj) - write_inheritable_hash(:#{sym}, obj) - end + class_eval(<<-EOS, __FILE__, __LINE__ + 1) + def self.#{sym}=(obj) # def self.property=(obj) + write_inheritable_hash(:#{sym}, obj) # write_inheritable_hash(:property, obj) + end # end #{" - def #{sym}=(obj) - self.class.#{sym} = obj - end + def #{sym}=(obj) # def property=(obj) + self.class.#{sym} = obj # self.class.property = obj + end # end " unless options[:instance_writer] == false } EOS end diff --git a/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb b/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb index 51e1c9af90..9467eb71ac 100644 --- a/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb +++ b/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb @@ -14,18 +14,18 @@ class Module def mattr_reader(*syms) syms.each do |sym| next if sym.is_a?(Hash) - class_eval(<<-EOS, __FILE__, __LINE__) - unless defined? @@#{sym} - @@#{sym} = nil - end + class_eval(<<-EOS, __FILE__, __LINE__ + 1) + unless defined? @@#{sym} # unless defined? @@property + @@#{sym} = nil # @@ property = nil + end # end - def self.#{sym} - @@#{sym} - end + def self.#{sym} # def self.property + @@#{sym} # @@property + end # end - def #{sym} - @@#{sym} - end + def #{sym} # def property + @@#{sym} # @@property + end # end EOS end end @@ -33,19 +33,19 @@ class Module def mattr_writer(*syms) options = syms.extract_options! syms.each do |sym| - class_eval(<<-EOS, __FILE__, __LINE__) - unless defined? @@#{sym} - @@#{sym} = nil - end - - def self.#{sym}=(obj) - @@#{sym} = obj - end - - #{" - def #{sym}=(obj) - @@#{sym} = obj - end + class_eval(<<-EOS, __FILE__, __LINE__ + 1) + unless defined? @@#{sym} # unless defined? @@property + @@#{sym} = nil # @@ property = nil + end # end + + def self.#{sym}=(obj) # def self.property=(obj) + @@#{sym} = obj # @@property = obj + end # end + + #{" + def #{sym}=(obj) # def property=(obj) + @@#{sym} = obj # @@property = obj + end # end " unless options[:instance_writer] == false } EOS end diff --git a/activesupport/lib/active_support/core_ext/proc.rb b/activesupport/lib/active_support/core_ext/proc.rb index 2ca23f62ef..5c29cc32a2 100644 --- a/activesupport/lib/active_support/core_ext/proc.rb +++ b/activesupport/lib/active_support/core_ext/proc.rb @@ -3,9 +3,9 @@ class Proc #:nodoc: block, time = self, Time.now (class << object; self end).class_eval do method_name = "__bind_#{time.to_i}_#{time.usec}" - define_method(method_name, &block) - method = instance_method(method_name) - remove_method(method_name) + define_method(method_name, &block) # define_method("__bind_1230458026_720454", &block) + method = instance_method(method_name) # method = instance_method("__bind_1230458026_720454") + remove_method(method_name) # remove_method("__bind_1230458026_720454") method end.bind(object) end diff --git a/activesupport/lib/active_support/core_ext/string/multibyte.rb b/activesupport/lib/active_support/core_ext/string/multibyte.rb index a4caa83b74..8f8f0968fd 100644 --- a/activesupport/lib/active_support/core_ext/string/multibyte.rb +++ b/activesupport/lib/active_support/core_ext/string/multibyte.rb @@ -55,7 +55,11 @@ module ActiveSupport #:nodoc: unless '1.8.7 and later'.respond_to?(:chars) def chars - ActiveSupport::Deprecation.warn('String#chars has been deprecated in favor of String#mb_chars.', caller) + # FIXME: + # ActiveSupport::Deprecation refers to RAILS_ENV + # and is a show stopper for 3rd party applications + # that only want ActiveSupport + ActiveSupport::Deprecation.warn('String#chars has been deprecated in favor of String#mb_chars.', caller) if defined?(ActiveSupport::Deprecation) mb_chars end end diff --git a/activesupport/lib/active_support/deprecation.rb b/activesupport/lib/active_support/deprecation.rb index 25b26e9c96..d9bd40199f 100644 --- a/activesupport/lib/active_support/deprecation.rb +++ b/activesupport/lib/active_support/deprecation.rb @@ -89,11 +89,13 @@ module ActiveSupport method_names = method_names + options.keys method_names.each do |method_name| alias_method_chain(method_name, :deprecation) do |target, punctuation| - class_eval(<<-EOS, __FILE__, __LINE__) - def #{target}_with_deprecation#{punctuation}(*args, &block) - ::ActiveSupport::Deprecation.warn(self.class.deprecated_method_warning(:#{method_name}, #{options[method_name].inspect}), caller) - #{target}_without_deprecation#{punctuation}(*args, &block) - end + class_eval(<<-EOS, __FILE__, __LINE__ + 1) + def #{target}_with_deprecation#{punctuation}(*args, &block) # def multi_with_reprecation(*args, &block) + ::ActiveSupport::Deprecation.warn( # ::ActiveSupport::Deprecation.warn( + self.class.deprecated_method_warning(:#{method_name}, #{options[method_name].inspect}), # self.class.deprecated_method_warning(:multi, "this method is deprecated, blah, blah, blah") + caller) # caller) + #{target}_without_deprecation#{punctuation}(*args, &block) # multi_without_deprecation(*args, &block) + end # end EOS end end diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb index 9f2fd3a401..67ed10d58d 100644 --- a/activesupport/lib/active_support/memoizable.rb +++ b/activesupport/lib/active_support/memoizable.rb @@ -58,35 +58,35 @@ module ActiveSupport original_method = :"_unmemoized_#{symbol}" memoized_ivar = ActiveSupport::Memoizable.memoized_ivar_for(symbol) - class_eval <<-EOS, __FILE__, __LINE__ + class_eval <<-EOS, __FILE__, __LINE__ + 1 include InstanceMethods - raise "Already memoized #{symbol}" if method_defined?(:#{original_method}) - alias #{original_method} #{symbol} + raise "Already memoized #{symbol}" if method_defined?(:#{original_method}) # raise "Already memoized if_modified_since" if method_defined?(:__unmemoized_if_modified_since) + alias #{original_method} #{symbol} # alias __unmemoized_if_modified_since if_modified_since - if instance_method(:#{symbol}).arity == 0 - def #{symbol}(reload = false) - if reload || !defined?(#{memoized_ivar}) || #{memoized_ivar}.empty? - #{memoized_ivar} = [#{original_method}.freeze] - end - #{memoized_ivar}[0] - end - else - def #{symbol}(*args) - #{memoized_ivar} ||= {} unless frozen? - reload = args.pop if args.last == true || args.last == :reload - - if defined?(#{memoized_ivar}) && #{memoized_ivar} - if !reload && #{memoized_ivar}.has_key?(args) - #{memoized_ivar}[args] - elsif #{memoized_ivar} - #{memoized_ivar}[args] = #{original_method}(*args).freeze - end - else - #{original_method}(*args) - end - end - end + if instance_method(:#{symbol}).arity == 0 # if instance_method(:if_modified_since).arity == 0 + def #{symbol}(reload = false) # def if_modified_since(reload = false) + if reload || !defined?(#{memoized_ivar}) || #{memoized_ivar}.empty? # if reload || !defined?(@_memoized_if_modified_since) || @_memoized_if_modified_since.empty? + #{memoized_ivar} = [#{original_method}.freeze] # @_memoized_if_modified_since = [__unmemoized_if_modified_since.freeze] + end # end + #{memoized_ivar}[0] # @_memoized_if_modified_since[0] + end # end + else # else + def #{symbol}(*args) # def if_modified_since(*args) + #{memoized_ivar} ||= {} unless frozen? # @_memoized_if_modified_since ||= {} unless frozen? + reload = args.pop if args.last == true || args.last == :reload # reload = args.pop if args.last == true || args.last == :reload + # + if defined?(#{memoized_ivar}) && #{memoized_ivar} # if defined?(@_memoized_if_modified_since) && @_memoized_if_modified_since + if !reload && #{memoized_ivar}.has_key?(args) # if !reload && @_memoized_if_modified_since.has_key?(args) + #{memoized_ivar}[args] # @_memoized_if_modified_since[args] + elsif #{memoized_ivar} # elsif @_memoized_if_modified_since + #{memoized_ivar}[args] = #{original_method}(*args).freeze # @_memoized_if_modified_since[args] = __unmemoized_if_modified_since(*args).freeze + end # end + else # else + #{original_method}(*args) # __unmemoized_if_modified_since(*args) + end # end + end # end + end # end EOS end end diff --git a/activesupport/lib/active_support/minimalistic.rb b/activesupport/lib/active_support/minimalistic.rb new file mode 100644 index 0000000000..ecb5de9eaa --- /dev/null +++ b/activesupport/lib/active_support/minimalistic.rb @@ -0,0 +1,15 @@ +$LOAD_PATH.unshift File.dirname(__FILE__) + +require "core_ext/blank" +# whole object.rb pulls up rare used introspection extensions +require "core_ext/object/metaclass" +require 'core_ext/array' +require 'core_ext/hash' +require 'core_ext/module/attribute_accessors' +require 'multibyte' +require 'core_ext/string/multibyte' +require 'core_ext/string/inflections' + +class String + include ActiveSupport::CoreExtensions::String::Multibyte +end diff --git a/activesupport/lib/active_support/multibyte/unicode_database.rb b/activesupport/lib/active_support/multibyte/unicode_database.rb index 3b8cf8f9eb..074ad8613a 100644 --- a/activesupport/lib/active_support/multibyte/unicode_database.rb +++ b/activesupport/lib/active_support/multibyte/unicode_database.rb @@ -23,11 +23,11 @@ module ActiveSupport #:nodoc: # Lazy load the Unicode database so it's only loaded when it's actually used ATTRIBUTES.each do |attr_name| - class_eval(<<-EOS, __FILE__, __LINE__) - def #{attr_name} - load - @#{attr_name} - end + class_eval(<<-EOS, __FILE__, __LINE__ + 1) + def #{attr_name} # def codepoints + load # load + @#{attr_name} # @codepoints + end # end EOS end diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index 9a2d283b30..59f1e6163b 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -233,10 +233,10 @@ module ActiveSupport end %w(year mon month day mday wday yday hour min sec to_date).each do |method_name| - class_eval <<-EOV - def #{method_name} - time.#{method_name} - end + class_eval <<-EOV, __FILE__, __LINE__ + 1 + def #{method_name} # def month + time.#{method_name} # time.month + end # end EOV end -- cgit v1.2.3 From 89e98955c79b39ec408efb39cde07d6f14997183 Mon Sep 17 00:00:00 2001 From: "Michael S. Klishin" Date: Sun, 28 Dec 2008 21:41:48 +0300 Subject: active_support/minimalistic.rb => active_support/mini.rb --- activesupport/lib/active_support/mini.rb | 15 +++++++++++++++ activesupport/lib/active_support/minimalistic.rb | 15 --------------- 2 files changed, 15 insertions(+), 15 deletions(-) create mode 100644 activesupport/lib/active_support/mini.rb delete mode 100644 activesupport/lib/active_support/minimalistic.rb (limited to 'activesupport') diff --git a/activesupport/lib/active_support/mini.rb b/activesupport/lib/active_support/mini.rb new file mode 100644 index 0000000000..ecb5de9eaa --- /dev/null +++ b/activesupport/lib/active_support/mini.rb @@ -0,0 +1,15 @@ +$LOAD_PATH.unshift File.dirname(__FILE__) + +require "core_ext/blank" +# whole object.rb pulls up rare used introspection extensions +require "core_ext/object/metaclass" +require 'core_ext/array' +require 'core_ext/hash' +require 'core_ext/module/attribute_accessors' +require 'multibyte' +require 'core_ext/string/multibyte' +require 'core_ext/string/inflections' + +class String + include ActiveSupport::CoreExtensions::String::Multibyte +end diff --git a/activesupport/lib/active_support/minimalistic.rb b/activesupport/lib/active_support/minimalistic.rb deleted file mode 100644 index ecb5de9eaa..0000000000 --- a/activesupport/lib/active_support/minimalistic.rb +++ /dev/null @@ -1,15 +0,0 @@ -$LOAD_PATH.unshift File.dirname(__FILE__) - -require "core_ext/blank" -# whole object.rb pulls up rare used introspection extensions -require "core_ext/object/metaclass" -require 'core_ext/array' -require 'core_ext/hash' -require 'core_ext/module/attribute_accessors' -require 'multibyte' -require 'core_ext/string/multibyte' -require 'core_ext/string/inflections' - -class String - include ActiveSupport::CoreExtensions::String::Multibyte -end -- cgit v1.2.3 From e523b43e202d343912f67b8c8737d9e2e956b31f Mon Sep 17 00:00:00 2001 From: "Michael S. Klishin" Date: Sun, 28 Dec 2008 22:18:03 +0300 Subject: Use active_support/mini instead of active_support/minimalistic --- activesupport/lib/active_support/minimalistic.rb | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 activesupport/lib/active_support/minimalistic.rb (limited to 'activesupport') diff --git a/activesupport/lib/active_support/minimalistic.rb b/activesupport/lib/active_support/minimalistic.rb deleted file mode 100644 index ecb5de9eaa..0000000000 --- a/activesupport/lib/active_support/minimalistic.rb +++ /dev/null @@ -1,15 +0,0 @@ -$LOAD_PATH.unshift File.dirname(__FILE__) - -require "core_ext/blank" -# whole object.rb pulls up rare used introspection extensions -require "core_ext/object/metaclass" -require 'core_ext/array' -require 'core_ext/hash' -require 'core_ext/module/attribute_accessors' -require 'multibyte' -require 'core_ext/string/multibyte' -require 'core_ext/string/inflections' - -class String - include ActiveSupport::CoreExtensions::String::Multibyte -end -- cgit v1.2.3 From 31fb733bae7bd07f3f45067671315e74dd83af22 Mon Sep 17 00:00:00 2001 From: "Michael S. Klishin" Date: Mon, 29 Dec 2008 23:31:57 +0300 Subject: It was decided that Multibyte does not belong to as/mini. --- activesupport/lib/active_support/mini.rb | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/mini.rb b/activesupport/lib/active_support/mini.rb index ecb5de9eaa..fe7ba48e58 100644 --- a/activesupport/lib/active_support/mini.rb +++ b/activesupport/lib/active_support/mini.rb @@ -1,15 +1,9 @@ $LOAD_PATH.unshift File.dirname(__FILE__) require "core_ext/blank" -# whole object.rb pulls up rare used introspection extensions +# whole object.rb pulls up rarely used introspection extensions require "core_ext/object/metaclass" require 'core_ext/array' require 'core_ext/hash' require 'core_ext/module/attribute_accessors' -require 'multibyte' -require 'core_ext/string/multibyte' -require 'core_ext/string/inflections' - -class String - include ActiveSupport::CoreExtensions::String::Multibyte -end +require 'core_ext/string/inflections' \ No newline at end of file -- cgit v1.2.3 From db619c4a4115d5eeca9473f8f77f34c877e4e1dd Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Mon, 5 Jan 2009 01:10:55 -0800 Subject: Sync 'rails/rails/master' --- activesupport/CHANGELOG | 2 ++ activesupport/lib/active_support/time_with_zone.rb | 2 +- activesupport/test/core_ext/time_with_zone_test.rb | 9 +++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) (limited to 'activesupport') diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 7b9ccc888d..3c5f39d321 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,5 +1,7 @@ *2.3.0 [Edge]* +* TimeWithZone#- gives correct result with wrapped DateTime, and with DateTime argument [Geoff Buesing] + * Updated i18n gem to version 0.1.1 #1635 [Yaroslav Markin] * Add :allow_nil option to delegate. #1127 [Sergio Gil] diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index 59f1e6163b..51939e1d01 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -199,7 +199,7 @@ module ActiveSupport # If we're subtracting a Duration of variable length (i.e., years, months, days), move backwards from #time, # otherwise move backwards #utc, for accuracy when moving across DST boundaries if other.acts_like?(:time) - utc - other + utc.to_f - other.to_f elsif duration_of_variable_length?(other) method_missing(:-, other) else diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb index dc36336239..7c8fb7dd94 100644 --- a/activesupport/test/core_ext/time_with_zone_test.rb +++ b/activesupport/test/core_ext/time_with_zone_test.rb @@ -256,6 +256,15 @@ class TimeWithZoneTest < Test::Unit::TestCase twz2 = ActiveSupport::TimeWithZone.new( Time.utc(2000, 1, 2), ActiveSupport::TimeZone['UTC'] ) assert_equal 86_400.0, twz2 - twz1 end + + def test_minus_with_datetime + assert_equal 86_400.0, ActiveSupport::TimeWithZone.new( Time.utc(2000, 1, 2), ActiveSupport::TimeZone['UTC'] ) - DateTime.civil(2000, 1, 1) + end + + def test_minus_with_wrapped_datetime + assert_equal 86_400.0, ActiveSupport::TimeWithZone.new( DateTime.civil(2000, 1, 2), ActiveSupport::TimeZone['UTC'] ) - Time.utc(2000, 1, 1) + assert_equal 86_400.0, ActiveSupport::TimeWithZone.new( DateTime.civil(2000, 1, 2), ActiveSupport::TimeZone['UTC'] ) - DateTime.civil(2000, 1, 1) + end def test_plus_and_minus_enforce_spring_dst_rules silence_warnings do # silence warnings raised by tzinfo gem -- cgit v1.2.3 From b1530545d259c144770bd8fd7881cb16160c0afc Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Wed, 7 Jan 2009 17:51:11 +0000 Subject: Fix JSON decoder date-converter regexp [#1662 state:resolved] [Jonathan del Strother] --- activesupport/lib/active_support/json/decoding.rb | 2 +- activesupport/test/json/decoding_test.rb | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/json/decoding.rb b/activesupport/lib/active_support/json/decoding.rb index fdb219dbf7..9da4048272 100644 --- a/activesupport/lib/active_support/json/decoding.rb +++ b/activesupport/lib/active_support/json/decoding.rb @@ -16,7 +16,7 @@ module ActiveSupport protected # matches YAML-formatted dates - DATE_REGEX = /^\d{4}-\d{2}-\d{2}|\d{4}-\d{1,2}-\d{1,2}[ \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?)?$/ + DATE_REGEX = /^(?:\d{4}-\d{2}-\d{2}|\d{4}-\d{1,2}-\d{1,2}[ \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?)?)$/ # Ensure that ":" and "," are always followed by a space def convert_json_to_yaml(json) #:nodoc: diff --git a/activesupport/test/json/decoding_test.rb b/activesupport/test/json/decoding_test.rb index 19ae3a01a8..558b03b90d 100644 --- a/activesupport/test/json/decoding_test.rb +++ b/activesupport/test/json/decoding_test.rb @@ -15,7 +15,8 @@ class TestJSONDecoding < Test::Unit::TestCase # no time zone %({a: "2007-01-01 01:12:34"}) => {'a' => "2007-01-01 01:12:34"}, # needs to be *exact* - %({a: " 2007-01-01 01:12:34 Z "}) => {'a' => " 2007-01-01 01:12:34 Z "}, + %({a: " 2007-01-01 01:12:34 Z "}) => {'a' => " 2007-01-01 01:12:34 Z "}, + %({a: "2007-01-01 : it's your birthday"}) => {'a' => "2007-01-01 : it's your birthday"}, %([]) => [], %({}) => {}, %(1) => 1, -- cgit v1.2.3 From c2d23affad0ed4542e3906c334a7b27b07fc695c Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 7 Jan 2009 13:19:48 -0800 Subject: Object#tap for Ruby < 1.8.7 --- activesupport/CHANGELOG | 3 +++ activesupport/lib/active_support/core_ext/object/misc.rb | 15 +++++++++++++++ activesupport/test/core_ext/object_ext_test.rb | 8 ++++++++ 3 files changed, 26 insertions(+) create mode 100644 activesupport/test/core_ext/object_ext_test.rb (limited to 'activesupport') diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 3c5f39d321..757cb1da04 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,5 +1,8 @@ *2.3.0 [Edge]* +* Object#tap shim for Ruby < 1.8.7. Similar to Object#returning, tap yields self then returns self. [Jeremy Kemper] + array.select { ... }.tap(&:inspect).map { ... } + * TimeWithZone#- gives correct result with wrapped DateTime, and with DateTime argument [Geoff Buesing] * Updated i18n gem to version 0.1.1 #1635 [Yaroslav Markin] diff --git a/activesupport/lib/active_support/core_ext/object/misc.rb b/activesupport/lib/active_support/core_ext/object/misc.rb index 46f9c7d676..4570570bbc 100644 --- a/activesupport/lib/active_support/core_ext/object/misc.rb +++ b/activesupport/lib/active_support/core_ext/object/misc.rb @@ -40,6 +40,21 @@ class Object value end + # Yields x to the block, and then returns x. + # The primary purpose of this method is to "tap into" a method chain, + # in order to perform operations on intermediate results within the chain. + # + # (1..10).tap { |x| puts "original: #{x.inspect}" }.to_a. + # tap { |x| puts "array: #{x.inspect}" }. + # select { |x| x%2 == 0 }. + # tap { |x| puts "evens: #{x.inspect}" }. + # map { |x| x*x }. + # tap { |x| puts "squares: #{x.inspect}" } + def tap + yield self + self + end unless Object.respond_to?(:tap) + # An elegant way to factor duplication out of options passed to a series of # method calls. Each method called in the block, with the block variable as # the receiver, will have its options merged with the default +options+ hash diff --git a/activesupport/test/core_ext/object_ext_test.rb b/activesupport/test/core_ext/object_ext_test.rb new file mode 100644 index 0000000000..a413d331c4 --- /dev/null +++ b/activesupport/test/core_ext/object_ext_test.rb @@ -0,0 +1,8 @@ +require 'abstract_unit' + +class ObjectExtTest < Test::Unit::TestCase + def test_tap_yields_and_returns_self + foo = Object.new + assert_equal foo, foo.tap { |x| assert_equal foo, x; :bar } + end +end -- cgit v1.2.3 From eb9af20b7cc0e374277cf330bdd404f9daab28ec Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 22 Jan 2009 16:18:10 -0600 Subject: Begin unifying the interface between ActionController and ActionView --- activesupport/lib/active_support.rb | 1 + .../lib/active_support/buffered_logger.rb | 16 ++++++------- activesupport/lib/active_support/callbacks.rb | 2 +- .../lib/active_support/concurrent_hash.rb | 26 ++++++++++++++++++++++ .../core_ext/class/attribute_accessors.rb | 4 ++-- .../core_ext/class/delegating_attributes.rb | 10 ++++----- .../core_ext/class/inheritable_attributes.rb | 22 +++++++++--------- .../core_ext/module/attribute_accessors.rb | 4 ++-- activesupport/lib/active_support/core_ext/proc.rb | 6 ++--- .../active_support/core_ext/string/multibyte.rb | 6 ++++- activesupport/lib/active_support/deprecation.rb | 2 +- activesupport/lib/active_support/memoizable.rb | 2 +- activesupport/lib/active_support/mini.rb | 9 ++++++++ .../active_support/multibyte/unicode_database.rb | 10 ++++----- activesupport/lib/active_support/time_with_zone.rb | 8 +++---- 15 files changed, 84 insertions(+), 44 deletions(-) create mode 100644 activesupport/lib/active_support/concurrent_hash.rb create mode 100644 activesupport/lib/active_support/mini.rb (limited to 'activesupport') diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb index 7ebb3c48e0..62d538e2d5 100644 --- a/activesupport/lib/active_support.rb +++ b/activesupport/lib/active_support.rb @@ -32,6 +32,7 @@ module ActiveSupport autoload :BufferedLogger, 'active_support/buffered_logger' autoload :Cache, 'active_support/cache' autoload :Callbacks, 'active_support/callbacks' + autoload :ConcurrentHash, 'active_support/concurrent_hash' autoload :Deprecation, 'active_support/deprecation' autoload :Duration, 'active_support/duration' autoload :Gzip, 'active_support/gzip' diff --git a/activesupport/lib/active_support/buffered_logger.rb b/activesupport/lib/active_support/buffered_logger.rb index 33bcf327f8..568c596f91 100644 --- a/activesupport/lib/active_support/buffered_logger.rb +++ b/activesupport/lib/active_support/buffered_logger.rb @@ -67,14 +67,14 @@ module ActiveSupport end for severity in Severity.constants - class_eval <<-EOT, __FILE__, __LINE__ - def #{severity.downcase}(message = nil, progname = nil, &block) # def debug(message = nil, progname = nil, &block) - add(#{severity}, message, progname, &block) # add(DEBUG, message, progname, &block) - end # end - # - def #{severity.downcase}? # def debug? - #{severity} >= @level # DEBUG >= @level - end # end + class_eval <<-EOT, __FILE__, __LINE__ + 1 + def #{severity.downcase}(message = nil, progname = nil, &block) # def debug(message = nil, progname = nil, &block) + add(#{severity}, message, progname, &block) # add(DEBUG, message, progname, &block) + end # end + + def #{severity.downcase}? # def debug? + #{severity} >= @level # DEBUG >= @level + end # end EOT end diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb index 86e66e0588..4bac8292e2 100644 --- a/activesupport/lib/active_support/callbacks.rb +++ b/activesupport/lib/active_support/callbacks.rb @@ -204,7 +204,7 @@ module ActiveSupport module ClassMethods def define_callbacks(*callbacks) callbacks.each do |callback| - class_eval <<-"end_eval" + class_eval <<-"end_eval", __FILE__, __LINE__ + 1 def self.#{callback}(*methods, &block) # def self.before_save(*methods, &block) callbacks = CallbackChain.build(:#{callback}, *methods, &block) # callbacks = CallbackChain.build(:before_save, *methods, &block) @#{callback}_callbacks ||= CallbackChain.new # @before_save_callbacks ||= CallbackChain.new diff --git a/activesupport/lib/active_support/concurrent_hash.rb b/activesupport/lib/active_support/concurrent_hash.rb new file mode 100644 index 0000000000..c9f9b16da3 --- /dev/null +++ b/activesupport/lib/active_support/concurrent_hash.rb @@ -0,0 +1,26 @@ +module ActiveSupport + class ConcurrentHash + def initialize(hash = {}) + @backup_cache = hash.dup + @frozen_cache = hash.dup.freeze + @mutex = Mutex.new + end + + def []=(k,v) + @mutex.synchronize { @backup_cache[k] = v } + @frozen_cache = @backup_cache.dup.freeze + end + + def [](k) + if @frozen_cache.key?(k) + @frozen_cache[k] + else + @mutex.synchronize { @backup_cache[k] } + end + end + + def empty? + @backup_cache.empty? + end + end +end diff --git a/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb index c795871474..75e481fc54 100644 --- a/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb +++ b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb @@ -10,7 +10,7 @@ class Class def cattr_reader(*syms) syms.flatten.each do |sym| next if sym.is_a?(Hash) - class_eval(<<-EOS, __FILE__, __LINE__) + class_eval(<<-EOS, __FILE__, __LINE__ + 1) unless defined? @@#{sym} # unless defined? @@hair_colors @@#{sym} = nil # @@hair_colors = nil end # end @@ -29,7 +29,7 @@ class Class def cattr_writer(*syms) options = syms.extract_options! syms.flatten.each do |sym| - class_eval(<<-EOS, __FILE__, __LINE__) + class_eval(<<-EOS, __FILE__, __LINE__ + 1) unless defined? @@#{sym} # unless defined? @@hair_colors @@#{sym} = nil # @@hair_colors = nil end # end diff --git a/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb b/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb index 000ccf4d55..d893818695 100644 --- a/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb +++ b/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb @@ -8,7 +8,7 @@ class Class def superclass_delegating_reader(*names) class_name_to_stop_searching_on = self.superclass.name.blank? ? "Object" : self.superclass.name names.each do |name| - class_eval <<-EOS + class_eval(<<-EOS, __FILE__, __LINE__ + 1) def self.#{name} # def self.only_reader if defined?(@#{name}) # if defined?(@only_reader) @#{name} # @only_reader @@ -32,10 +32,10 @@ class Class def superclass_delegating_writer(*names) names.each do |name| - class_eval <<-EOS - def self.#{name}=(value) # def self.only_writer=(value) - @#{name} = value # @only_writer = value - end # end + class_eval(<<-EOS, __FILE__, __LINE__ + 1) + def self.#{name}=(value) # def self.property=(value) + @#{name} = value # @property = value + end # end EOS end end diff --git a/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb b/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb index 1794afe77c..70fdde3a58 100644 --- a/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb +++ b/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb @@ -10,14 +10,14 @@ class Class # :nodoc: def class_inheritable_reader(*syms) syms.each do |sym| next if sym.is_a?(Hash) - class_eval <<-EOS - def self.#{sym} # def self.before_add_for_comments - read_inheritable_attribute(:#{sym}) # read_inheritable_attribute(:before_add_for_comments) - end # end - # - def #{sym} # def before_add_for_comments - self.class.#{sym} # self.class.before_add_for_comments - end # end + class_eval(<<-EOS, __FILE__, __LINE__ + 1) + def self.#{sym} # def self.after_add + read_inheritable_attribute(:#{sym}) # read_inheritable_attribute(:after_add) + end # end + + def #{sym} # def after_add + self.class.#{sym} # self.class.after_add + end # end EOS end end @@ -25,7 +25,7 @@ class Class # :nodoc: def class_inheritable_writer(*syms) options = syms.extract_options! syms.each do |sym| - class_eval <<-EOS + class_eval(<<-EOS, __FILE__, __LINE__ + 1) def self.#{sym}=(obj) # def self.color=(obj) write_inheritable_attribute(:#{sym}, obj) # write_inheritable_attribute(:color, obj) end # end @@ -42,7 +42,7 @@ class Class # :nodoc: def class_inheritable_array_writer(*syms) options = syms.extract_options! syms.each do |sym| - class_eval <<-EOS + class_eval(<<-EOS, __FILE__, __LINE__ + 1) def self.#{sym}=(obj) # def self.levels=(obj) write_inheritable_array(:#{sym}, obj) # write_inheritable_array(:levels, obj) end # end @@ -59,7 +59,7 @@ class Class # :nodoc: def class_inheritable_hash_writer(*syms) options = syms.extract_options! syms.each do |sym| - class_eval <<-EOS + class_eval(<<-EOS, __FILE__, __LINE__ + 1) def self.#{sym}=(obj) # def self.nicknames=(obj) write_inheritable_hash(:#{sym}, obj) # write_inheritable_hash(:nicknames, obj) end # end diff --git a/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb b/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb index 9402cb8534..137590d286 100644 --- a/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb +++ b/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb @@ -14,7 +14,7 @@ class Module def mattr_reader(*syms) syms.each do |sym| next if sym.is_a?(Hash) - class_eval(<<-EOS, __FILE__, __LINE__) + class_eval(<<-EOS, __FILE__, __LINE__ + 1) unless defined? @@#{sym} # unless defined? @@pagination_options @@#{sym} = nil # @@pagination_options = nil end # end @@ -33,7 +33,7 @@ class Module def mattr_writer(*syms) options = syms.extract_options! syms.each do |sym| - class_eval(<<-EOS, __FILE__, __LINE__) + class_eval(<<-EOS, __FILE__, __LINE__ + 1) unless defined? @@#{sym} # unless defined? @@pagination_options @@#{sym} = nil # @@pagination_options = nil end # end diff --git a/activesupport/lib/active_support/core_ext/proc.rb b/activesupport/lib/active_support/core_ext/proc.rb index 2ca23f62ef..5c29cc32a2 100644 --- a/activesupport/lib/active_support/core_ext/proc.rb +++ b/activesupport/lib/active_support/core_ext/proc.rb @@ -3,9 +3,9 @@ class Proc #:nodoc: block, time = self, Time.now (class << object; self end).class_eval do method_name = "__bind_#{time.to_i}_#{time.usec}" - define_method(method_name, &block) - method = instance_method(method_name) - remove_method(method_name) + define_method(method_name, &block) # define_method("__bind_1230458026_720454", &block) + method = instance_method(method_name) # method = instance_method("__bind_1230458026_720454") + remove_method(method_name) # remove_method("__bind_1230458026_720454") method end.bind(object) end diff --git a/activesupport/lib/active_support/core_ext/string/multibyte.rb b/activesupport/lib/active_support/core_ext/string/multibyte.rb index a4caa83b74..8f8f0968fd 100644 --- a/activesupport/lib/active_support/core_ext/string/multibyte.rb +++ b/activesupport/lib/active_support/core_ext/string/multibyte.rb @@ -55,7 +55,11 @@ module ActiveSupport #:nodoc: unless '1.8.7 and later'.respond_to?(:chars) def chars - ActiveSupport::Deprecation.warn('String#chars has been deprecated in favor of String#mb_chars.', caller) + # FIXME: + # ActiveSupport::Deprecation refers to RAILS_ENV + # and is a show stopper for 3rd party applications + # that only want ActiveSupport + ActiveSupport::Deprecation.warn('String#chars has been deprecated in favor of String#mb_chars.', caller) if defined?(ActiveSupport::Deprecation) mb_chars end end diff --git a/activesupport/lib/active_support/deprecation.rb b/activesupport/lib/active_support/deprecation.rb index d20151661b..202b46ce7a 100644 --- a/activesupport/lib/active_support/deprecation.rb +++ b/activesupport/lib/active_support/deprecation.rb @@ -89,7 +89,7 @@ module ActiveSupport method_names = method_names + options.keys method_names.each do |method_name| alias_method_chain(method_name, :deprecation) do |target, punctuation| - class_eval(<<-EOS, __FILE__, __LINE__) + class_eval(<<-EOS, __FILE__, __LINE__ + 1) def #{target}_with_deprecation#{punctuation}(*args, &block) # def generate_secret_with_deprecation(*args, &block) ::ActiveSupport::Deprecation.warn( # ::ActiveSupport::Deprecation.warn( self.class.deprecated_method_warning( # self.class.deprecated_method_warning( diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb index 952b4d8063..4ffb5d9520 100644 --- a/activesupport/lib/active_support/memoizable.rb +++ b/activesupport/lib/active_support/memoizable.rb @@ -58,7 +58,7 @@ module ActiveSupport original_method = :"_unmemoized_#{symbol}" memoized_ivar = ActiveSupport::Memoizable.memoized_ivar_for(symbol) - class_eval <<-EOS, __FILE__, __LINE__ + class_eval <<-EOS, __FILE__, __LINE__ + 1 include InstanceMethods # include InstanceMethods # if method_defined?(:#{original_method}) # if method_defined?(:_unmemoized_mime_type) diff --git a/activesupport/lib/active_support/mini.rb b/activesupport/lib/active_support/mini.rb new file mode 100644 index 0000000000..fe7ba48e58 --- /dev/null +++ b/activesupport/lib/active_support/mini.rb @@ -0,0 +1,9 @@ +$LOAD_PATH.unshift File.dirname(__FILE__) + +require "core_ext/blank" +# whole object.rb pulls up rarely used introspection extensions +require "core_ext/object/metaclass" +require 'core_ext/array' +require 'core_ext/hash' +require 'core_ext/module/attribute_accessors' +require 'core_ext/string/inflections' \ No newline at end of file diff --git a/activesupport/lib/active_support/multibyte/unicode_database.rb b/activesupport/lib/active_support/multibyte/unicode_database.rb index a08f38cdbb..074ad8613a 100644 --- a/activesupport/lib/active_support/multibyte/unicode_database.rb +++ b/activesupport/lib/active_support/multibyte/unicode_database.rb @@ -23,11 +23,11 @@ module ActiveSupport #:nodoc: # Lazy load the Unicode database so it's only loaded when it's actually used ATTRIBUTES.each do |attr_name| - class_eval(<<-EOS, __FILE__, __LINE__) - def #{attr_name} # def codepoints - load # load - @#{attr_name} # @codepoints - end # end + class_eval(<<-EOS, __FILE__, __LINE__ + 1) + def #{attr_name} # def codepoints + load # load + @#{attr_name} # @codepoints + end # end EOS end diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index 1a59b2a08d..3a5a083629 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -237,10 +237,10 @@ module ActiveSupport end %w(year mon month day mday wday yday hour min sec to_date).each do |method_name| - class_eval <<-EOV - def #{method_name} # def year - time.#{method_name} # time.year - end # end + class_eval <<-EOV, __FILE__, __LINE__ + 1 + def #{method_name} # def month + time.#{method_name} # time.month + end # end EOV end -- cgit v1.2.3 From a0f2b1d95d3785de92ae271fd7ea23e91c0cadc6 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 27 Jan 2009 18:17:39 -0600 Subject: Reorganize ActionController folder structure --- activesupport/lib/active_support/memoizable.rb | 38 ++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb index 4ffb5d9520..8e9abeaf91 100644 --- a/activesupport/lib/active_support/memoizable.rb +++ b/activesupport/lib/active_support/memoizable.rb @@ -1,4 +1,42 @@ module ActiveSupport + class ConcurrentHash + def initialize(hash = {}) + @backup_cache = hash.dup + @frozen_cache = hash.dup.freeze + @mutex = Mutex.new + end + + def []=(k,v) + @mutex.synchronize { @backup_cache[k] = v } + @frozen_cache = @backup_cache.dup.freeze + end + + def [](k) + if @frozen_cache.key?(k) + @frozen_cache[k] + else + @mutex.synchronize { @backup_cache[k] } + end + end + + def empty? + @backup_cache.empty? + end + end + + module SafelyMemoizable + def safely_memoize(*symbols) + symbols.each do |symbol| + class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{symbol}(*args) + memoized = @_memoized_#{symbol} || ::ActiveSupport::ConcurrentHash.new + memoized[args] ||= memoized_#{symbol}(*args) + end + RUBY + end + end + end + module Memoizable def self.memoized_ivar_for(symbol) "@_memoized_#{symbol.to_s.sub(/\?\Z/, '_query').sub(/!\Z/, '_bang')}".to_sym -- cgit v1.2.3 From 8da52b13b5a565d4c41c3e3b3f2562f3f1852a56 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sat, 31 Jan 2009 14:44:04 -0800 Subject: Remove duplicate ConcurrentHash --- activesupport/lib/active_support/memoizable.rb | 25 ------------------------- 1 file changed, 25 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb index 8e9abeaf91..bd9dbb60fc 100644 --- a/activesupport/lib/active_support/memoizable.rb +++ b/activesupport/lib/active_support/memoizable.rb @@ -1,29 +1,4 @@ module ActiveSupport - class ConcurrentHash - def initialize(hash = {}) - @backup_cache = hash.dup - @frozen_cache = hash.dup.freeze - @mutex = Mutex.new - end - - def []=(k,v) - @mutex.synchronize { @backup_cache[k] = v } - @frozen_cache = @backup_cache.dup.freeze - end - - def [](k) - if @frozen_cache.key?(k) - @frozen_cache[k] - else - @mutex.synchronize { @backup_cache[k] } - end - end - - def empty? - @backup_cache.empty? - end - end - module SafelyMemoizable def safely_memoize(*symbols) symbols.each do |symbol| -- cgit v1.2.3 From 44cdf0c5fe080d470429ab0640af25e927244907 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Mon, 2 Feb 2009 09:54:23 -0800 Subject: Some merge cleanup --- activesupport/test/new_callbacks_test.rb | 121 +++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 activesupport/test/new_callbacks_test.rb (limited to 'activesupport') diff --git a/activesupport/test/new_callbacks_test.rb b/activesupport/test/new_callbacks_test.rb new file mode 100644 index 0000000000..e0edf262fc --- /dev/null +++ b/activesupport/test/new_callbacks_test.rb @@ -0,0 +1,121 @@ +# require 'abstract_unit' +require 'test/unit' +$:.unshift "#{File.dirname(__FILE__)}/../lib" +require 'active_support' + +class Record + include ActiveSupport::Callbacks + define_callbacks :save +end + +class AroundPerson < Record + attr_reader :history + + save_callback :before, :nope, :if => :no + save_callback :before, :nope, :unless => :yes + save_callback :after, :tweedle + save_callback :before, "tweedle_dee" + save_callback :before, proc {|m| m.history << "yup" } + save_callback :before, :nope, :if => proc { false } + save_callback :before, :nope, :unless => proc { true } + save_callback :before, :yup, :if => proc { true } + save_callback :before, :yup, :unless => proc { false } + save_callback :around, :tweedle_dum + save_callback :around, :w0tyes, :if => :yes + save_callback :around, :w0tno, :if => :no + save_callback :around, :tweedle_deedle + + def no; false; end + def yes; true; end + + def nope + @history << "boom" + end + + def yup + @history << "yup" + end + + def w0tyes + @history << "w0tyes before" + yield + @history << "w0tyes after" + end + + def w0tno + @history << "boom" + yield + end + + def tweedle_dee + @history << "tweedle dee" + end + + def tweedle_dum + @history << "tweedle dum pre" + yield + @history << "tweedle dum post" + end + + def tweedle + @history << "tweedle" + end + + def tweedle_deedle + @history << "tweedle deedle pre" + yield + @history << "tweedle deedle post" + end + + def initialize + @history = [] + end + + def save + _run_save_callbacks do + @history << "running" + end + end +end + +class Foo + include ActiveSupport::Callbacks + define_callbacks :save +end + +class Bar < Foo + save_callback(:before) {|s| puts "Before" } +end + +class Baz < Bar + save_callback(:after) {|s| puts "After"} +end + +class Bat < Baz + def inside + _run_save_callbacks do + puts "Inside" + end + end +end + +Bat.new.inside + +# class AroundCallbacksTest < Test::Unit::TestCase +# def test_save_around +# around = AroundPerson.new +# around.save +# assert_equal [ +# "tweedle dee", +# "yup", "yup", "yup", +# "tweedle dum pre", +# "w0tyes before", +# "tweedle deedle pre", +# "running", +# "tweedle deedle post", +# "w0tyes after", +# "tweedle dum post", +# "tweedle" +# ], around.history +# end +# end \ No newline at end of file -- cgit v1.2.3 From 9744f687ccfe83bde52696985030225919c2e681 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Mon, 2 Feb 2009 11:49:32 -0800 Subject: Add support for pending --- activesupport/lib/active_support/test_case.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/test_case.rb b/activesupport/lib/active_support/test_case.rb index 97b2b6ef9c..3d4924f4eb 100644 --- a/activesupport/lib/active_support/test_case.rb +++ b/activesupport/lib/active_support/test_case.rb @@ -12,6 +12,7 @@ require 'active_support/testing/setup_and_teardown' require 'active_support/testing/assertions' require 'active_support/testing/deprecation' require 'active_support/testing/declarative' +require 'active_support/testing/pending' module ActiveSupport class TestCase < ::Test::Unit::TestCase @@ -34,6 +35,7 @@ module ActiveSupport include ActiveSupport::Testing::SetupAndTeardown include ActiveSupport::Testing::Assertions include ActiveSupport::Testing::Deprecation + include ActiveSupport::Testing::Pending extend ActiveSupport::Testing::Declarative end end -- cgit v1.2.3 From ff68430077bc534c03dfe9b2fd7faad3b720a433 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Mon, 2 Feb 2009 12:03:35 -0800 Subject: Whoops. --- .../lib/active_support/testing/pending.rb | 40 ++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 activesupport/lib/active_support/testing/pending.rb (limited to 'activesupport') diff --git a/activesupport/lib/active_support/testing/pending.rb b/activesupport/lib/active_support/testing/pending.rb new file mode 100644 index 0000000000..9b2ab73dd0 --- /dev/null +++ b/activesupport/lib/active_support/testing/pending.rb @@ -0,0 +1,40 @@ +# Some code from jeremymcanally's "pending" +# http://github.com/jeremymcanally/pending/tree/master + +module ActiveSupport + module Testing + module Pending + + @@pending_cases = [] + @@at_exit = false + + def pending(description = "", &block) + if block_given? + failed = false + + begin + block.call + rescue + failed = true + end + + flunk("<#{description}> did not fail.") unless failed + end + + caller[0] =~ (/(.*):(.*):in `(.*)'/) + @@pending_cases << "#{$3} at #{$1}, line #{$2}" + print "P" + + @@at_exit ||= begin + at_exit do + puts "\nPending Cases:" + @@pending_cases.each do |test_case| + puts test_case + end + end + end + end + + end + end +end \ No newline at end of file -- cgit v1.2.3 From d4a817c066ec66ab6f44958a3e10619f952b77e8 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Mon, 2 Feb 2009 14:01:29 -0800 Subject: Make tests pass --- activesupport/test/new_callbacks_test.rb | 121 ------------------------------- 1 file changed, 121 deletions(-) delete mode 100644 activesupport/test/new_callbacks_test.rb (limited to 'activesupport') diff --git a/activesupport/test/new_callbacks_test.rb b/activesupport/test/new_callbacks_test.rb deleted file mode 100644 index e0edf262fc..0000000000 --- a/activesupport/test/new_callbacks_test.rb +++ /dev/null @@ -1,121 +0,0 @@ -# require 'abstract_unit' -require 'test/unit' -$:.unshift "#{File.dirname(__FILE__)}/../lib" -require 'active_support' - -class Record - include ActiveSupport::Callbacks - define_callbacks :save -end - -class AroundPerson < Record - attr_reader :history - - save_callback :before, :nope, :if => :no - save_callback :before, :nope, :unless => :yes - save_callback :after, :tweedle - save_callback :before, "tweedle_dee" - save_callback :before, proc {|m| m.history << "yup" } - save_callback :before, :nope, :if => proc { false } - save_callback :before, :nope, :unless => proc { true } - save_callback :before, :yup, :if => proc { true } - save_callback :before, :yup, :unless => proc { false } - save_callback :around, :tweedle_dum - save_callback :around, :w0tyes, :if => :yes - save_callback :around, :w0tno, :if => :no - save_callback :around, :tweedle_deedle - - def no; false; end - def yes; true; end - - def nope - @history << "boom" - end - - def yup - @history << "yup" - end - - def w0tyes - @history << "w0tyes before" - yield - @history << "w0tyes after" - end - - def w0tno - @history << "boom" - yield - end - - def tweedle_dee - @history << "tweedle dee" - end - - def tweedle_dum - @history << "tweedle dum pre" - yield - @history << "tweedle dum post" - end - - def tweedle - @history << "tweedle" - end - - def tweedle_deedle - @history << "tweedle deedle pre" - yield - @history << "tweedle deedle post" - end - - def initialize - @history = [] - end - - def save - _run_save_callbacks do - @history << "running" - end - end -end - -class Foo - include ActiveSupport::Callbacks - define_callbacks :save -end - -class Bar < Foo - save_callback(:before) {|s| puts "Before" } -end - -class Baz < Bar - save_callback(:after) {|s| puts "After"} -end - -class Bat < Baz - def inside - _run_save_callbacks do - puts "Inside" - end - end -end - -Bat.new.inside - -# class AroundCallbacksTest < Test::Unit::TestCase -# def test_save_around -# around = AroundPerson.new -# around.save -# assert_equal [ -# "tweedle dee", -# "yup", "yup", "yup", -# "tweedle dum pre", -# "w0tyes before", -# "tweedle deedle pre", -# "running", -# "tweedle deedle post", -# "w0tyes after", -# "tweedle dum post", -# "tweedle" -# ], around.history -# end -# end \ No newline at end of file -- cgit v1.2.3 From b1f078bddfecd40cce47b7db738620f2df2219c9 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Tue, 24 Feb 2009 17:25:21 -0800 Subject: First, very early, AbstractController code. More to come --- .../core_ext/class/inheritable_attributes.rb | 79 ++++++++++++++++++++++ 1 file changed, 79 insertions(+) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb b/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb index 70fdde3a58..c121933050 100644 --- a/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb +++ b/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb @@ -138,3 +138,82 @@ class Class # :nodoc: alias inherited_without_inheritable_attributes inherited alias inherited inherited_with_inheritable_attributes end + +class Class + # Defines class-level inheritable attribute reader. Attributes are available to subclasses, + # each subclass has a copy of parent's attribute. + # + # @param *syms Array of attributes to define inheritable reader for. + # @return Array of attributes converted into inheritable_readers. + # + # @api public + # + # @todo Do we want to block instance_reader via :instance_reader => false + # @todo It would be preferable that we do something with a Hash passed in + # (error out or do the same as other methods above) instead of silently + # moving on). In particular, this makes the return value of this function + # less useful. + def extlib_inheritable_reader(*ivars) + instance_reader = ivars.pop[:reader] if ivars.last.is_a?(Hash) + + ivars.each do |ivar| + self.class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def self.#{ivar} + return @#{ivar} if self.object_id == #{self.object_id} || defined?(@#{ivar}) + ivar = superclass.#{ivar} + return nil if ivar.nil? && !#{self}.instance_variable_defined?("@#{ivar}") + @#{ivar} = ivar && !ivar.is_a?(Module) && !ivar.is_a?(Numeric) && !ivar.is_a?(TrueClass) && !ivar.is_a?(FalseClass) ? ivar.dup : ivar + end + RUBY + unless instance_reader == false + self.class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{ivar} + self.class.#{ivar} + end + RUBY + end + end + end + + # Defines class-level inheritable attribute writer. Attributes are available to subclasses, + # each subclass has a copy of parent's attribute. + # + # @param *syms Boolean}]> Array of attributes to + # define inheritable writer for. + # @option syms :instance_writer if true, instance-level inheritable attribute writer is defined. + # @return An Array of the attributes that were made into inheritable writers. + # + # @api public + # + # @todo We need a style for class_eval <<-HEREDOC. I'd like to make it + # class_eval(<<-RUBY, __FILE__, __LINE__), but we should codify it somewhere. + def extlib_inheritable_writer(*ivars) + instance_writer = ivars.pop[:instance_writer] if ivars.last.is_a?(Hash) + ivars.each do |ivar| + self.class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def self.#{ivar}=(obj) + @#{ivar} = obj + end + RUBY + unless instance_writer == false + self.class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{ivar}=(obj) self.class.#{ivar} = obj end + RUBY + end + end + end + + # Defines class-level inheritable attribute accessor. Attributes are available to subclasses, + # each subclass has a copy of parent's attribute. + # + # @param *syms Boolean}]> Array of attributes to + # define inheritable accessor for. + # @option syms :instance_writer if true, instance-level inheritable attribute writer is defined. + # @return An Array of attributes turned into inheritable accessors. + # + # @api public + def extlib_inheritable_accessor(*syms) + class_inheritable_reader(*syms) + class_inheritable_writer(*syms) + end +end \ No newline at end of file -- cgit v1.2.3 From c16c7a8de4e543a92de10a138bdd7caa5ac902d7 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Fri, 27 Feb 2009 19:25:45 -0800 Subject: Add support for callbacks --- activesupport/lib/active_support.rb | 1 + activesupport/lib/active_support/new_callbacks.rb | 477 +++++++++++++++++++++ .../test/new_callback_inheritance_test.rb | 115 +++++ activesupport/test/new_callbacks_test.rb | 382 +++++++++++++++++ 4 files changed, 975 insertions(+) create mode 100644 activesupport/lib/active_support/new_callbacks.rb create mode 100644 activesupport/test/new_callback_inheritance_test.rb create mode 100644 activesupport/test/new_callbacks_test.rb (limited to 'activesupport') diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb index 62d538e2d5..dbd30f9271 100644 --- a/activesupport/lib/active_support.rb +++ b/activesupport/lib/active_support.rb @@ -32,6 +32,7 @@ module ActiveSupport autoload :BufferedLogger, 'active_support/buffered_logger' autoload :Cache, 'active_support/cache' autoload :Callbacks, 'active_support/callbacks' + autoload :NewCallbacks, 'active_support/new_callbacks' autoload :ConcurrentHash, 'active_support/concurrent_hash' autoload :Deprecation, 'active_support/deprecation' autoload :Duration, 'active_support/duration' diff --git a/activesupport/lib/active_support/new_callbacks.rb b/activesupport/lib/active_support/new_callbacks.rb new file mode 100644 index 0000000000..cf717bfbb9 --- /dev/null +++ b/activesupport/lib/active_support/new_callbacks.rb @@ -0,0 +1,477 @@ +module ActiveSupport + # Callbacks are hooks into the lifecycle of an object that allow you to trigger logic + # before or after an alteration of the object state. + # + # Mixing in this module allows you to define callbacks in your class. + # + # Example: + # class Storage + # include ActiveSupport::Callbacks + # + # define_callbacks :save + # end + # + # class ConfigStorage < Storage + # save_callback :before, :saving_message + # def saving_message + # puts "saving..." + # end + # + # save_callback :after do |object| + # puts "saved" + # end + # + # def save + # _run_save_callbacks do + # puts "- save" + # end + # end + # end + # + # config = ConfigStorage.new + # config.save + # + # Output: + # saving... + # - save + # saved + # + # Callbacks from parent classes are inherited. + # + # Example: + # class Storage + # include ActiveSupport::Callbacks + # + # define_callbacks :save + # + # save_callback :before, :prepare + # def prepare + # puts "preparing save" + # end + # end + # + # class ConfigStorage < Storage + # save_callback :before, :saving_message + # def saving_message + # puts "saving..." + # end + # + # save_callback :after do |object| + # puts "saved" + # end + # + # def save + # _run_save_callbacks do + # puts "- save" + # end + # end + # end + # + # config = ConfigStorage.new + # config.save + # + # Output: + # preparing save + # saving... + # - save + # saved + module NewCallbacks + def self.included(klass) + klass.extend ClassMethods + end + + def run_callbacks(kind, options = {}, &blk) + send("_run_#{kind}_callbacks", &blk) + end + + class Callback + @@_callback_sequence = 0 + + attr_accessor :filter, :kind, :name, :options, :per_key, :klass + def initialize(filter, kind, options, klass, name) + @kind, @klass = kind, klass + @name = name + + normalize_options!(options) + + @per_key = options.delete(:per_key) + @raw_filter, @options = filter, options + @filter = _compile_filter(filter) + @compiled_options = _compile_options(options) + @callback_id = next_id + + _compile_per_key_options + end + + def clone(klass) + obj = super() + obj.klass = klass + obj.per_key = @per_key.dup + obj.options = @options.dup + obj.per_key[:if] = @per_key[:if].dup + obj.per_key[:unless] = @per_key[:unless].dup + obj.options[:if] = @options[:if].dup + obj.options[:unless] = @options[:unless].dup + obj + end + + def normalize_options!(options) + options[:if] = Array(options[:if]) + options[:unless] = Array(options[:unless]) + + options[:per_key] ||= {} + options[:per_key][:if] = Array(options[:per_key][:if]) + options[:per_key][:unless] = Array(options[:per_key][:unless]) + end + + def next_id + @@_callback_sequence += 1 + end + + def matches?(_kind, _name, _filter) + @kind == _kind && + @name == _name && + @filter == _filter + end + + def _update_filter(filter_options, new_options) + filter_options[:if].push(new_options[:unless]) if new_options.key?(:unless) + filter_options[:unless].push(new_options[:if]) if new_options.key?(:if) + end + + def recompile!(_options, _per_key) + _update_filter(self.options, _options) + _update_filter(self.per_key, _per_key) + + @callback_id = next_id + @filter = _compile_filter(@raw_filter) + @compiled_options = _compile_options(@options) + _compile_per_key_options + end + + def _compile_per_key_options + key_options = _compile_options(@per_key) + + @klass.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 + def _one_time_conditions_valid_#{@callback_id}? + true #{key_options[0]} + end + RUBY_EVAL + end + + # This will supply contents for before and around filters, and no + # contents for after filters (for the forward pass). + def start(key = nil, options = {}) + object, terminator = (options || {}).values_at(:object, :terminator) + + return if key && !object.send("_one_time_conditions_valid_#{@callback_id}?") + + terminator ||= false + + # options[0] is the compiled form of supplied conditions + # options[1] is the "end" for the conditional + + if @kind == :before || @kind == :around + if @kind == :before + # if condition # before_save :filter_name, :if => :condition + # filter_name + # end + filter = <<-RUBY_EVAL + unless halted + result = #{@filter} + halted ||= (#{terminator}) + end + RUBY_EVAL + [@compiled_options[0], filter, @compiled_options[1]].compact.join("\n") + else + # Compile around filters with conditions into proxy methods + # that contain the conditions. + # + # For `around_save :filter_name, :if => :condition': + # + # def _conditional_callback_save_17 + # if condition + # filter_name do + # yield self + # end + # else + # yield self + # end + # end + + name = "_conditional_callback_#{@kind}_#{next_id}" + txt = <<-RUBY_EVAL + def #{name}(halted) + #{@compiled_options[0] || "if true"} && !halted + #{@filter} do + yield self + end + else + yield self + end + end + RUBY_EVAL + @klass.class_eval(txt) + "#{name}(halted) do" + end + end + end + + # This will supply contents for around and after filters, but not + # before filters (for the backward pass). + def end(key = nil, options = {}) + object = (options || {})[:object] + + return if key && !object.send("_one_time_conditions_valid_#{@callback_id}?") + + if @kind == :around || @kind == :after + # if condition # after_save :filter_name, :if => :condition + # filter_name + # end + if @kind == :after + [@compiled_options[0], @filter, @compiled_options[1]].compact.join("\n") + else + "end" + end + end + end + + private + # Options support the same options as filters themselves (and support + # symbols, string, procs, and objects), so compile a conditional + # expression based on the options + def _compile_options(options) + return [] if options[:if].empty? && options[:unless].empty? + + conditions = [] + + unless options[:if].empty? + conditions << Array(_compile_filter(options[:if])) + end + + unless options[:unless].empty? + conditions << Array(_compile_filter(options[:unless])).map {|f| "!#{f}"} + end + + ["if #{conditions.flatten.join(" && ")}", "end"] + end + + # Filters support: + # Arrays:: Used in conditions. This is used to specify + # multiple conditions. Used internally to + # merge conditions from skip_* filters + # Symbols:: A method to call + # Strings:: Some content to evaluate + # Procs:: A proc to call with the object + # Objects:: An object with a before_foo method on it to call + # + # All of these objects are compiled into methods and handled + # the same after this point: + # Arrays:: Merged together into a single filter + # Symbols:: Already methods + # Strings:: class_eval'ed into methods + # Procs:: define_method'ed into methods + # Objects:: + # a method is created that calls the before_foo method + # on the object. + def _compile_filter(filter) + method_name = "_callback_#{@kind}_#{next_id}" + case filter + when Array + filter.map {|f| _compile_filter(f)} + when Symbol + filter + when Proc + @klass.send(:define_method, method_name, &filter) + method_name << (filter.arity == 1 ? "(self)" : "") + when String + @klass.class_eval <<-RUBY_EVAL + def #{method_name} + #{filter} + end + RUBY_EVAL + method_name + else + kind, name = @kind, @name + @klass.send(:define_method, method_name) do + filter.send("#{kind}_#{name}", self) + end + method_name + end + end + end + + # This method_missing is supplied to catch callbacks with keys and create + # the appropriate callback for future use. + def method_missing(meth, *args, &blk) + if meth.to_s =~ /_run__([\w:]+)__(\w+)__(\w+)__callbacks/ + return self.class._create_and_run_keyed_callback($1, $2.to_sym, $3.to_sym, self, &blk) + end + super + end + + # An Array with a compile method + class CallbackChain < Array + def initialize(symbol) + @symbol = symbol + end + + def compile(key = nil, options = {}) + method = [] + method << "halted = false" + each do |callback| + method << callback.start(key, options) + end + method << "yield self if block_given?" + reverse_each do |callback| + method << callback.end(key, options) + end + method.compact.join("\n") + end + + def clone(klass) + chain = CallbackChain.new(@symbol) + chain.push(*map {|c| c.clone(klass)}) + end + end + + module ClassMethods + CHAINS = {:before => :before, :around => :before, :after => :after} + + # Make the _run_save_callbacks method. The generated method takes + # a block that it'll yield to. It'll call the before and around filters + # in order, yield the block, and then run the after filters. + # + # _run_save_callbacks do + # save + # end + # + # The _run_save_callbacks method can optionally take a key, which + # will be used to compile an optimized callback method for each + # key. See #define_callbacks for more information. + def _define_runner(symbol, str, options) + str = <<-RUBY_EVAL + def _run_#{symbol}_callbacks(key = nil) + if key + send("_run__\#{self.class.name.split("::").last}__#{symbol}__\#{key}__callbacks") { yield if block_given? } + else + #{str} + end + end + RUBY_EVAL + + class_eval str, __FILE__, __LINE__ + 1 + + before_name, around_name, after_name = + options.values_at(:before, :after, :around) + end + + # This is called the first time a callback is called with a particular + # key. It creates a new callback method for the key, calculating + # which callbacks can be omitted because of per_key conditions. + def _create_and_run_keyed_callback(klass, kind, key, obj, &blk) + @_keyed_callbacks ||= {} + @_keyed_callbacks[[kind, key]] ||= begin + str = self.send("_#{kind}_callbacks").compile(key, :object => obj, :terminator => self.send("_#{kind}_terminator")) + + self.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 + def _run__#{klass.split("::").last}__#{kind}__#{key}__callbacks + #{str} + end + RUBY_EVAL + + true + end + + obj.send("_run__#{klass.split("::").last}__#{kind}__#{key}__callbacks", &blk) + end + + # Define callbacks. + # + # Creates a _callback method that you can use to add callbacks. + # + # Syntax: + # save_callback :before, :before_meth + # save_callback :after, :after_meth, :if => :condition + # save_callback :around {|r| stuff; yield; stuff } + # + # The _callback method also updates the _run__callbacks + # method, which is the public API to run the callbacks. + # + # Also creates a skip__callback method that you can use to skip + # callbacks. + # + # When creating or skipping callbacks, you can specify conditions that + # are always the same for a given key. For instance, in ActionPack, + # we convert :only and :except conditions into per-key conditions. + # + # before_filter :authenticate, :except => "index" + # becomes + # dispatch_callback :before, :authenticate, :per_key => {:unless => proc {|c| c.action_name == "index"}} + # + # Per-Key conditions are evaluated only once per use of a given key. + # In the case of the above example, you would do: + # + # run_dispatch_callbacks(action_name) { ... dispatch stuff ... } + # + # In that case, each action_name would get its own compiled callback + # method that took into consideration the per_key conditions. This + # is a speed improvement for ActionPack. + def define_callbacks(*symbols) + terminator = symbols.pop if symbols.last.is_a?(String) + symbols.each do |symbol| + self.class_inheritable_accessor("_#{symbol}_terminator") + self.send("_#{symbol}_terminator=", terminator) + self.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 + class_inheritable_accessor :_#{symbol}_callbacks + self._#{symbol}_callbacks = CallbackChain.new(:#{symbol}) + + def self.#{symbol}_callback(*filters, &blk) + type = [:before, :after, :around].include?(filters.first) ? filters.shift : :before + options = filters.last.is_a?(Hash) ? filters.pop : {} + filters.unshift(blk) if block_given? + + filters.map! do |filter| + # overrides parent class + self._#{symbol}_callbacks.delete_if {|c| c.matches?(type, :#{symbol}, filter)} + Callback.new(filter, type, options.dup, self, :#{symbol}) + end + self._#{symbol}_callbacks.push(*filters) + _define_runner(:#{symbol}, + self._#{symbol}_callbacks.compile(nil, :terminator => _#{symbol}_terminator), + options) + end + + def self.skip_#{symbol}_callback(*filters, &blk) + type = [:before, :after, :around].include?(filters.first) ? filters.shift : :before + options = filters.last.is_a?(Hash) ? filters.pop : {} + filters.unshift(blk) if block_given? + filters.each do |filter| + self._#{symbol}_callbacks = self._#{symbol}_callbacks.clone(self) + + filter = self._#{symbol}_callbacks.find {|c| c.matches?(type, :#{symbol}, filter) } + per_key = options[:per_key] || {} + if filter + filter.recompile!(options, per_key) + else + self._#{symbol}_callbacks.delete(filter) + end + _define_runner(:#{symbol}, + self._#{symbol}_callbacks.compile(nil, :terminator => _#{symbol}_terminator), + options) + end + + end + + def self.reset_#{symbol}_callbacks + self._#{symbol}_callbacks = CallbackChain.new(:#{symbol}) + _define_runner(:#{symbol}, self._#{symbol}_callbacks.compile, {}) + end + + self.#{symbol}_callback(:before) + RUBY_EVAL + end + end + end + end +end diff --git a/activesupport/test/new_callback_inheritance_test.rb b/activesupport/test/new_callback_inheritance_test.rb new file mode 100644 index 0000000000..95020389b0 --- /dev/null +++ b/activesupport/test/new_callback_inheritance_test.rb @@ -0,0 +1,115 @@ +require 'test/unit' +$:.unshift "#{File.dirname(__FILE__)}/../lib" +require 'active_support' + +class GrandParent + include ActiveSupport::NewCallbacks + + attr_reader :log, :action_name + def initialize(action_name) + @action_name, @log = action_name, [] + end + + define_callbacks :dispatch + dispatch_callback :before, :before1, :before2, :per_key => {:if => proc {|c| c.action_name == "index" || c.action_name == "update" }} + dispatch_callback :after, :after1, :after2, :per_key => {:if => proc {|c| c.action_name == "update" || c.action_name == "delete" }} + + def before1 + @log << "before1" + end + + def before2 + @log << "before2" + end + + def after1 + @log << "after1" + end + + def after2 + @log << "after2" + end + + def dispatch + _run_dispatch_callbacks(action_name) do + @log << action_name + end + self + end +end + +class Parent < GrandParent + skip_dispatch_callback :before, :before2, :per_key => {:unless => proc {|c| c.action_name == "update" }} + skip_dispatch_callback :after, :after2, :per_key => {:unless => proc {|c| c.action_name == "delete" }} +end + +class Child < GrandParent + skip_dispatch_callback :before, :before2, :per_key => {:unless => proc {|c| c.action_name == "update" }}, :if => :state_open? + + def state_open? + @state == :open + end + + def initialize(action_name, state) + super(action_name) + @state = state + end +end + + +class BasicCallbacksTest < Test::Unit::TestCase + def setup + @index = GrandParent.new("index").dispatch + @update = GrandParent.new("update").dispatch + @delete = GrandParent.new("delete").dispatch + @unknown = GrandParent.new("unknown").dispatch + end + + def test_basic_per_key1 + assert_equal %w(before1 before2 index), @index.log + end + + def test_basic_per_key2 + assert_equal %w(before1 before2 update after2 after1), @update.log + end + + def test_basic_per_key3 + assert_equal %w(delete after2 after1), @delete.log + end +end + +class InheritedCallbacksTest < Test::Unit::TestCase + def setup + @index = Parent.new("index").dispatch + @update = Parent.new("update").dispatch + @delete = Parent.new("delete").dispatch + @unknown = Parent.new("unknown").dispatch + end + + def test_inherited_excluded + assert_equal %w(before1 index), @index.log + end + + def test_inherited_not_excluded + assert_equal %w(before1 before2 update after1), @update.log + end + + def test_partially_excluded + assert_equal %w(delete after2 after1), @delete.log + end +end + +class InheritedCallbacksTest2 < Test::Unit::TestCase + def setup + @update1 = Child.new("update", :open).dispatch + @update2 = Child.new("update", :closed).dispatch + end + + def test_crazy_mix_on + assert_equal %w(before1 update after2 after1), @update1.log + end + + def test_crazy_mix_off + assert_equal %w(before1 before2 update after2 after1), @update2.log + end +end \ No newline at end of file diff --git a/activesupport/test/new_callbacks_test.rb b/activesupport/test/new_callbacks_test.rb new file mode 100644 index 0000000000..6948ad23dc --- /dev/null +++ b/activesupport/test/new_callbacks_test.rb @@ -0,0 +1,382 @@ +# require 'abstract_unit' +require 'test/unit' +$:.unshift "#{File.dirname(__FILE__)}/../lib" +require 'active_support' + +class Record + include ActiveSupport::NewCallbacks + + define_callbacks :save + + def self.before_save(*filters, &blk) + save_callback(:before, *filters, &blk) + end + + def self.after_save(*filters, &blk) + save_callback(:after, *filters, &blk) + end + + class << self + def callback_symbol(callback_method) + returning(:"#{callback_method}_method") do |method_name| + define_method(method_name) do + history << [callback_method, :symbol] + end + end + end + + def callback_string(callback_method) + "history << [#{callback_method.to_sym.inspect}, :string]" + end + + def callback_proc(callback_method) + Proc.new { |model| model.history << [callback_method, :proc] } + end + + def callback_object(callback_method) + klass = Class.new + klass.send(:define_method, callback_method) do |model| + model.history << [callback_method, :object] + end + klass.new + end + end + + def history + @history ||= [] + end +end + +class Person < Record + [:before_save, :after_save].each do |callback_method| + callback_method_sym = callback_method.to_sym + send(callback_method, callback_symbol(callback_method_sym)) + send(callback_method, callback_string(callback_method_sym)) + send(callback_method, callback_proc(callback_method_sym)) + send(callback_method, callback_object(callback_method_sym)) + send(callback_method) { |model| model.history << [callback_method_sym, :block] } + end + + def save + _run_save_callbacks {} + end +end + +class PersonSkipper < Person + skip_save_callback :before, :before_save_method, :if => :yes + skip_save_callback :after, :before_save_method, :unless => :yes + skip_save_callback :after, :before_save_method, :if => :no + skip_save_callback :before, :before_save_method, :unless => :no + def yes; true; end + def no; false; end +end + +class ParentController + include ActiveSupport::NewCallbacks + + define_callbacks :dispatch + + dispatch_callback :before, :log, :per_key => {:unless => proc {|c| c.action_name == :index || c.action_name == :show }} + dispatch_callback :after, :log2 + + attr_reader :action_name, :logger + def initialize(action_name) + @action_name, @logger = action_name, [] + end + + def log + @logger << action_name + end + + def log2 + @logger << action_name + end + + def dispatch + _run_dispatch_callbacks(action_name) { + @logger << "Done" + } + self + end +end + +class Child < ParentController + skip_dispatch_callback :before, :log, :per_key => {:if => proc {|c| c.action_name == :update} } + skip_dispatch_callback :after, :log2 +end + +class OneTimeCompile < Record + @@starts_true, @@starts_false = true, false + + def initialize + super + end + + before_save Proc.new {|r| r.history << [:before_save, :starts_true, :if] }, :per_key => {:if => :starts_true} + before_save Proc.new {|r| r.history << [:before_save, :starts_false, :if] }, :per_key => {:if => :starts_false} + before_save Proc.new {|r| r.history << [:before_save, :starts_true, :unless] }, :per_key => {:unless => :starts_true} + before_save Proc.new {|r| r.history << [:before_save, :starts_false, :unless] }, :per_key => {:unless => :starts_false} + + def starts_true + if @@starts_true + @@starts_true = false + return true + end + @@starts_true + end + + def starts_false + unless @@starts_false + @@starts_false = true + return false + end + @@starts_false + end + + def save + _run_save_callbacks(:action) {} + end +end + +class OneTimeCompileTest < Test::Unit::TestCase + def test_optimized_first_compile + around = OneTimeCompile.new + around.save + assert_equal [ + [:before_save, :starts_true, :if], + [:before_save, :starts_true, :unless] + ], around.history + end +end + +class ConditionalPerson < Record + # proc + before_save Proc.new { |r| r.history << [:before_save, :proc] }, :if => Proc.new { |r| true } + before_save Proc.new { |r| r.history << "b00m" }, :if => Proc.new { |r| false } + before_save Proc.new { |r| r.history << [:before_save, :proc] }, :unless => Proc.new { |r| false } + before_save Proc.new { |r| r.history << "b00m" }, :unless => Proc.new { |r| true } + # symbol + before_save Proc.new { |r| r.history << [:before_save, :symbol] }, :if => :yes + before_save Proc.new { |r| r.history << "b00m" }, :if => :no + before_save Proc.new { |r| r.history << [:before_save, :symbol] }, :unless => :no + before_save Proc.new { |r| r.history << "b00m" }, :unless => :yes + # string + before_save Proc.new { |r| r.history << [:before_save, :string] }, :if => 'yes' + before_save Proc.new { |r| r.history << "b00m" }, :if => 'no' + before_save Proc.new { |r| r.history << [:before_save, :string] }, :unless => 'no' + before_save Proc.new { |r| r.history << "b00m" }, :unless => 'yes' + # Combined if and unless + before_save Proc.new { |r| r.history << [:before_save, :combined_symbol] }, :if => :yes, :unless => :no + before_save Proc.new { |r| r.history << "b00m" }, :if => :yes, :unless => :yes + + def yes; true; end + def other_yes; true; end + def no; false; end + def other_no; false; end + + def save + _run_save_callbacks {} + end +end + +class MySuper + include ActiveSupport::NewCallbacks + define_callbacks :save +end + +class AroundPerson < MySuper + attr_reader :history + + save_callback :before, :nope, :if => :no + save_callback :before, :nope, :unless => :yes + save_callback :after, :tweedle + save_callback :before, "tweedle_dee" + save_callback :before, proc {|m| m.history << "yup" } + save_callback :before, :nope, :if => proc { false } + save_callback :before, :nope, :unless => proc { true } + save_callback :before, :yup, :if => proc { true } + save_callback :before, :yup, :unless => proc { false } + save_callback :around, :tweedle_dum + save_callback :around, :w0tyes, :if => :yes + save_callback :around, :w0tno, :if => :no + save_callback :around, :tweedle_deedle + + def no; false; end + def yes; true; end + + def nope + @history << "boom" + end + + def yup + @history << "yup" + end + + def w0tyes + @history << "w0tyes before" + yield + @history << "w0tyes after" + end + + def w0tno + @history << "boom" + yield + end + + def tweedle_dee + @history << "tweedle dee" + end + + def tweedle_dum + @history << "tweedle dum pre" + yield + @history << "tweedle dum post" + end + + def tweedle + @history << "tweedle" + end + + def tweedle_deedle + @history << "tweedle deedle pre" + yield + @history << "tweedle deedle post" + end + + def initialize + @history = [] + end + + def save + _run_save_callbacks do + @history << "running" + end + end +end + +class AroundCallbacksTest < Test::Unit::TestCase + def test_save_around + around = AroundPerson.new + around.save + assert_equal [ + "tweedle dee", + "yup", "yup", "yup", + "tweedle dum pre", + "w0tyes before", + "tweedle deedle pre", + "running", + "tweedle deedle post", + "w0tyes after", + "tweedle dum post", + "tweedle" + ], around.history + end +end + +class SkipCallbacksTest < Test::Unit::TestCase + def test_skip_person + person = PersonSkipper.new + assert_equal [], person.history + person.save + assert_equal [ + [:before_save, :string], + [:before_save, :proc], + [:before_save, :object], + [:before_save, :block], + [:after_save, :block], + [:after_save, :object], + [:after_save, :proc], + [:after_save, :string], + [:after_save, :symbol] + ], person.history + end +end + +class CallbacksTest < Test::Unit::TestCase + def test_save_person + person = Person.new + assert_equal [], person.history + person.save + assert_equal [ + [:before_save, :symbol], + [:before_save, :string], + [:before_save, :proc], + [:before_save, :object], + [:before_save, :block], + [:after_save, :block], + [:after_save, :object], + [:after_save, :proc], + [:after_save, :string], + [:after_save, :symbol] + ], person.history + end +end + +class ConditionalCallbackTest < Test::Unit::TestCase + def test_save_conditional_person + person = ConditionalPerson.new + person.save + assert_equal [ + [:before_save, :proc], + [:before_save, :proc], + [:before_save, :symbol], + [:before_save, :symbol], + [:before_save, :string], + [:before_save, :string], + [:before_save, :combined_symbol], + ], person.history + end +end + +class CallbackTerminator + include ActiveSupport::NewCallbacks + + define_callbacks :save, "result == :halt" + + save_callback :before, :first + save_callback :before, :second + save_callback :around, :around_it + save_callback :before, :third + save_callback :after, :first + save_callback :around, :around_it + save_callback :after, :second + save_callback :around, :around_it + save_callback :after, :third + + + attr_reader :history + def initialize + @history = [] + end + + def around_it + @history << "around1" + yield + @history << "around2" + end + + def first + @history << "first" + end + + def second + @history << "second" + :halt + end + + def third + @history << "third" + end + + def save + _run_save_callbacks + end +end + +class CallbackTerminatorTest < Test::Unit::TestCase + def test_termination + terminator = CallbackTerminator.new + terminator.save + assert_equal ["first", "second", "third", "second", "first"], terminator.history + end +end -- cgit v1.2.3 From 9510070f7859d00b1e47b62c1e06dbf21fca1b9b Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Fri, 27 Feb 2009 19:37:09 -0800 Subject: Fixes multiple conditions --- activesupport/lib/active_support/new_callbacks.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/new_callbacks.rb b/activesupport/lib/active_support/new_callbacks.rb index cf717bfbb9..5f1afc9b3c 100644 --- a/activesupport/lib/active_support/new_callbacks.rb +++ b/activesupport/lib/active_support/new_callbacks.rb @@ -349,7 +349,7 @@ module ActiveSupport # The _run_save_callbacks method can optionally take a key, which # will be used to compile an optimized callback method for each # key. See #define_callbacks for more information. - def _define_runner(symbol, str, options) + def _define_runner(symbol, str, options) str = <<-RUBY_EVAL def _run_#{symbol}_callbacks(key = nil) if key @@ -373,7 +373,7 @@ module ActiveSupport @_keyed_callbacks ||= {} @_keyed_callbacks[[kind, key]] ||= begin str = self.send("_#{kind}_callbacks").compile(key, :object => obj, :terminator => self.send("_#{kind}_terminator")) - + self.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 def _run__#{klass.split("::").last}__#{kind}__#{key}__callbacks #{str} -- cgit v1.2.3 From 6001cea5d70344d4c13b5cff94ee853f5f5462ce Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Tue, 3 Mar 2009 16:42:20 -0800 Subject: Helpers with an initial test --- .../lib/active_support/core_ext/class/inheritable_attributes.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb b/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb index c121933050..2f18666ab9 100644 --- a/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb +++ b/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb @@ -188,7 +188,7 @@ class Class # @todo We need a style for class_eval <<-HEREDOC. I'd like to make it # class_eval(<<-RUBY, __FILE__, __LINE__), but we should codify it somewhere. def extlib_inheritable_writer(*ivars) - instance_writer = ivars.pop[:instance_writer] if ivars.last.is_a?(Hash) + instance_writer = ivars.pop[:writer] if ivars.last.is_a?(Hash) ivars.each do |ivar| self.class_eval <<-RUBY, __FILE__, __LINE__ + 1 def self.#{ivar}=(obj) @@ -213,7 +213,7 @@ class Class # # @api public def extlib_inheritable_accessor(*syms) - class_inheritable_reader(*syms) - class_inheritable_writer(*syms) + extlib_inheritable_reader(*syms) + extlib_inheritable_writer(*syms) end end \ No newline at end of file -- cgit v1.2.3 From 67f9b39bd05678881e200ddeed02b2bce9744ac8 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 12 Mar 2009 13:18:31 -0600 Subject: Use extlib accessor for new callbacks --- activesupport/lib/active_support/new_callbacks.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/new_callbacks.rb b/activesupport/lib/active_support/new_callbacks.rb index 5f1afc9b3c..65d2ddac32 100644 --- a/activesupport/lib/active_support/new_callbacks.rb +++ b/activesupport/lib/active_support/new_callbacks.rb @@ -420,10 +420,10 @@ module ActiveSupport def define_callbacks(*symbols) terminator = symbols.pop if symbols.last.is_a?(String) symbols.each do |symbol| - self.class_inheritable_accessor("_#{symbol}_terminator") + self.extlib_inheritable_accessor("_#{symbol}_terminator") self.send("_#{symbol}_terminator=", terminator) self.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 - class_inheritable_accessor :_#{symbol}_callbacks + extlib_inheritable_accessor :_#{symbol}_callbacks self._#{symbol}_callbacks = CallbackChain.new(:#{symbol}) def self.#{symbol}_callback(*filters, &blk) -- cgit v1.2.3 From fb626ee39065512928c90c396db8b5476c5a7aeb Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Tue, 17 Mar 2009 18:05:08 -0700 Subject: Rework NewCallbacks to not require method_missing --- activesupport/lib/active_support/new_callbacks.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/new_callbacks.rb b/activesupport/lib/active_support/new_callbacks.rb index 65d2ddac32..b93057fe27 100644 --- a/activesupport/lib/active_support/new_callbacks.rb +++ b/activesupport/lib/active_support/new_callbacks.rb @@ -353,7 +353,15 @@ module ActiveSupport str = <<-RUBY_EVAL def _run_#{symbol}_callbacks(key = nil) if key - send("_run__\#{self.class.name.split("::").last}__#{symbol}__\#{key}__callbacks") { yield if block_given? } + name = "_run__\#{self.class.name.split("::").last}__#{symbol}__\#{key}__callbacks" + + if respond_to?(name) + send(name) { yield if block_given? } + else + self.class._create_and_run_keyed_callback( + self.class.name.split("::").last, + :#{symbol}, key, self) { yield if block_given? } + end else #{str} end -- cgit v1.2.3 From 5a8b481f717470b952ac7eb890f260ea98428153 Mon Sep 17 00:00:00 2001 From: Michael Curtis Date: Tue, 10 Mar 2009 12:14:54 -0500 Subject: Time.local instances: Adding 24.hours across the DST boundary adds 24 hours instead of one day [#2066 state:resolved] --- activesupport/CHANGELOG | 5 ++++ .../active_support/core_ext/time/calculations.rb | 14 ++-------- activesupport/test/core_ext/duration_test.rb | 12 ++++++++ activesupport/test/core_ext/time_ext_test.rb | 32 +++++++++++----------- 4 files changed, 36 insertions(+), 27 deletions(-) (limited to 'activesupport') diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index ab40e1a17a..2acce97646 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,3 +1,8 @@ +*Edge + +* Time.local instances: Adding 24.hours across the DST boundary adds 24 hours instead of one day #2066 [Michael Curtis] + + *2.3.2 [Final] (March 15, 2009)* * XmlMini supports LibXML and Nokogiri backends. #2084, #2190 [Bart ten Brinke, Aaron Patterson] diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index 5ed750afcc..d13d0e01a7 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -116,22 +116,14 @@ module ActiveSupport #:nodoc: seconds_to_advance == 0 ? time_advanced_by_date : time_advanced_by_date.since(seconds_to_advance) end - # Returns a new Time representing the time a number of seconds ago, this is basically a wrapper around the Numeric extension + # Returns a new Time representing the time a number of seconds ago def ago(seconds) self.since(-seconds) end - # Returns a new Time representing the time a number of seconds since the instance time, this is basically a wrapper around - # the Numeric extension. + # Returns a new Time representing the time a number of seconds since the instance time def since(seconds) - f = seconds.since(self) - if ActiveSupport::Duration === seconds - f - else - initial_dst = self.dst? ? 1 : 0 - final_dst = f.dst? ? 1 : 0 - (seconds.abs >= 86400 && initial_dst != final_dst) ? f + (initial_dst - final_dst).hours : f - end + self + seconds rescue self.to_datetime.since(seconds) end diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb index ab5a86668e..8954295d10 100644 --- a/activesupport/test/core_ext/duration_test.rb +++ b/activesupport/test/core_ext/duration_test.rb @@ -109,6 +109,18 @@ class DurationTest < ActiveSupport::TestCase ensure Time.zone_default = nil end + + def test_adding_hours_across_dst_boundary + with_env_tz 'CET' do + assert_equal Time.local(2009,3,29,0,0,0) + 24.hours, Time.local(2009,3,30,1,0,0) + end + end + + def test_adding_day_across_dst_boundary + with_env_tz 'CET' do + assert_equal Time.local(2009,3,29,0,0,0) + 1.day, Time.local(2009,3,30,0,0,0) + end + end protected def with_env_tz(new_tz = 'US/Eastern') diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index c0855520e8..1775f81d3d 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -183,26 +183,26 @@ class TimeExtCalculationsTest < Test::Unit::TestCase def test_daylight_savings_time_crossings_backward_start with_env_tz 'US/Eastern' do # dt: US: 2005 April 3rd 4:18am - assert_equal Time.local(2005,4,2,4,18,0), Time.local(2005,4,3,4,18,0).ago(86400), 'dt-1.day=>st' - assert_equal Time.local(2005,4,1,4,18,0), Time.local(2005,4,2,4,18,0).ago(86400), 'st-1.day=>st' + assert_equal Time.local(2005,4,2,3,18,0), Time.local(2005,4,3,4,18,0).ago(24.hours), 'dt-1.day=>st' + assert_equal Time.local(2005,4,1,4,18,0), Time.local(2005,4,2,4,18,0).ago(24.hours), 'st-1.day=>st' end with_env_tz 'NZ' do # dt: New Zealand: 2006 October 1st 4:18am - assert_equal Time.local(2006,9,30,4,18,0), Time.local(2006,10,1,4,18,0).ago(86400), 'dt-1.day=>st' - assert_equal Time.local(2006,9,29,4,18,0), Time.local(2006,9,30,4,18,0).ago(86400), 'st-1.day=>st' + assert_equal Time.local(2006,9,30,3,18,0), Time.local(2006,10,1,4,18,0).ago(24.hours), 'dt-1.day=>st' + assert_equal Time.local(2006,9,29,4,18,0), Time.local(2006,9,30,4,18,0).ago(24.hours), 'st-1.day=>st' end end def test_daylight_savings_time_crossings_backward_end with_env_tz 'US/Eastern' do # st: US: 2005 October 30th 4:03am - assert_equal Time.local(2005,10,29,4,3), Time.local(2005,10,30,4,3,0).ago(86400), 'st-1.day=>dt' - assert_equal Time.local(2005,10,28,4,3), Time.local(2005,10,29,4,3,0).ago(86400), 'dt-1.day=>dt' + assert_equal Time.local(2005,10,29,5,3), Time.local(2005,10,30,4,3,0).ago(24.hours), 'st-1.day=>dt' + assert_equal Time.local(2005,10,28,4,3), Time.local(2005,10,29,4,3,0).ago(24.hours), 'dt-1.day=>dt' end with_env_tz 'NZ' do # st: New Zealand: 2006 March 19th 4:03am - assert_equal Time.local(2006,3,18,4,3), Time.local(2006,3,19,4,3,0).ago(86400), 'st-1.day=>dt' - assert_equal Time.local(2006,3,17,4,3), Time.local(2006,3,18,4,3,0).ago(86400), 'dt-1.day=>dt' + assert_equal Time.local(2006,3,18,5,3), Time.local(2006,3,19,4,3,0).ago(24.hours), 'st-1.day=>dt' + assert_equal Time.local(2006,3,17,4,3), Time.local(2006,3,18,4,3,0).ago(24.hours), 'dt-1.day=>dt' end end @@ -243,13 +243,13 @@ class TimeExtCalculationsTest < Test::Unit::TestCase def test_daylight_savings_time_crossings_forward_start with_env_tz 'US/Eastern' do # st: US: 2005 April 2nd 7:27pm - assert_equal Time.local(2005,4,3,19,27,0), Time.local(2005,4,2,19,27,0).since(86400), 'st+1.day=>dt' - assert_equal Time.local(2005,4,4,19,27,0), Time.local(2005,4,3,19,27,0).since(86400), 'dt+1.day=>dt' + assert_equal Time.local(2005,4,3,20,27,0), Time.local(2005,4,2,19,27,0).since(24.hours), 'st+1.day=>dt' + assert_equal Time.local(2005,4,4,19,27,0), Time.local(2005,4,3,19,27,0).since(24.hours), 'dt+1.day=>dt' end with_env_tz 'NZ' do # st: New Zealand: 2006 September 30th 7:27pm - assert_equal Time.local(2006,10,1,19,27,0), Time.local(2006,9,30,19,27,0).since(86400), 'st+1.day=>dt' - assert_equal Time.local(2006,10,2,19,27,0), Time.local(2006,10,1,19,27,0).since(86400), 'dt+1.day=>dt' + assert_equal Time.local(2006,10,1,20,27,0), Time.local(2006,9,30,19,27,0).since(24.hours), 'st+1.day=>dt' + assert_equal Time.local(2006,10,2,19,27,0), Time.local(2006,10,1,19,27,0).since(24.hours), 'dt+1.day=>dt' end end @@ -295,13 +295,13 @@ class TimeExtCalculationsTest < Test::Unit::TestCase def test_daylight_savings_time_crossings_forward_end with_env_tz 'US/Eastern' do # dt: US: 2005 October 30th 12:45am - assert_equal Time.local(2005,10,31,0,45,0), Time.local(2005,10,30,0,45,0).since(86400), 'dt+1.day=>st' - assert_equal Time.local(2005,11, 1,0,45,0), Time.local(2005,10,31,0,45,0).since(86400), 'st+1.day=>st' + assert_equal Time.local(2005,10,30,23,45,0), Time.local(2005,10,30,0,45,0).since(24.hours), 'dt+1.day=>st' + assert_equal Time.local(2005,11, 1,0,45,0), Time.local(2005,10,31,0,45,0).since(24.hours), 'st+1.day=>st' end with_env_tz 'NZ' do # dt: New Zealand: 2006 March 19th 1:45am - assert_equal Time.local(2006,3,20,1,45,0), Time.local(2006,3,19,1,45,0).since(86400), 'dt+1.day=>st' - assert_equal Time.local(2006,3,21,1,45,0), Time.local(2006,3,20,1,45,0).since(86400), 'st+1.day=>st' + assert_equal Time.local(2006,3,20,0,45,0), Time.local(2006,3,19,1,45,0).since(24.hours), 'dt+1.day=>st' + assert_equal Time.local(2006,3,21,1,45,0), Time.local(2006,3,20,1,45,0).since(24.hours), 'st+1.day=>st' end end -- cgit v1.2.3 From ea8077c6427d208188f9cd11f88ebdc8f60dec28 Mon Sep 17 00:00:00 2001 From: Geoff Buesing Date: Sun, 29 Mar 2009 16:37:13 -0500 Subject: Enhance Time #since and #ago DST tests. --- activesupport/test/core_ext/time_ext_test.rb | 73 ++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 16 deletions(-) (limited to 'activesupport') diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index 1775f81d3d..70cf4a9450 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -183,26 +183,46 @@ class TimeExtCalculationsTest < Test::Unit::TestCase def test_daylight_savings_time_crossings_backward_start with_env_tz 'US/Eastern' do # dt: US: 2005 April 3rd 4:18am - assert_equal Time.local(2005,4,2,3,18,0), Time.local(2005,4,3,4,18,0).ago(24.hours), 'dt-1.day=>st' - assert_equal Time.local(2005,4,1,4,18,0), Time.local(2005,4,2,4,18,0).ago(24.hours), 'st-1.day=>st' + assert_equal Time.local(2005,4,2,3,18,0), Time.local(2005,4,3,4,18,0).ago(24.hours), 'dt-24.hours=>st' + assert_equal Time.local(2005,4,2,3,18,0), Time.local(2005,4,3,4,18,0).ago(86400), 'dt-86400=>st' + assert_equal Time.local(2005,4,2,3,18,0), Time.local(2005,4,3,4,18,0).ago(86400.seconds), 'dt-86400.seconds=>st' + + assert_equal Time.local(2005,4,1,4,18,0), Time.local(2005,4,2,4,18,0).ago(24.hours), 'st-24.hours=>st' + assert_equal Time.local(2005,4,1,4,18,0), Time.local(2005,4,2,4,18,0).ago(86400), 'st-86400=>st' + assert_equal Time.local(2005,4,1,4,18,0), Time.local(2005,4,2,4,18,0).ago(86400.seconds), 'st-86400.seconds=>st' end with_env_tz 'NZ' do # dt: New Zealand: 2006 October 1st 4:18am - assert_equal Time.local(2006,9,30,3,18,0), Time.local(2006,10,1,4,18,0).ago(24.hours), 'dt-1.day=>st' - assert_equal Time.local(2006,9,29,4,18,0), Time.local(2006,9,30,4,18,0).ago(24.hours), 'st-1.day=>st' + assert_equal Time.local(2006,9,30,3,18,0), Time.local(2006,10,1,4,18,0).ago(24.hours), 'dt-24.hours=>st' + assert_equal Time.local(2006,9,30,3,18,0), Time.local(2006,10,1,4,18,0).ago(86400.seconds), 'dt-86400.seconds=>st' + assert_equal Time.local(2006,9,30,3,18,0), Time.local(2006,10,1,4,18,0).ago(86400), 'dt-86400=>st' + + assert_equal Time.local(2006,9,29,4,18,0), Time.local(2006,9,30,4,18,0).ago(86400), 'st-86400=>st' + assert_equal Time.local(2006,9,29,4,18,0), Time.local(2006,9,30,4,18,0).ago(24.hours), 'st-24.hours=>st' + assert_equal Time.local(2006,9,29,4,18,0), Time.local(2006,9,30,4,18,0).ago(86400.seconds), 'st-86400.seconds=>st' end end def test_daylight_savings_time_crossings_backward_end with_env_tz 'US/Eastern' do # st: US: 2005 October 30th 4:03am - assert_equal Time.local(2005,10,29,5,3), Time.local(2005,10,30,4,3,0).ago(24.hours), 'st-1.day=>dt' - assert_equal Time.local(2005,10,28,4,3), Time.local(2005,10,29,4,3,0).ago(24.hours), 'dt-1.day=>dt' + assert_equal Time.local(2005,10,29,5,3), Time.local(2005,10,30,4,3,0).ago(24.hours), 'st-24.hours=>dt' + assert_equal Time.local(2005,10,29,5,3), Time.local(2005,10,30,4,3,0).ago(86400), 'st-86400=>dt' + assert_equal Time.local(2005,10,29,5,3), Time.local(2005,10,30,4,3,0).ago(86400.seconds), 'st-86400.seconds=>dt' + + assert_equal Time.local(2005,10,28,4,3), Time.local(2005,10,29,4,3,0).ago(24.hours), 'dt-24.hours=>dt' + assert_equal Time.local(2005,10,28,4,3), Time.local(2005,10,29,4,3,0).ago(86400), 'dt-86400=>dt' + assert_equal Time.local(2005,10,28,4,3), Time.local(2005,10,29,4,3,0).ago(86400.seconds), 'dt-86400.seconds=>dt' end with_env_tz 'NZ' do # st: New Zealand: 2006 March 19th 4:03am - assert_equal Time.local(2006,3,18,5,3), Time.local(2006,3,19,4,3,0).ago(24.hours), 'st-1.day=>dt' - assert_equal Time.local(2006,3,17,4,3), Time.local(2006,3,18,4,3,0).ago(24.hours), 'dt-1.day=>dt' + assert_equal Time.local(2006,3,18,5,3), Time.local(2006,3,19,4,3,0).ago(24.hours), 'st-24.hours=>dt' + assert_equal Time.local(2006,3,18,5,3), Time.local(2006,3,19,4,3,0).ago(86400), 'st-86400=>dt' + assert_equal Time.local(2006,3,18,5,3), Time.local(2006,3,19,4,3,0).ago(86400.seconds), 'st-86400.seconds=>dt' + + assert_equal Time.local(2006,3,17,4,3), Time.local(2006,3,18,4,3,0).ago(24.hours), 'dt-24.hours=>dt' + assert_equal Time.local(2006,3,17,4,3), Time.local(2006,3,18,4,3,0).ago(86400), 'dt-86400=>dt' + assert_equal Time.local(2006,3,17,4,3), Time.local(2006,3,18,4,3,0).ago(86400.seconds), 'dt-86400.seconds=>dt' end end @@ -231,6 +251,7 @@ class TimeExtCalculationsTest < Test::Unit::TestCase assert_equal Time.local(2006,3,17,4,3), Time.local(2006,3,18,4,3,0).ago(1.day), 'dt-1.day=>dt' end end + def test_since assert_equal Time.local(2005,2,22,10,10,11), Time.local(2005,2,22,10,10,10).since(1) assert_equal Time.local(2005,2,22,11,10,10), Time.local(2005,2,22,10,10,10).since(3600) @@ -243,13 +264,23 @@ class TimeExtCalculationsTest < Test::Unit::TestCase def test_daylight_savings_time_crossings_forward_start with_env_tz 'US/Eastern' do # st: US: 2005 April 2nd 7:27pm - assert_equal Time.local(2005,4,3,20,27,0), Time.local(2005,4,2,19,27,0).since(24.hours), 'st+1.day=>dt' - assert_equal Time.local(2005,4,4,19,27,0), Time.local(2005,4,3,19,27,0).since(24.hours), 'dt+1.day=>dt' + assert_equal Time.local(2005,4,3,20,27,0), Time.local(2005,4,2,19,27,0).since(24.hours), 'st+24.hours=>dt' + assert_equal Time.local(2005,4,3,20,27,0), Time.local(2005,4,2,19,27,0).since(86400), 'st+86400=>dt' + assert_equal Time.local(2005,4,3,20,27,0), Time.local(2005,4,2,19,27,0).since(86400.seconds), 'st+86400.seconds=>dt' + + assert_equal Time.local(2005,4,4,19,27,0), Time.local(2005,4,3,19,27,0).since(24.hours), 'dt+24.hoursy=>dt' + assert_equal Time.local(2005,4,4,19,27,0), Time.local(2005,4,3,19,27,0).since(86400), 'dt+86400=>dt' + assert_equal Time.local(2005,4,4,19,27,0), Time.local(2005,4,3,19,27,0).since(86400.seconds), 'dt+86400.seconds=>dt' end with_env_tz 'NZ' do # st: New Zealand: 2006 September 30th 7:27pm - assert_equal Time.local(2006,10,1,20,27,0), Time.local(2006,9,30,19,27,0).since(24.hours), 'st+1.day=>dt' - assert_equal Time.local(2006,10,2,19,27,0), Time.local(2006,10,1,19,27,0).since(24.hours), 'dt+1.day=>dt' + assert_equal Time.local(2006,10,1,20,27,0), Time.local(2006,9,30,19,27,0).since(24.hours), 'st+24.hours=>dt' + assert_equal Time.local(2006,10,1,20,27,0), Time.local(2006,9,30,19,27,0).since(86400), 'st+86400=>dt' + assert_equal Time.local(2006,10,1,20,27,0), Time.local(2006,9,30,19,27,0).since(86400.seconds), 'st+86400.seconds=>dt' + + assert_equal Time.local(2006,10,2,19,27,0), Time.local(2006,10,1,19,27,0).since(24.hours), 'dt+24.hours=>dt' + assert_equal Time.local(2006,10,2,19,27,0), Time.local(2006,10,1,19,27,0).since(86400), 'dt+86400=>dt' + assert_equal Time.local(2006,10,2,19,27,0), Time.local(2006,10,1,19,27,0).since(86400.seconds), 'dt+86400.seconds=>dt' end end @@ -295,13 +326,23 @@ class TimeExtCalculationsTest < Test::Unit::TestCase def test_daylight_savings_time_crossings_forward_end with_env_tz 'US/Eastern' do # dt: US: 2005 October 30th 12:45am - assert_equal Time.local(2005,10,30,23,45,0), Time.local(2005,10,30,0,45,0).since(24.hours), 'dt+1.day=>st' - assert_equal Time.local(2005,11, 1,0,45,0), Time.local(2005,10,31,0,45,0).since(24.hours), 'st+1.day=>st' + assert_equal Time.local(2005,10,30,23,45,0), Time.local(2005,10,30,0,45,0).since(24.hours), 'dt+24.hours=>st' + assert_equal Time.local(2005,10,30,23,45,0), Time.local(2005,10,30,0,45,0).since(86400), 'dt+86400=>st' + assert_equal Time.local(2005,10,30,23,45,0), Time.local(2005,10,30,0,45,0).since(86400.seconds), 'dt+86400.seconds=>st' + + assert_equal Time.local(2005,11, 1,0,45,0), Time.local(2005,10,31,0,45,0).since(24.hours), 'st+24.hours=>st' + assert_equal Time.local(2005,11, 1,0,45,0), Time.local(2005,10,31,0,45,0).since(86400), 'st+86400=>st' + assert_equal Time.local(2005,11, 1,0,45,0), Time.local(2005,10,31,0,45,0).since(86400.seconds), 'st+86400.seconds=>st' end with_env_tz 'NZ' do # dt: New Zealand: 2006 March 19th 1:45am - assert_equal Time.local(2006,3,20,0,45,0), Time.local(2006,3,19,1,45,0).since(24.hours), 'dt+1.day=>st' - assert_equal Time.local(2006,3,21,1,45,0), Time.local(2006,3,20,1,45,0).since(24.hours), 'st+1.day=>st' + assert_equal Time.local(2006,3,20,0,45,0), Time.local(2006,3,19,1,45,0).since(24.hours), 'dt+24.hours=>st' + assert_equal Time.local(2006,3,20,0,45,0), Time.local(2006,3,19,1,45,0).since(86400), 'dt+86400=>st' + assert_equal Time.local(2006,3,20,0,45,0), Time.local(2006,3,19,1,45,0).since(86400.seconds), 'dt+86400.seconds=>st' + + assert_equal Time.local(2006,3,21,1,45,0), Time.local(2006,3,20,1,45,0).since(24.hours), 'st+24.hours=>st' + assert_equal Time.local(2006,3,21,1,45,0), Time.local(2006,3,20,1,45,0).since(86400), 'st+86400=>st' + assert_equal Time.local(2006,3,21,1,45,0), Time.local(2006,3,20,1,45,0).since(86400.seconds), 'st+86400.seconds=>st' end end -- cgit v1.2.3 From 0e9efae4745e232b1c778fda69ee110e42a223a7 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Thu, 2 Apr 2009 12:05:21 -0500 Subject: Nicer name for anonymous local cache middleware class --- activesupport/lib/active_support/cache/strategy/local_cache.rb | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/cache/strategy/local_cache.rb b/activesupport/lib/active_support/cache/strategy/local_cache.rb index d83e259a2a..84d9a0e6d8 100644 --- a/activesupport/lib/active_support/cache/strategy/local_cache.rb +++ b/activesupport/lib/active_support/cache/strategy/local_cache.rb @@ -27,6 +27,11 @@ module ActiveSupport Thread.current[:#{thread_local_key}] = nil end EOS + + def klass.to_s + "ActiveSupport::Cache::Strategy::LocalCache" + end + klass end end -- cgit v1.2.3 From c00f2d25de640b8de1c8583474085f3836ee1768 Mon Sep 17 00:00:00 2001 From: Geoff Buesing Date: Sun, 5 Apr 2009 10:08:54 -0500 Subject: TimeWithZone.name returns 'Time', to further thwart type checking --- activesupport/CHANGELOG | 2 ++ activesupport/lib/active_support/time_with_zone.rb | 5 +++++ activesupport/test/core_ext/time_with_zone_test.rb | 4 ++++ 3 files changed, 11 insertions(+) (limited to 'activesupport') diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 2acce97646..2ba96c390b 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,5 +1,7 @@ *Edge +* TimeWithZone.name returns 'Time', to further thwart type checking [Geoff Buesing] + * Time.local instances: Adding 24.hours across the DST boundary adds 24 hours instead of one day #2066 [Michael Curtis] diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index 518ca7742f..2574f4e88e 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -31,6 +31,11 @@ module ActiveSupport # t.is_a?(Time) # => true # t.is_a?(ActiveSupport::TimeWithZone) # => true class TimeWithZone + + def self.name + 'Time' # Report class name as 'Time' to thwart type checking + end + include Comparable attr_reader :time_zone diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb index accfe51ed6..7be19e7900 100644 --- a/activesupport/test/core_ext/time_with_zone_test.rb +++ b/activesupport/test/core_ext/time_with_zone_test.rb @@ -317,6 +317,10 @@ class TimeWithZoneTest < Test::Unit::TestCase assert @twz.kind_of?(Time) assert @twz.is_a?(ActiveSupport::TimeWithZone) end + + def test_class_name + assert_equal 'Time', ActiveSupport::TimeWithZone.name + end def test_method_missing_with_time_return_value assert_instance_of ActiveSupport::TimeWithZone, @twz.months_since(1) -- cgit v1.2.3 From 7685ea20b4915f907082a22028260d04024a200b Mon Sep 17 00:00:00 2001 From: Geoff Buesing Date: Sun, 5 Apr 2009 10:15:54 -0500 Subject: Hash::XML_TYPE_NAMES: no longer a need for a TimeWithZone entry; this class will now match "Time" --- activesupport/lib/active_support/core_ext/hash/conversions.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb index 10435975c5..f8a5e70eea 100644 --- a/activesupport/lib/active_support/core_ext/hash/conversions.rb +++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb @@ -28,8 +28,7 @@ module ActiveSupport #:nodoc: "FalseClass" => "boolean", "Date" => "date", "DateTime" => "datetime", - "Time" => "datetime", - "ActiveSupport::TimeWithZone" => "datetime" + "Time" => "datetime" } unless defined?(XML_TYPE_NAMES) XML_FORMATTING = { -- cgit v1.2.3 From 660fc93942697b74a8093d4d5338d1ced25cbe7f Mon Sep 17 00:00:00 2001 From: Geoff Buesing Date: Sun, 5 Apr 2009 10:19:03 -0500 Subject: Test cleanup --- activesupport/test/core_ext/time_ext_test.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'activesupport') diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index 70cf4a9450..8ee4904036 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -194,11 +194,11 @@ class TimeExtCalculationsTest < Test::Unit::TestCase with_env_tz 'NZ' do # dt: New Zealand: 2006 October 1st 4:18am assert_equal Time.local(2006,9,30,3,18,0), Time.local(2006,10,1,4,18,0).ago(24.hours), 'dt-24.hours=>st' - assert_equal Time.local(2006,9,30,3,18,0), Time.local(2006,10,1,4,18,0).ago(86400.seconds), 'dt-86400.seconds=>st' assert_equal Time.local(2006,9,30,3,18,0), Time.local(2006,10,1,4,18,0).ago(86400), 'dt-86400=>st' + assert_equal Time.local(2006,9,30,3,18,0), Time.local(2006,10,1,4,18,0).ago(86400.seconds), 'dt-86400.seconds=>st' - assert_equal Time.local(2006,9,29,4,18,0), Time.local(2006,9,30,4,18,0).ago(86400), 'st-86400=>st' assert_equal Time.local(2006,9,29,4,18,0), Time.local(2006,9,30,4,18,0).ago(24.hours), 'st-24.hours=>st' + assert_equal Time.local(2006,9,29,4,18,0), Time.local(2006,9,30,4,18,0).ago(86400), 'st-86400=>st' assert_equal Time.local(2006,9,29,4,18,0), Time.local(2006,9,30,4,18,0).ago(86400.seconds), 'st-86400.seconds=>st' end end @@ -268,7 +268,7 @@ class TimeExtCalculationsTest < Test::Unit::TestCase assert_equal Time.local(2005,4,3,20,27,0), Time.local(2005,4,2,19,27,0).since(86400), 'st+86400=>dt' assert_equal Time.local(2005,4,3,20,27,0), Time.local(2005,4,2,19,27,0).since(86400.seconds), 'st+86400.seconds=>dt' - assert_equal Time.local(2005,4,4,19,27,0), Time.local(2005,4,3,19,27,0).since(24.hours), 'dt+24.hoursy=>dt' + assert_equal Time.local(2005,4,4,19,27,0), Time.local(2005,4,3,19,27,0).since(24.hours), 'dt+24.hours=>dt' assert_equal Time.local(2005,4,4,19,27,0), Time.local(2005,4,3,19,27,0).since(86400), 'dt+86400=>dt' assert_equal Time.local(2005,4,4,19,27,0), Time.local(2005,4,3,19,27,0).since(86400.seconds), 'dt+86400.seconds=>dt' end -- cgit v1.2.3 From 4d3cd9b43f6b7425ca3eee303773d2221e8af38f Mon Sep 17 00:00:00 2001 From: Yehuda Katz and Carl Lerche Date: Mon, 6 Apr 2009 12:35:24 -0700 Subject: Changes necessary to run the T::U tests with the rspec runner --- .../lib/active_support/testing/setup_and_teardown.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/testing/setup_and_teardown.rb b/activesupport/lib/active_support/testing/setup_and_teardown.rb index 245f57a7b0..780c1309f4 100644 --- a/activesupport/lib/active_support/testing/setup_and_teardown.rb +++ b/activesupport/lib/active_support/testing/setup_and_teardown.rb @@ -39,6 +39,14 @@ module ActiveSupport # For compatibility with Ruby < 1.8.6 PASSTHROUGH_EXCEPTIONS = Test::Unit::TestCase::PASSTHROUGH_EXCEPTIONS rescue [NoMemoryError, SignalException, Interrupt, SystemExit] + def setup + run_callbacks :setup + end + + def teardown + run_callbacks :teardown, :enumerator => :reverse_each + end + # This redefinition is unfortunate but test/unit shows us no alternative. # Doubly unfortunate: hax to support Mocha's hax. def run(result) @@ -52,7 +60,7 @@ module ActiveSupport @_result = result begin begin - run_callbacks :setup + # run_callbacks :setup setup __send__(@method_name) mocha_verify(assertion_counter) if using_mocha @@ -66,7 +74,7 @@ module ActiveSupport ensure begin teardown - run_callbacks :teardown, :enumerator => :reverse_each + # run_callbacks :teardown, :enumerator => :reverse_each rescue Test::Unit::AssertionFailedError => e add_failure(e.message, e.backtrace) rescue Exception => e -- cgit v1.2.3 From c1aa5b0e14cd4bd27a5d8bd85cf7c36fa5911830 Mon Sep 17 00:00:00 2001 From: Yehuda Katz and Carl Lerche Date: Tue, 7 Apr 2009 14:57:18 -0700 Subject: Add depends_on, use, and setup to abstract up ideas about module inheritance. --- .../lib/active_support/core_ext/module.rb | 1 + .../lib/active_support/core_ext/module/setup.rb | 26 ++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 activesupport/lib/active_support/core_ext/module/setup.rb (limited to 'activesupport') diff --git a/activesupport/lib/active_support/core_ext/module.rb b/activesupport/lib/active_support/core_ext/module.rb index da8d28ec13..cb31437094 100644 --- a/activesupport/lib/active_support/core_ext/module.rb +++ b/activesupport/lib/active_support/core_ext/module.rb @@ -8,6 +8,7 @@ require 'active_support/core_ext/module/loading' require 'active_support/core_ext/module/aliasing' require 'active_support/core_ext/module/model_naming' require 'active_support/core_ext/module/synchronization' +require 'active_support/core_ext/module/setup' module ActiveSupport module CoreExtensions diff --git a/activesupport/lib/active_support/core_ext/module/setup.rb b/activesupport/lib/active_support/core_ext/module/setup.rb new file mode 100644 index 0000000000..e6dfd0cf56 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/module/setup.rb @@ -0,0 +1,26 @@ +class Module + attr_accessor :_setup_block + attr_accessor :_dependencies + + def setup(&blk) + @_setup_block = blk + end + + def use(mod) + return if self < mod + + (mod._dependencies || []).each do |dep| + use dep + end + # raise "Circular dependencies" if self < mod + include mod + extend mod.const_get("ClassMethods") if mod.const_defined?("ClassMethods") + class_eval(&mod._setup_block) if mod._setup_block + end + + def depends_on(mod) + return if self < mod + @_dependencies ||= [] + @_dependencies << mod + end +end \ No newline at end of file -- cgit v1.2.3 From 95c9718118bc0342ddb320f23b5e0a17fb12b7ad Mon Sep 17 00:00:00 2001 From: Yehuda Katz and Carl Lerche Date: Tue, 7 Apr 2009 15:54:02 -0700 Subject: Layouts work in AbstractController. Add support for the rspec runner for T::U --- .../lib/active_support/testing/declarative.rb | 49 ++++++++++++++++------ .../lib/active_support/testing/pending.rb | 45 ++++++++++---------- 2 files changed, 61 insertions(+), 33 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/testing/declarative.rb b/activesupport/lib/active_support/testing/declarative.rb index cb6a5844eb..a7af7f4224 100644 --- a/activesupport/lib/active_support/testing/declarative.rb +++ b/activesupport/lib/active_support/testing/declarative.rb @@ -1,18 +1,43 @@ module ActiveSupport module Testing module Declarative - # test "verify something" do - # ... - # end - def test(name, &block) - test_name = "test_#{name.gsub(/\s+/,'_')}".to_sym - defined = instance_method(test_name) rescue false - raise "#{test_name} is already defined in #{self}" if defined - if block_given? - define_method(test_name, &block) - else - define_method(test_name) do - flunk "No implementation provided for #{name}" + + def self.extended(klass) + klass.class_eval do + + unless method_defined?(:describe) + def self.describe(text) + class_eval <<-RUBY_EVAL + def self.name + "#{text}" + end + RUBY_EVAL + end + end + + if defined?(Spec) + class << self + alias_method :test, :it + end + end + + end + end + + unless defined?(Spec) + # test "verify something" do + # ... + # end + def test(name, &block) + test_name = "test_#{name.gsub(/\s+/,'_')}".to_sym + defined = instance_method(test_name) rescue false + raise "#{test_name} is already defined in #{self}" if defined + if block_given? + define_method(test_name, &block) + else + define_method(test_name) do + flunk "No implementation provided for #{name}" + end end end end diff --git a/activesupport/lib/active_support/testing/pending.rb b/activesupport/lib/active_support/testing/pending.rb index 9b2ab73dd0..b6905ddccd 100644 --- a/activesupport/lib/active_support/testing/pending.rb +++ b/activesupport/lib/active_support/testing/pending.rb @@ -5,31 +5,34 @@ module ActiveSupport module Testing module Pending - @@pending_cases = [] - @@at_exit = false + unless defined?(Spec) - def pending(description = "", &block) - if block_given? - failed = false + @@pending_cases = [] + @@at_exit = false - begin - block.call - rescue - failed = true - end + def pending(description = "", &block) + if block_given? + failed = false - flunk("<#{description}> did not fail.") unless failed - end + begin + block.call + rescue + failed = true + end - caller[0] =~ (/(.*):(.*):in `(.*)'/) - @@pending_cases << "#{$3} at #{$1}, line #{$2}" - print "P" - - @@at_exit ||= begin - at_exit do - puts "\nPending Cases:" - @@pending_cases.each do |test_case| - puts test_case + flunk("<#{description}> did not fail.") unless failed + end + + caller[0] =~ (/(.*):(.*):in `(.*)'/) + @@pending_cases << "#{$3} at #{$1}, line #{$2}" + print "P" + + @@at_exit ||= begin + at_exit do + puts "\nPending Cases:" + @@pending_cases.each do |test_case| + puts test_case + end end end end -- cgit v1.2.3 From 1aadafda8dd28ec081da6827878003c478c77c76 Mon Sep 17 00:00:00 2001 From: Yehuda Katz and Carl Lerche Date: Wed, 8 Apr 2009 17:32:19 -0700 Subject: Updated old AC::Base for small changes to AV --- activesupport/lib/active_support/memoizable.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb index bd9dbb60fc..945c1a68bb 100644 --- a/activesupport/lib/active_support/memoizable.rb +++ b/activesupport/lib/active_support/memoizable.rb @@ -82,7 +82,7 @@ module ActiveSupport if instance_method(:#{symbol}).arity == 0 # if instance_method(:mime_type).arity == 0 def #{symbol}(reload = false) # def mime_type(reload = false) if reload || !defined?(#{memoized_ivar}) || #{memoized_ivar}.empty? # if reload || !defined?(@_memoized_mime_type) || @_memoized_mime_type.empty? - #{memoized_ivar} = [#{original_method}.freeze] # @_memoized_mime_type = [_unmemoized_mime_type.freeze] + #{memoized_ivar} = [#{original_method}] # @_memoized_mime_type = [_unmemoized_mime_type] end # end #{memoized_ivar}[0] # @_memoized_mime_type[0] end # end @@ -95,7 +95,7 @@ module ActiveSupport if !reload && #{memoized_ivar}.has_key?(args) # if !reload && @_memoized_mime_type.has_key?(args) #{memoized_ivar}[args] # @_memoized_mime_type[args] elsif #{memoized_ivar} # elsif @_memoized_mime_type - #{memoized_ivar}[args] = #{original_method}(*args).freeze # @_memoized_mime_type[args] = _unmemoized_mime_type(*args).freeze + #{memoized_ivar}[args] = #{original_method}(*args) # @_memoized_mime_type[args] = _unmemoized_mime_type(*args) end # end else # else #{original_method}(*args) # _unmemoized_mime_type(*args) -- cgit v1.2.3 From 2036d3ba75da1a0f3061bf5a33c89e2b2eaff420 Mon Sep 17 00:00:00 2001 From: Carl Lerche & Yehuda Katz Date: Thu, 9 Apr 2009 12:33:39 -0700 Subject: Revert rspec-runner change. TODO: Add back support for the rspec T::U runner. --- .../active_support/testing/setup_and_teardown.rb | 16 +- activesupport/test/new_callbacks_test.rb | 600 +++++++++++---------- 2 files changed, 306 insertions(+), 310 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/testing/setup_and_teardown.rb b/activesupport/lib/active_support/testing/setup_and_teardown.rb index 780c1309f4..6248bf1921 100644 --- a/activesupport/lib/active_support/testing/setup_and_teardown.rb +++ b/activesupport/lib/active_support/testing/setup_and_teardown.rb @@ -10,6 +10,8 @@ module ActiveSupport if defined? MiniTest include ForMiniTest + elsif defined? Spec + include ForRspec else include ForClassicTestUnit end @@ -34,19 +36,11 @@ module ActiveSupport result end end - + module ForClassicTestUnit # For compatibility with Ruby < 1.8.6 PASSTHROUGH_EXCEPTIONS = Test::Unit::TestCase::PASSTHROUGH_EXCEPTIONS rescue [NoMemoryError, SignalException, Interrupt, SystemExit] - def setup - run_callbacks :setup - end - - def teardown - run_callbacks :teardown, :enumerator => :reverse_each - end - # This redefinition is unfortunate but test/unit shows us no alternative. # Doubly unfortunate: hax to support Mocha's hax. def run(result) @@ -60,7 +54,7 @@ module ActiveSupport @_result = result begin begin - # run_callbacks :setup + run_callbacks :setup setup __send__(@method_name) mocha_verify(assertion_counter) if using_mocha @@ -74,7 +68,7 @@ module ActiveSupport ensure begin teardown - # run_callbacks :teardown, :enumerator => :reverse_each + run_callbacks :teardown, :enumerator => :reverse_each rescue Test::Unit::AssertionFailedError => e add_failure(e.message, e.backtrace) rescue Exception => e diff --git a/activesupport/test/new_callbacks_test.rb b/activesupport/test/new_callbacks_test.rb index 6948ad23dc..5cde078b65 100644 --- a/activesupport/test/new_callbacks_test.rb +++ b/activesupport/test/new_callbacks_test.rb @@ -3,380 +3,382 @@ require 'test/unit' $:.unshift "#{File.dirname(__FILE__)}/../lib" require 'active_support' -class Record - include ActiveSupport::NewCallbacks +module NewCallbacksTest + class Record + include ActiveSupport::NewCallbacks - define_callbacks :save + define_callbacks :save - def self.before_save(*filters, &blk) - save_callback(:before, *filters, &blk) - end + def self.before_save(*filters, &blk) + save_callback(:before, *filters, &blk) + end - def self.after_save(*filters, &blk) - save_callback(:after, *filters, &blk) - end + def self.after_save(*filters, &blk) + save_callback(:after, *filters, &blk) + end - class << self - def callback_symbol(callback_method) - returning(:"#{callback_method}_method") do |method_name| - define_method(method_name) do - history << [callback_method, :symbol] + class << self + def callback_symbol(callback_method) + returning(:"#{callback_method}_method") do |method_name| + define_method(method_name) do + history << [callback_method, :symbol] + end end end - end - def callback_string(callback_method) - "history << [#{callback_method.to_sym.inspect}, :string]" - end + def callback_string(callback_method) + "history << [#{callback_method.to_sym.inspect}, :string]" + end - def callback_proc(callback_method) - Proc.new { |model| model.history << [callback_method, :proc] } - end + def callback_proc(callback_method) + Proc.new { |model| model.history << [callback_method, :proc] } + end - def callback_object(callback_method) - klass = Class.new - klass.send(:define_method, callback_method) do |model| - model.history << [callback_method, :object] + def callback_object(callback_method) + klass = Class.new + klass.send(:define_method, callback_method) do |model| + model.history << [callback_method, :object] + end + klass.new end - klass.new end - end - def history - @history ||= [] + def history + @history ||= [] + end end -end -class Person < Record - [:before_save, :after_save].each do |callback_method| - callback_method_sym = callback_method.to_sym - send(callback_method, callback_symbol(callback_method_sym)) - send(callback_method, callback_string(callback_method_sym)) - send(callback_method, callback_proc(callback_method_sym)) - send(callback_method, callback_object(callback_method_sym)) - send(callback_method) { |model| model.history << [callback_method_sym, :block] } - end + class Person < Record + [:before_save, :after_save].each do |callback_method| + callback_method_sym = callback_method.to_sym + send(callback_method, callback_symbol(callback_method_sym)) + send(callback_method, callback_string(callback_method_sym)) + send(callback_method, callback_proc(callback_method_sym)) + send(callback_method, callback_object(callback_method_sym)) + send(callback_method) { |model| model.history << [callback_method_sym, :block] } + end - def save - _run_save_callbacks {} + def save + _run_save_callbacks {} + end end -end -class PersonSkipper < Person - skip_save_callback :before, :before_save_method, :if => :yes - skip_save_callback :after, :before_save_method, :unless => :yes - skip_save_callback :after, :before_save_method, :if => :no - skip_save_callback :before, :before_save_method, :unless => :no - def yes; true; end - def no; false; end -end + class PersonSkipper < Person + skip_save_callback :before, :before_save_method, :if => :yes + skip_save_callback :after, :before_save_method, :unless => :yes + skip_save_callback :after, :before_save_method, :if => :no + skip_save_callback :before, :before_save_method, :unless => :no + def yes; true; end + def no; false; end + end -class ParentController - include ActiveSupport::NewCallbacks + class ParentController + include ActiveSupport::NewCallbacks - define_callbacks :dispatch + define_callbacks :dispatch - dispatch_callback :before, :log, :per_key => {:unless => proc {|c| c.action_name == :index || c.action_name == :show }} - dispatch_callback :after, :log2 + dispatch_callback :before, :log, :per_key => {:unless => proc {|c| c.action_name == :index || c.action_name == :show }} + dispatch_callback :after, :log2 - attr_reader :action_name, :logger - def initialize(action_name) - @action_name, @logger = action_name, [] - end + attr_reader :action_name, :logger + def initialize(action_name) + @action_name, @logger = action_name, [] + end - def log - @logger << action_name - end + def log + @logger << action_name + end - def log2 - @logger << action_name - end + def log2 + @logger << action_name + end - def dispatch - _run_dispatch_callbacks(action_name) { - @logger << "Done" - } - self + def dispatch + _run_dispatch_callbacks(action_name) { + @logger << "Done" + } + self + end end -end -class Child < ParentController - skip_dispatch_callback :before, :log, :per_key => {:if => proc {|c| c.action_name == :update} } - skip_dispatch_callback :after, :log2 -end + class Child < ParentController + skip_dispatch_callback :before, :log, :per_key => {:if => proc {|c| c.action_name == :update} } + skip_dispatch_callback :after, :log2 + end -class OneTimeCompile < Record - @@starts_true, @@starts_false = true, false + class OneTimeCompile < Record + @@starts_true, @@starts_false = true, false - def initialize - super - end + def initialize + super + end - before_save Proc.new {|r| r.history << [:before_save, :starts_true, :if] }, :per_key => {:if => :starts_true} - before_save Proc.new {|r| r.history << [:before_save, :starts_false, :if] }, :per_key => {:if => :starts_false} - before_save Proc.new {|r| r.history << [:before_save, :starts_true, :unless] }, :per_key => {:unless => :starts_true} - before_save Proc.new {|r| r.history << [:before_save, :starts_false, :unless] }, :per_key => {:unless => :starts_false} + before_save Proc.new {|r| r.history << [:before_save, :starts_true, :if] }, :per_key => {:if => :starts_true} + before_save Proc.new {|r| r.history << [:before_save, :starts_false, :if] }, :per_key => {:if => :starts_false} + before_save Proc.new {|r| r.history << [:before_save, :starts_true, :unless] }, :per_key => {:unless => :starts_true} + before_save Proc.new {|r| r.history << [:before_save, :starts_false, :unless] }, :per_key => {:unless => :starts_false} - def starts_true - if @@starts_true - @@starts_true = false - return true + def starts_true + if @@starts_true + @@starts_true = false + return true + end + @@starts_true end - @@starts_true - end - def starts_false - unless @@starts_false - @@starts_false = true - return false + def starts_false + unless @@starts_false + @@starts_false = true + return false + end + @@starts_false end - @@starts_false - end - def save - _run_save_callbacks(:action) {} + def save + _run_save_callbacks(:action) {} + end end -end -class OneTimeCompileTest < Test::Unit::TestCase - def test_optimized_first_compile - around = OneTimeCompile.new - around.save - assert_equal [ - [:before_save, :starts_true, :if], - [:before_save, :starts_true, :unless] - ], around.history + class OneTimeCompileTest < Test::Unit::TestCase + def test_optimized_first_compile + around = OneTimeCompile.new + around.save + assert_equal [ + [:before_save, :starts_true, :if], + [:before_save, :starts_true, :unless] + ], around.history + end end -end -class ConditionalPerson < Record - # proc - before_save Proc.new { |r| r.history << [:before_save, :proc] }, :if => Proc.new { |r| true } - before_save Proc.new { |r| r.history << "b00m" }, :if => Proc.new { |r| false } - before_save Proc.new { |r| r.history << [:before_save, :proc] }, :unless => Proc.new { |r| false } - before_save Proc.new { |r| r.history << "b00m" }, :unless => Proc.new { |r| true } - # symbol - before_save Proc.new { |r| r.history << [:before_save, :symbol] }, :if => :yes - before_save Proc.new { |r| r.history << "b00m" }, :if => :no - before_save Proc.new { |r| r.history << [:before_save, :symbol] }, :unless => :no - before_save Proc.new { |r| r.history << "b00m" }, :unless => :yes - # string - before_save Proc.new { |r| r.history << [:before_save, :string] }, :if => 'yes' - before_save Proc.new { |r| r.history << "b00m" }, :if => 'no' - before_save Proc.new { |r| r.history << [:before_save, :string] }, :unless => 'no' - before_save Proc.new { |r| r.history << "b00m" }, :unless => 'yes' - # Combined if and unless - before_save Proc.new { |r| r.history << [:before_save, :combined_symbol] }, :if => :yes, :unless => :no - before_save Proc.new { |r| r.history << "b00m" }, :if => :yes, :unless => :yes + class ConditionalPerson < Record + # proc + before_save Proc.new { |r| r.history << [:before_save, :proc] }, :if => Proc.new { |r| true } + before_save Proc.new { |r| r.history << "b00m" }, :if => Proc.new { |r| false } + before_save Proc.new { |r| r.history << [:before_save, :proc] }, :unless => Proc.new { |r| false } + before_save Proc.new { |r| r.history << "b00m" }, :unless => Proc.new { |r| true } + # symbol + before_save Proc.new { |r| r.history << [:before_save, :symbol] }, :if => :yes + before_save Proc.new { |r| r.history << "b00m" }, :if => :no + before_save Proc.new { |r| r.history << [:before_save, :symbol] }, :unless => :no + before_save Proc.new { |r| r.history << "b00m" }, :unless => :yes + # string + before_save Proc.new { |r| r.history << [:before_save, :string] }, :if => 'yes' + before_save Proc.new { |r| r.history << "b00m" }, :if => 'no' + before_save Proc.new { |r| r.history << [:before_save, :string] }, :unless => 'no' + before_save Proc.new { |r| r.history << "b00m" }, :unless => 'yes' + # Combined if and unless + before_save Proc.new { |r| r.history << [:before_save, :combined_symbol] }, :if => :yes, :unless => :no + before_save Proc.new { |r| r.history << "b00m" }, :if => :yes, :unless => :yes - def yes; true; end - def other_yes; true; end - def no; false; end - def other_no; false; end + def yes; true; end + def other_yes; true; end + def no; false; end + def other_no; false; end - def save - _run_save_callbacks {} + def save + _run_save_callbacks {} + end end -end -class MySuper - include ActiveSupport::NewCallbacks - define_callbacks :save -end + class MySuper + include ActiveSupport::NewCallbacks + define_callbacks :save + end -class AroundPerson < MySuper - attr_reader :history + class AroundPerson < MySuper + attr_reader :history - save_callback :before, :nope, :if => :no - save_callback :before, :nope, :unless => :yes - save_callback :after, :tweedle - save_callback :before, "tweedle_dee" - save_callback :before, proc {|m| m.history << "yup" } - save_callback :before, :nope, :if => proc { false } - save_callback :before, :nope, :unless => proc { true } - save_callback :before, :yup, :if => proc { true } - save_callback :before, :yup, :unless => proc { false } - save_callback :around, :tweedle_dum - save_callback :around, :w0tyes, :if => :yes - save_callback :around, :w0tno, :if => :no - save_callback :around, :tweedle_deedle + save_callback :before, :nope, :if => :no + save_callback :before, :nope, :unless => :yes + save_callback :after, :tweedle + save_callback :before, "tweedle_dee" + save_callback :before, proc {|m| m.history << "yup" } + save_callback :before, :nope, :if => proc { false } + save_callback :before, :nope, :unless => proc { true } + save_callback :before, :yup, :if => proc { true } + save_callback :before, :yup, :unless => proc { false } + save_callback :around, :tweedle_dum + save_callback :around, :w0tyes, :if => :yes + save_callback :around, :w0tno, :if => :no + save_callback :around, :tweedle_deedle - def no; false; end - def yes; true; end + def no; false; end + def yes; true; end - def nope - @history << "boom" - end + def nope + @history << "boom" + end - def yup - @history << "yup" - end + def yup + @history << "yup" + end - def w0tyes - @history << "w0tyes before" - yield - @history << "w0tyes after" - end + def w0tyes + @history << "w0tyes before" + yield + @history << "w0tyes after" + end - def w0tno - @history << "boom" - yield - end + def w0tno + @history << "boom" + yield + end - def tweedle_dee - @history << "tweedle dee" - end + def tweedle_dee + @history << "tweedle dee" + end - def tweedle_dum - @history << "tweedle dum pre" - yield - @history << "tweedle dum post" - end + def tweedle_dum + @history << "tweedle dum pre" + yield + @history << "tweedle dum post" + end - def tweedle - @history << "tweedle" - end + def tweedle + @history << "tweedle" + end - def tweedle_deedle - @history << "tweedle deedle pre" - yield - @history << "tweedle deedle post" - end + def tweedle_deedle + @history << "tweedle deedle pre" + yield + @history << "tweedle deedle post" + end - def initialize - @history = [] - end + def initialize + @history = [] + end - def save - _run_save_callbacks do - @history << "running" + def save + _run_save_callbacks do + @history << "running" + end end end -end -class AroundCallbacksTest < Test::Unit::TestCase - def test_save_around - around = AroundPerson.new - around.save - assert_equal [ - "tweedle dee", - "yup", "yup", "yup", - "tweedle dum pre", - "w0tyes before", - "tweedle deedle pre", - "running", - "tweedle deedle post", - "w0tyes after", - "tweedle dum post", - "tweedle" - ], around.history + class AroundCallbacksTest < Test::Unit::TestCase + def test_save_around + around = AroundPerson.new + around.save + assert_equal [ + "tweedle dee", + "yup", "yup", + "tweedle dum pre", + "w0tyes before", + "tweedle deedle pre", + "running", + "tweedle deedle post", + "w0tyes after", + "tweedle dum post", + "tweedle" + ], around.history + end end -end -class SkipCallbacksTest < Test::Unit::TestCase - def test_skip_person - person = PersonSkipper.new - assert_equal [], person.history - person.save - assert_equal [ - [:before_save, :string], - [:before_save, :proc], - [:before_save, :object], - [:before_save, :block], - [:after_save, :block], - [:after_save, :object], - [:after_save, :proc], - [:after_save, :string], - [:after_save, :symbol] - ], person.history + class SkipCallbacksTest < Test::Unit::TestCase + def test_skip_person + person = PersonSkipper.new + assert_equal [], person.history + person.save + assert_equal [ + [:before_save, :string], + [:before_save, :proc], + [:before_save, :object], + [:before_save, :block], + [:after_save, :block], + [:after_save, :object], + [:after_save, :proc], + [:after_save, :string], + [:after_save, :symbol] + ], person.history + end end -end -class CallbacksTest < Test::Unit::TestCase - def test_save_person - person = Person.new - assert_equal [], person.history - person.save - assert_equal [ - [:before_save, :symbol], - [:before_save, :string], - [:before_save, :proc], - [:before_save, :object], - [:before_save, :block], - [:after_save, :block], - [:after_save, :object], - [:after_save, :proc], - [:after_save, :string], - [:after_save, :symbol] - ], person.history + class CallbacksTest < Test::Unit::TestCase + def test_save_person + person = Person.new + assert_equal [], person.history + person.save + assert_equal [ + [:before_save, :symbol], + [:before_save, :string], + [:before_save, :proc], + [:before_save, :object], + [:before_save, :block], + [:after_save, :block], + [:after_save, :object], + [:after_save, :proc], + [:after_save, :string], + [:after_save, :symbol] + ], person.history + end end -end -class ConditionalCallbackTest < Test::Unit::TestCase - def test_save_conditional_person - person = ConditionalPerson.new - person.save - assert_equal [ - [:before_save, :proc], - [:before_save, :proc], - [:before_save, :symbol], - [:before_save, :symbol], - [:before_save, :string], - [:before_save, :string], - [:before_save, :combined_symbol], - ], person.history + class ConditionalCallbackTest < Test::Unit::TestCase + def test_save_conditional_person + person = ConditionalPerson.new + person.save + assert_equal [ + [:before_save, :proc], + [:before_save, :proc], + [:before_save, :symbol], + [:before_save, :symbol], + [:before_save, :string], + [:before_save, :string], + [:before_save, :combined_symbol], + ], person.history + end end -end -class CallbackTerminator - include ActiveSupport::NewCallbacks + class CallbackTerminator + include ActiveSupport::NewCallbacks - define_callbacks :save, "result == :halt" + define_callbacks :save, "result == :halt" - save_callback :before, :first - save_callback :before, :second - save_callback :around, :around_it - save_callback :before, :third - save_callback :after, :first - save_callback :around, :around_it - save_callback :after, :second - save_callback :around, :around_it - save_callback :after, :third + save_callback :before, :first + save_callback :before, :second + save_callback :around, :around_it + save_callback :before, :third + save_callback :after, :first + save_callback :around, :around_it + save_callback :after, :second + save_callback :around, :around_it + save_callback :after, :third - attr_reader :history - def initialize - @history = [] - end + attr_reader :history + def initialize + @history = [] + end - def around_it - @history << "around1" - yield - @history << "around2" - end + def around_it + @history << "around1" + yield + @history << "around2" + end - def first - @history << "first" - end + def first + @history << "first" + end - def second - @history << "second" - :halt - end + def second + @history << "second" + :halt + end - def third - @history << "third" - end + def third + @history << "third" + end - def save - _run_save_callbacks + def save + _run_save_callbacks + end end -end -class CallbackTerminatorTest < Test::Unit::TestCase - def test_termination - terminator = CallbackTerminator.new - terminator.save - assert_equal ["first", "second", "third", "second", "first"], terminator.history + class CallbackTerminatorTest < Test::Unit::TestCase + def test_termination + terminator = CallbackTerminator.new + terminator.save + assert_equal ["first", "second", "third", "second", "first"], terminator.history + end end -end +end \ No newline at end of file -- cgit v1.2.3 From 647b83d50cba655422bcb83815f618b5a92bfc7d Mon Sep 17 00:00:00 2001 From: Carl Lerche & Yehuda Katz Date: Mon, 13 Apr 2009 16:56:04 -0700 Subject: Resurrecting 1.9 compatibility. --- activesupport/lib/active_support/concurrent_hash.rb | 1 + activesupport/lib/active_support/new_callbacks.rb | 3 ++- activesupport/lib/active_support/testing/pending.rb | 2 +- activesupport/test/memoizable_test.rb | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/concurrent_hash.rb b/activesupport/lib/active_support/concurrent_hash.rb index c9f9b16da3..40224765a7 100644 --- a/activesupport/lib/active_support/concurrent_hash.rb +++ b/activesupport/lib/active_support/concurrent_hash.rb @@ -9,6 +9,7 @@ module ActiveSupport def []=(k,v) @mutex.synchronize { @backup_cache[k] = v } @frozen_cache = @backup_cache.dup.freeze + v end def [](k) diff --git a/activesupport/lib/active_support/new_callbacks.rb b/activesupport/lib/active_support/new_callbacks.rb index b93057fe27..2ac5339f07 100644 --- a/activesupport/lib/active_support/new_callbacks.rb +++ b/activesupport/lib/active_support/new_callbacks.rb @@ -368,7 +368,8 @@ module ActiveSupport end RUBY_EVAL - class_eval str, __FILE__, __LINE__ + 1 + undef_method "_run_#{symbol}_callbacks" if method_defined?("_run_#{symbol}_callbacks") + class_eval str, __FILE__, __LINE__ before_name, around_name, after_name = options.values_at(:before, :after, :around) diff --git a/activesupport/lib/active_support/testing/pending.rb b/activesupport/lib/active_support/testing/pending.rb index b6905ddccd..d945c7e476 100644 --- a/activesupport/lib/active_support/testing/pending.rb +++ b/activesupport/lib/active_support/testing/pending.rb @@ -16,7 +16,7 @@ module ActiveSupport begin block.call - rescue + rescue Exception failed = true end diff --git a/activesupport/test/memoizable_test.rb b/activesupport/test/memoizable_test.rb index b03178900f..214e243aa5 100644 --- a/activesupport/test/memoizable_test.rb +++ b/activesupport/test/memoizable_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class MemoizableTest < Test::Unit::TestCase +class MemoizableTest < ActiveSupport::TestCase class Person extend ActiveSupport::Memoizable -- cgit v1.2.3 From 60896ca6f4c89260cb9770487f80dec829674b89 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Fri, 17 Apr 2009 13:44:59 -0500 Subject: Clearer String#first and #last edge cases. Fix that foo.first(0) == instead of foo. --- .../lib/active_support/core_ext/string/access.rb | 18 +++++++++++++++--- activesupport/test/core_ext/string_ext_test.rb | 2 ++ 2 files changed, 17 insertions(+), 3 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/core_ext/string/access.rb b/activesupport/lib/active_support/core_ext/string/access.rb index 7fb21fa4dd..e067f930da 100644 --- a/activesupport/lib/active_support/core_ext/string/access.rb +++ b/activesupport/lib/active_support/core_ext/string/access.rb @@ -41,9 +41,15 @@ module ActiveSupport #:nodoc: # "hello".first(2) # => "he" # "hello".first(10) # => "hello" def first(limit = 1) - mb_chars[0..(limit - 1)].to_s + if limit == 0 + '' + elsif limit >= size + self + else + mb_chars[0...limit].to_s + end end - + # Returns the last character of the string or the last +limit+ characters. # # Examples: @@ -51,7 +57,13 @@ module ActiveSupport #:nodoc: # "hello".last(2) # => "lo" # "hello".last(10) # => "hello" def last(limit = 1) - (mb_chars[(-limit)..-1] || self).to_s + if limit == 0 + '' + elsif limit >= size + self + else + mb_chars[(-limit)..-1].to_s + end end end else diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index 6c9b7e7236..7d51e81feb 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -132,10 +132,12 @@ class StringInflectionsTest < Test::Unit::TestCase assert_equal "h", s.first assert_equal "he", s.first(2) + assert_equal "", s.first(0) assert_equal "o", s.last assert_equal "llo", s.last(3) assert_equal "hello", s.last(10) + assert_equal "", s.last(0) assert_equal 'x', 'x'.first assert_equal 'x', 'x'.first(4) -- cgit v1.2.3 From 5d84c732ee06f58732167b74ae51d94ca216df12 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Mon, 20 Apr 2009 00:32:14 -0700 Subject: Treating strings as enumerable is deprecated --- activesupport/lib/active_support/new_callbacks.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/new_callbacks.rb b/activesupport/lib/active_support/new_callbacks.rb index 2ac5339f07..356d70b650 100644 --- a/activesupport/lib/active_support/new_callbacks.rb +++ b/activesupport/lib/active_support/new_callbacks.rb @@ -116,12 +116,12 @@ module ActiveSupport end def normalize_options!(options) - options[:if] = Array(options[:if]) - options[:unless] = Array(options[:unless]) + options[:if] = Array.wrap(options[:if]) + options[:unless] = Array.wrap(options[:unless]) options[:per_key] ||= {} - options[:per_key][:if] = Array(options[:per_key][:if]) - options[:per_key][:unless] = Array(options[:per_key][:unless]) + options[:per_key][:if] = Array.wrap(options[:per_key][:if]) + options[:per_key][:unless] = Array.wrap(options[:per_key][:unless]) end def next_id @@ -246,11 +246,11 @@ module ActiveSupport conditions = [] unless options[:if].empty? - conditions << Array(_compile_filter(options[:if])) + conditions << Array.wrap(_compile_filter(options[:if])) end unless options[:unless].empty? - conditions << Array(_compile_filter(options[:unless])).map {|f| "!#{f}"} + conditions << Array.wrap(_compile_filter(options[:unless])).map {|f| "!#{f}"} end ["if #{conditions.flatten.join(" && ")}", "end"] -- cgit v1.2.3 From 164a94d0bc8c9124ab820506e5ad79496395c026 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Mon, 20 Apr 2009 00:40:15 -0700 Subject: Clearer String#first and #last edge cases. Fix that 'foo'.first(0) == 'foo' instead of '' --- .../lib/active_support/core_ext/string/access.rb | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/core_ext/string/access.rb b/activesupport/lib/active_support/core_ext/string/access.rb index e067f930da..e806b321f1 100644 --- a/activesupport/lib/active_support/core_ext/string/access.rb +++ b/activesupport/lib/active_support/core_ext/string/access.rb @@ -81,11 +81,23 @@ module ActiveSupport #:nodoc: end def first(limit = 1) - self[0..(limit - 1)] + if limit == 0 + '' + elsif limit >= size + self + else + to(limit - 1) + end end def last(limit = 1) - from(-limit) || self + if limit == 0 + '' + elsif limit >= size + self + else + from(-limit) + end end end end -- cgit v1.2.3