aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport')
-rw-r--r--activesupport/CHANGELOG.md3
-rw-r--r--activesupport/lib/active_support/core_ext/date/calculations.rb47
-rw-r--r--activesupport/lib/active_support/core_ext/object/inclusion.rb24
-rw-r--r--activesupport/lib/active_support/core_ext/object/to_json.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/time/calculations.rb37
-rw-r--r--activesupport/lib/active_support/dependencies.rb34
-rw-r--r--activesupport/lib/active_support/json/encoding.rb8
-rw-r--r--activesupport/test/class_cache_test.rb43
-rw-r--r--activesupport/test/core_ext/date_ext_test.rb10
-rw-r--r--activesupport/test/core_ext/date_time_ext_test.rb18
-rw-r--r--activesupport/test/core_ext/object/inclusion_test.rb10
-rw-r--r--activesupport/test/core_ext/time_ext_test.rb20
12 files changed, 196 insertions, 62 deletions
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index 18a115b369..465b0c1e16 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,5 +1,8 @@
## Rails 3.2.0 (unreleased) ##
+* (Date|DateTime|Time)#beginning_of_week accept an optional argument to
+ be able to set the day at which weeks are assumed to start.
+
* Deprecated ActiveSupport::MessageEncryptor#encrypt and decrypt. *José Valim*
* ActiveSupport::Notifications.subscribed provides subscriptions to events while a block runs. *fxn*
diff --git a/activesupport/lib/active_support/core_ext/date/calculations.rb b/activesupport/lib/active_support/core_ext/date/calculations.rb
index c6d5f29690..f0f67765c6 100644
--- a/activesupport/lib/active_support/core_ext/date/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/date/calculations.rb
@@ -174,25 +174,48 @@ class Date
months_since(1)
end unless method_defined?(:next_month)
- # Returns a new Date/DateTime representing the "start" of this week (i.e, Monday; DateTime objects will have time set to 0:00).
- def beginning_of_week
- days_to_monday = self.wday!=0 ? self.wday-1 : 6
- result = self - days_to_monday
- self.acts_like?(:time) ? result.midnight : result
+ # Returns number of days to start of this week. Week is assumed to start on
+ # +start_day+, default is +:monday+.
+ def days_to_week_start(start_day = :monday)
+ start_day_number = DAYS_INTO_WEEK[start_day]
+ current_day_number = wday != 0 ? wday - 1 : 6
+ (current_day_number - start_day_number) % 7
+ end
+
+ # Returns a new +Date+/+DateTime+ representing the start of this week. Week is
+ # assumed to start on +start_day+, default is +:monday+. +DateTime+ objects
+ # have their time set to 0:00.
+ def beginning_of_week(start_day = :monday)
+ days_to_start = days_to_week_start(start_day)
+ result = self - days_to_start
+ acts_like?(:time) ? result.midnight : result
end
- alias :monday :beginning_of_week
alias :at_beginning_of_week :beginning_of_week
- # Returns a new Date/DateTime representing the end of this week (Sunday, DateTime objects will have time set to 23:59:59).
- def end_of_week
- days_to_sunday = self.wday!=0 ? 7-self.wday : 0
- result = self + days_to_sunday.days
+ # Returns a new +Date+/+DateTime+ representing the start of this week. Week is
+ # assumed to start on a Monday. +DateTime+ objects have their time set to 0:00.
+ def monday
+ beginning_of_week
+ end
+
+ # Returns a new +Date+/+DateTime+ representing the end of this week. Week is
+ # assumed to start on +start_day+, default is +:monday+. +DateTime+ objects
+ # have their time set to 23:59:59.
+ def end_of_week(start_day = :monday)
+ days_to_end = 6 - days_to_week_start(start_day)
+ result = self + days_to_end.days
self.acts_like?(:time) ? result.end_of_day : result
end
- alias :sunday :end_of_week
alias :at_end_of_week :end_of_week
- # Returns a new Date/DateTime representing the start of the given day in the previous week (default is :monday).
+ # Returns a new +Date+/+DateTime+ representing the end of this week. Week is
+ # assumed to start on a Monday. +DateTime+ objects have their time set to 23:59:59.
+ def sunday
+ end_of_week
+ end
+
+ # Returns a new +Date+/+DateTime+ representing the given +day+ in the previous
+ # week. Default is +:monday+. +DateTime+ objects have their time set to 0:00.
def prev_week(day = :monday)
result = (self - 7).beginning_of_week + DAYS_INTO_WEEK[day]
self.acts_like?(:time) ? result.change(:hour => 0) : result
diff --git a/activesupport/lib/active_support/core_ext/object/inclusion.rb b/activesupport/lib/active_support/core_ext/object/inclusion.rb
index b5671f66d0..f611cdd606 100644
--- a/activesupport/lib/active_support/core_ext/object/inclusion.rb
+++ b/activesupport/lib/active_support/core_ext/object/inclusion.rb
@@ -1,15 +1,25 @@
class Object
- # Returns true if this object is included in the argument. Argument must be
- # any object which responds to +#include?+. Usage:
+ # Returns true if this object is included in the argument(s). Argument must be
+ # any object which responds to +#include?+ or optionally, multiple arguments can be passed in. Usage:
#
# characters = ["Konata", "Kagami", "Tsukasa"]
# "Konata".in?(characters) # => true
+ #
+ # character = "Konata"
+ # character.in?("Konata", "Kagami", "Tsukasa") # => true
#
- # This will throw an ArgumentError if the argument doesn't respond
+ # This will throw an ArgumentError if a single argument is passed in and it doesn't respond
# to +#include?+.
- def in?(another_object)
- another_object.include?(self)
- rescue NoMethodError
- raise ArgumentError.new("The parameter passed to #in? must respond to #include?")
+ def in?(*args)
+ if args.length > 1
+ args.include? self
+ else
+ another_object = args.first
+ if another_object.respond_to? :include?
+ another_object.include? self
+ else
+ raise ArgumentError.new("The single parameter passed to #in? must respond to #include?")
+ end
+ end
end
end
diff --git a/activesupport/lib/active_support/core_ext/object/to_json.rb b/activesupport/lib/active_support/core_ext/object/to_json.rb
index 14ef27340e..e7dc60a612 100644
--- a/activesupport/lib/active_support/core_ext/object/to_json.rb
+++ b/activesupport/lib/active_support/core_ext/object/to_json.rb
@@ -10,10 +10,10 @@ end
# several cases (for instance, the JSON implementation for Hash does not work) with inheritance
# and consequently classes as ActiveSupport::OrderedHash cannot be serialized to json.
[Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass].each do |klass|
- klass.class_eval <<-RUBY, __FILE__, __LINE__
+ klass.class_eval do
# Dumps object in JSON (JavaScript Object Notation). See www.json.org for more info.
def to_json(options = nil)
ActiveSupport::JSON.encode(self, options)
end
- RUBY
+ end
end
diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb
index 1e15529569..f3235d11bb 100644
--- a/activesupport/lib/active_support/core_ext/time/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/time/calculations.rb
@@ -161,21 +161,40 @@ class Time
months_since(1)
end
- # Returns a new Time representing the "start" of this week (Monday, 0:00)
- def beginning_of_week
- days_to_monday = wday!=0 ? wday-1 : 6
- (self - days_to_monday.days).midnight
+ # Returns number of days to start of this week, week starts on start_day (default is :monday).
+ def days_to_week_start(start_day = :monday)
+ start_day_number = DAYS_INTO_WEEK[start_day]
+ current_day_number = wday != 0 ? wday - 1 : 6
+ days_span = current_day_number - start_day_number
+ days_span >= 0 ? days_span : 7 + days_span
+ end
+
+ # Returns a new Time representing the "start" of this week, week starts on start_day (default is :monday, i.e. Monday, 0:00).
+ def beginning_of_week(start_day = :monday)
+ days_to_start = days_to_week_start(start_day)
+ (self - days_to_start.days).midnight
end
- alias :monday :beginning_of_week
alias :at_beginning_of_week :beginning_of_week
- # Returns a new Time representing the end of this week, (end of Sunday)
- def end_of_week
- days_to_sunday = wday!=0 ? 7-wday : 0
- (self + days_to_sunday.days).end_of_day
+ # Returns a new +Date+/+DateTime+ representing the start of this week. Week is
+ # assumed to start on a Monday. +DateTime+ objects have their time set to 0:00.
+ def monday
+ beginning_of_week
+ end
+
+ # Returns a new Time representing the end of this week, week starts on start_day (default is :monday, i.e. end of Sunday).
+ def end_of_week(start_day = :monday)
+ days_to_end = 6 - days_to_week_start(start_day)
+ (self + days_to_end.days).end_of_day
end
alias :at_end_of_week :end_of_week
+ # Returns a new +Date+/+DateTime+ representing the end of this week. Week is
+ # assumed to start on a Monday. +DateTime+ objects have their time set to 23:59:59.
+ def sunday
+ end_of_week
+ end
+
# Returns a new Time representing the start of the given day in the previous week (default is :monday).
def prev_week(day = :monday)
ago(1.week).beginning_of_week.since(DAYS_INTO_WEEK[day].day).change(:hour => 0)
diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb
index db90de4682..1372e71a61 100644
--- a/activesupport/lib/active_support/dependencies.rb
+++ b/activesupport/lib/active_support/dependencies.rb
@@ -527,7 +527,7 @@ module ActiveSupport #:nodoc:
class ClassCache
def initialize
- @store = Hash.new { |h, k| h[k] = Inflector.constantize(k) }
+ @store = Hash.new
end
def empty?
@@ -538,23 +538,24 @@ module ActiveSupport #:nodoc:
@store.key?(key)
end
- def []=(key, value)
- return unless key.respond_to?(:name)
-
- raise(ArgumentError, 'anonymous classes cannot be cached') if key.name.blank?
-
- @store[key.name] = value
+ def get(key)
+ key = key.name if key.respond_to?(:name)
+ @store[key] ||= Inflector.constantize(key)
end
+ alias :[] :get
- def [](key)
+ def safe_get(key)
key = key.name if key.respond_to?(:name)
-
- @store[key]
+ @store[key] || begin
+ klass = Inflector.safe_constantize(key)
+ @store[key] = klass
+ end
end
- alias :get :[]
- def store(name)
- self[name] = name
+ def store(klass)
+ return self unless klass.respond_to?(:name)
+ raise(ArgumentError, 'anonymous classes cannot be cached') if klass.name.empty?
+ @store[klass.name] = klass
self
end
@@ -571,10 +572,17 @@ module ActiveSupport #:nodoc:
end
# Get the reference for class named +name+.
+ # Raises an exception if referenced class does not exist.
def constantize(name)
Reference.get(name)
end
+ # Get the reference for class named +name+ if one exists.
+ # Otherwise returns nil.
+ def safe_constantize(name)
+ Reference.safe_get(name)
+ end
+
# Determine if the given constant has been automatically loaded.
def autoloaded?(desc)
# No name => anonymous module.
diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb
index 469ae69258..b0fd3a3c0e 100644
--- a/activesupport/lib/active_support/json/encoding.rb
+++ b/activesupport/lib/active_support/json/encoding.rb
@@ -50,9 +50,9 @@ module ActiveSupport
end
# like encode, but only calls as_json, without encoding to string
- def as_json(value)
+ def as_json(value, use_options = true)
check_for_circular_references(value) do
- value.as_json(options_for(value))
+ use_options ? value.as_json(options_for(value)) : value.as_json
end
end
@@ -212,7 +212,7 @@ class Array
def as_json(options = nil) #:nodoc:
# use encoder as a proxy to call as_json on all elements, to protect from circular references
encoder = options && options[:encoder] || ActiveSupport::JSON::Encoding::Encoder.new(options)
- map { |v| encoder.as_json(v) }
+ map { |v| encoder.as_json(v, options) }
end
def encode_json(encoder) #:nodoc:
@@ -239,7 +239,7 @@ class Hash
# use encoder as a proxy to call as_json on all values in the subset, to protect from circular references
encoder = options && options[:encoder] || ActiveSupport::JSON::Encoding::Encoder.new(options)
result = self.is_a?(ActiveSupport::OrderedHash) ? ActiveSupport::OrderedHash : Hash
- result[subset.map { |k, v| [k.to_s, encoder.as_json(v)] }]
+ result[subset.map { |k, v| [k.to_s, encoder.as_json(v, options)] }]
end
def encode_json(encoder)
diff --git a/activesupport/test/class_cache_test.rb b/activesupport/test/class_cache_test.rb
index 752c0ee478..b96f476ce6 100644
--- a/activesupport/test/class_cache_test.rb
+++ b/activesupport/test/class_cache_test.rb
@@ -10,45 +10,58 @@ module ActiveSupport
def test_empty?
assert @cache.empty?
- @cache[ClassCacheTest] = ClassCacheTest
+ @cache.store(ClassCacheTest)
assert !@cache.empty?
end
def test_clear!
assert @cache.empty?
- @cache[ClassCacheTest] = ClassCacheTest
+ @cache.store(ClassCacheTest)
assert !@cache.empty?
@cache.clear!
assert @cache.empty?
end
def test_set_key
- @cache[ClassCacheTest] = ClassCacheTest
+ @cache.store(ClassCacheTest)
assert @cache.key?(ClassCacheTest.name)
end
- def test_set_rejects_strings
- @cache[ClassCacheTest.name] = ClassCacheTest
- assert @cache.empty?
- end
-
def test_get_with_class
- @cache[ClassCacheTest] = ClassCacheTest
- assert_equal ClassCacheTest, @cache[ClassCacheTest]
+ @cache.store(ClassCacheTest)
+ assert_equal ClassCacheTest, @cache.get(ClassCacheTest)
end
def test_get_with_name
- @cache[ClassCacheTest] = ClassCacheTest
- assert_equal ClassCacheTest, @cache[ClassCacheTest.name]
+ @cache.store(ClassCacheTest)
+ assert_equal ClassCacheTest, @cache.get(ClassCacheTest.name)
end
def test_get_constantizes
assert @cache.empty?
- assert_equal ClassCacheTest, @cache[ClassCacheTest.name]
+ assert_equal ClassCacheTest, @cache.get(ClassCacheTest.name)
end
- def test_get_is_an_alias
- assert_equal @cache[ClassCacheTest], @cache.get(ClassCacheTest.name)
+ def test_get_constantizes_fails_on_invalid_names
+ assert @cache.empty?
+ assert_raise NameError do
+ @cache.get("OmgTotallyInvalidConstantName")
+ end
+ end
+
+ def test_get_alias
+ assert @cache.empty?
+ assert_equal @cache[ClassCacheTest.name], @cache.get(ClassCacheTest.name)
+ end
+
+ def test_safe_get_constantizes
+ assert @cache.empty?
+ assert_equal ClassCacheTest, @cache.safe_get(ClassCacheTest.name)
+ end
+
+ def test_safe_get_constantizes_doesnt_fail_on_invalid_names
+ assert @cache.empty?
+ assert_equal nil, @cache.safe_get("OmgTotallyInvalidConstantName")
end
def test_new_rejects_strings
diff --git a/activesupport/test/core_ext/date_ext_test.rb b/activesupport/test/core_ext/date_ext_test.rb
index b4f848cd44..c040d86327 100644
--- a/activesupport/test/core_ext/date_ext_test.rb
+++ b/activesupport/test/core_ext/date_ext_test.rb
@@ -57,6 +57,16 @@ class DateExtCalculationsTest < ActiveSupport::TestCase
assert_equal Date.new(2005,11,28), Date.new(2005,12,04).beginning_of_week #sunday
end
+ def test_monday
+ assert_equal Date.new(2005,11,28), Date.new(2005,11,28).monday
+ assert_equal Date.new(2005,11,28), Date.new(2005,12,01).monday
+ end
+
+ def test_sunday
+ assert_equal Date.new(2008,3,2), Date.new(2008,3,02).sunday
+ assert_equal Date.new(2008,3,2), Date.new(2008,2,29).sunday
+ end
+
def test_beginning_of_week_in_calendar_reform
assert_equal Date.new(1582,10,1), Date.new(1582,10,15).beginning_of_week #friday
end
diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb
index 9be28272f7..0087163faf 100644
--- a/activesupport/test/core_ext/date_time_ext_test.rb
+++ b/activesupport/test/core_ext/date_time_ext_test.rb
@@ -54,6 +54,24 @@ class DateTimeExtCalculationsTest < Test::Unit::TestCase
assert_equal 86399,DateTime.civil(2005,1,1,23,59,59).seconds_since_midnight
end
+ def test_days_to_week_start
+ assert_equal 0, Time.local(2011,11,01,0,0,0).days_to_week_start(:tuesday)
+ assert_equal 1, Time.local(2011,11,02,0,0,0).days_to_week_start(:tuesday)
+ assert_equal 2, Time.local(2011,11,03,0,0,0).days_to_week_start(:tuesday)
+ assert_equal 3, Time.local(2011,11,04,0,0,0).days_to_week_start(:tuesday)
+ assert_equal 4, Time.local(2011,11,05,0,0,0).days_to_week_start(:tuesday)
+ assert_equal 5, Time.local(2011,11,06,0,0,0).days_to_week_start(:tuesday)
+ assert_equal 6, Time.local(2011,11,07,0,0,0).days_to_week_start(:tuesday)
+
+ assert_equal 3, Time.local(2011,11,03,0,0,0).days_to_week_start(:monday)
+ assert_equal 3, Time.local(2011,11,04,0,0,0).days_to_week_start(:tuesday)
+ assert_equal 3, Time.local(2011,11,05,0,0,0).days_to_week_start(:wednesday)
+ assert_equal 3, Time.local(2011,11,06,0,0,0).days_to_week_start(:thursday)
+ assert_equal 3, Time.local(2011,11,07,0,0,0).days_to_week_start(:friday)
+ assert_equal 3, Time.local(2011,11,8,0,0,0).days_to_week_start(:saturday)
+ assert_equal 3, Time.local(2011,11,9,0,0,0).days_to_week_start(:sunday)
+ end
+
def test_beginning_of_week
assert_equal DateTime.civil(2005,1,31), DateTime.civil(2005,2,4,10,10,10).beginning_of_week
assert_equal DateTime.civil(2005,11,28), DateTime.civil(2005,11,28,0,0,0).beginning_of_week #monday
diff --git a/activesupport/test/core_ext/object/inclusion_test.rb b/activesupport/test/core_ext/object/inclusion_test.rb
index 1de857d678..568ebe9aab 100644
--- a/activesupport/test/core_ext/object/inclusion_test.rb
+++ b/activesupport/test/core_ext/object/inclusion_test.rb
@@ -2,6 +2,16 @@ require 'abstract_unit'
require 'active_support/core_ext/object/inclusion'
class InTest < Test::Unit::TestCase
+ def test_in_multiple_args
+ assert :b.in?(:a,:b)
+ assert !:c.in?(:a,:b)
+ end
+
+ def test_in_multiple_arrays
+ assert [1,2].in?([1,2],[2,3])
+ assert ![1,2].in?([1,3],[2,1])
+ end
+
def test_in_array
assert 1.in?([1,2])
assert !3.in?([1,2])
diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb
index d2ff44e1b4..6cc63851e9 100644
--- a/activesupport/test/core_ext/time_ext_test.rb
+++ b/activesupport/test/core_ext/time_ext_test.rb
@@ -59,8 +59,28 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase
assert_equal Time.local(2005,11,28), Time.local(2005,12,02,0,0,0).beginning_of_week #friday
assert_equal Time.local(2005,11,28), Time.local(2005,12,03,0,0,0).beginning_of_week #saturday
assert_equal Time.local(2005,11,28), Time.local(2005,12,04,0,0,0).beginning_of_week #sunday
+
end
+ def test_days_to_week_start
+ assert_equal 0, Time.local(2011,11,01,0,0,0).days_to_week_start(:tuesday)
+ assert_equal 1, Time.local(2011,11,02,0,0,0).days_to_week_start(:tuesday)
+ assert_equal 2, Time.local(2011,11,03,0,0,0).days_to_week_start(:tuesday)
+ assert_equal 3, Time.local(2011,11,04,0,0,0).days_to_week_start(:tuesday)
+ assert_equal 4, Time.local(2011,11,05,0,0,0).days_to_week_start(:tuesday)
+ assert_equal 5, Time.local(2011,11,06,0,0,0).days_to_week_start(:tuesday)
+ assert_equal 6, Time.local(2011,11,07,0,0,0).days_to_week_start(:tuesday)
+
+ assert_equal 3, Time.local(2011,11,03,0,0,0).days_to_week_start(:monday)
+ assert_equal 3, Time.local(2011,11,04,0,0,0).days_to_week_start(:tuesday)
+ assert_equal 3, Time.local(2011,11,05,0,0,0).days_to_week_start(:wednesday)
+ assert_equal 3, Time.local(2011,11,06,0,0,0).days_to_week_start(:thursday)
+ assert_equal 3, Time.local(2011,11,07,0,0,0).days_to_week_start(:friday)
+ assert_equal 3, Time.local(2011,11,8,0,0,0).days_to_week_start(:saturday)
+ assert_equal 3, Time.local(2011,11,9,0,0,0).days_to_week_start(:sunday)
+ end
+
+
def test_beginning_of_day
assert_equal Time.local(2005,2,4,0,0,0), Time.local(2005,2,4,10,10,10).beginning_of_day
with_env_tz 'US/Eastern' do