activesupport 3.1.12 → 3.2.0.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (78) hide show
  1. data/CHANGELOG.md +1539 -30
  2. data/README.rdoc +2 -2
  3. data/lib/active_support.rb +1 -1
  4. data/lib/active_support/benchmarkable.rb +13 -18
  5. data/lib/active_support/buffered_logger.rb +43 -55
  6. data/lib/active_support/cache.rb +109 -115
  7. data/lib/active_support/cache/file_store.rb +6 -17
  8. data/lib/active_support/cache/mem_cache_store.rb +10 -2
  9. data/lib/active_support/cache/null_store.rb +44 -0
  10. data/lib/active_support/cache/strategy/local_cache.rb +2 -2
  11. data/lib/active_support/callbacks.rb +38 -35
  12. data/lib/active_support/concern.rb +5 -10
  13. data/lib/active_support/core_ext/array.rb +1 -0
  14. data/lib/active_support/core_ext/array/access.rb +1 -1
  15. data/lib/active_support/core_ext/array/prepend_and_append.rb +7 -0
  16. data/lib/active_support/core_ext/array/wrap.rb +1 -1
  17. data/lib/active_support/core_ext/class.rb +0 -1
  18. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -2
  19. data/lib/active_support/core_ext/date/calculations.rb +37 -14
  20. data/lib/active_support/core_ext/date/freeze.rb +6 -4
  21. data/lib/active_support/core_ext/date_time/calculations.rb +1 -1
  22. data/lib/active_support/core_ext/enumerable.rb +25 -8
  23. data/lib/active_support/core_ext/file/atomic.rb +1 -2
  24. data/lib/active_support/core_ext/hash/conversions.rb +7 -25
  25. data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -1
  26. data/lib/active_support/core_ext/io.rb +15 -0
  27. data/lib/active_support/core_ext/kernel.rb +0 -1
  28. data/lib/active_support/core_ext/kernel/agnostics.rb +2 -2
  29. data/lib/active_support/core_ext/kernel/debugger.rb +1 -7
  30. data/lib/active_support/core_ext/module.rb +2 -2
  31. data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -2
  32. data/lib/active_support/core_ext/module/delegation.rb +32 -21
  33. data/lib/active_support/core_ext/module/qualified_const.rb +64 -0
  34. data/lib/active_support/core_ext/module/reachable.rb +1 -3
  35. data/lib/active_support/core_ext/module/synchronization.rb +2 -0
  36. data/lib/active_support/core_ext/object/blank.rb +14 -2
  37. data/lib/active_support/core_ext/object/inclusion.rb +17 -7
  38. data/lib/active_support/core_ext/object/to_json.rb +2 -2
  39. data/lib/active_support/core_ext/range/conversions.rb +1 -1
  40. data/lib/active_support/core_ext/string/conversions.rb +2 -2
  41. data/lib/active_support/core_ext/string/inflections.rb +44 -6
  42. data/lib/active_support/core_ext/string/multibyte.rb +1 -1
  43. data/lib/active_support/core_ext/string/output_safety.rb +22 -25
  44. data/lib/active_support/core_ext/time/calculations.rb +66 -12
  45. data/lib/active_support/dependencies.rb +51 -52
  46. data/lib/active_support/file_update_checker.rb +100 -15
  47. data/lib/active_support/hash_with_indifferent_access.rb +5 -1
  48. data/lib/active_support/i18n.rb +1 -1
  49. data/lib/active_support/i18n_railtie.rb +9 -4
  50. data/lib/active_support/inflections.rb +3 -3
  51. data/lib/active_support/inflector/inflections.rb +53 -92
  52. data/lib/active_support/inflector/methods.rb +173 -9
  53. data/lib/active_support/json/decoding.rb +3 -17
  54. data/lib/active_support/json/encoding.rb +11 -14
  55. data/lib/active_support/memoizable.rb +12 -1
  56. data/lib/active_support/message_encryptor.rb +52 -20
  57. data/lib/active_support/message_verifier.rb +15 -4
  58. data/lib/active_support/notifications.rb +87 -14
  59. data/lib/active_support/notifications/instrumenter.rb +1 -2
  60. data/lib/active_support/ordered_hash.rb +7 -3
  61. data/lib/active_support/tagged_logging.rb +63 -0
  62. data/lib/active_support/testing/assertions.rb +1 -1
  63. data/lib/active_support/testing/mochaing.rb +2 -2
  64. data/lib/active_support/testing/performance/ruby.rb +1 -1
  65. data/lib/active_support/testing/setup_and_teardown.rb +4 -12
  66. data/lib/active_support/time_with_zone.rb +6 -3
  67. data/lib/active_support/values/time_zone.rb +3 -7
  68. data/lib/active_support/version.rb +3 -3
  69. data/lib/active_support/xml_mini.rb +3 -3
  70. data/lib/active_support/xml_mini/jdom.rb +4 -10
  71. metadata +28 -21
  72. checksums.yaml +0 -7
  73. data/lib/active_support/cache/compressed_mem_cache_store.rb +0 -13
  74. data/lib/active_support/cache/synchronized_memory_store.rb +0 -11
  75. data/lib/active_support/core_ext/class/inheritable_attributes.rb +0 -178
  76. data/lib/active_support/core_ext/kernel/requires.rb +0 -28
  77. data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +0 -31
  78. data/lib/active_support/secure_random.rb +0 -6
@@ -8,12 +8,13 @@ module ActiveSupport
8
8
  # A cache store implementation which stores everything on the filesystem.
9
9
  #
10
10
  # FileStore implements the Strategy::LocalCache strategy which implements
11
- # an in memory cache inside of a block.
11
+ # an in-memory cache inside of a block.
12
12
  class FileStore < Store
13
13
  attr_reader :cache_path
14
14
 
15
15
  DIR_FORMATTER = "%03X"
16
16
  FILENAME_MAX_SIZE = 230 # max filename size on file system is 255, minus room for timestamp and random characters appended by Tempfile (used by atomic write)
17
+ EXCLUDED_DIRS = ['.', '..'].freeze
17
18
 
18
19
  def initialize(cache_path, options = nil)
19
20
  super(options)
@@ -22,7 +23,7 @@ module ActiveSupport
22
23
  end
23
24
 
24
25
  def clear(options = nil)
25
- root_dirs = Dir.entries(cache_path).reject{|f| f.in?(['.', '..'])}
26
+ root_dirs = Dir.entries(cache_path).reject{|f| f.in?(EXCLUDED_DIRS)}
26
27
  FileUtils.rm_r(root_dirs.collect{|f| File.join(cache_path, f)})
27
28
  end
28
29
 
@@ -78,19 +79,7 @@ module ActiveSupport
78
79
  def read_entry(key, options)
79
80
  file_name = key_file_path(key)
80
81
  if File.exist?(file_name)
81
- entry = File.open(file_name) { |f| Marshal.load(f) }
82
- if entry && !entry.expired? && !entry.expires_in && !self.options[:expires_in]
83
- # Check for deprecated use of +:expires_in+ option from versions < 3.0
84
- deprecated_expires_in = options[:expires_in]
85
- if deprecated_expires_in
86
- ActiveSupport::Deprecation.warn('Setting :expires_in on read has been deprecated in favor of setting it on write.', caller)
87
- if entry.created_at + deprecated_expires_in.to_f <= Time.now.to_f
88
- delete_entry(key, options)
89
- entry = nil
90
- end
91
- end
92
- end
93
- entry
82
+ File.open(file_name) { |f| Marshal.load(f) }
94
83
  end
95
84
  rescue
96
85
  nil
@@ -161,7 +150,7 @@ module ActiveSupport
161
150
  # Delete empty directories in the cache.
162
151
  def delete_empty_directories(dir)
163
152
  return if dir == cache_path
164
- if Dir.entries(dir).reject{|f| f.in?(['.', '..'])}.empty?
153
+ if Dir.entries(dir).reject{|f| f.in?(EXCLUDED_DIRS)}.empty?
165
154
  File.delete(dir) rescue nil
166
155
  delete_empty_directories(File.dirname(dir))
167
156
  end
@@ -175,7 +164,7 @@ module ActiveSupport
175
164
  def search_dir(dir, &callback)
176
165
  return if !File.exist?(dir)
177
166
  Dir.foreach(dir) do |d|
178
- next if d == "." || d == ".."
167
+ next if d.in?(EXCLUDED_DIRS)
179
168
  name = File.join(dir, d)
180
169
  if File.directory?(name)
181
170
  search_dir(name, &callback)
@@ -11,7 +11,7 @@ require 'active_support/core_ext/string/encoding'
11
11
  module ActiveSupport
12
12
  module Cache
13
13
  # A cache store implementation which stores data in Memcached:
14
- # http://www.danga.com/memcached/
14
+ # http://memcached.org/
15
15
  #
16
16
  # This is currently the most popular cache store for production websites.
17
17
  #
@@ -21,7 +21,7 @@ module ActiveSupport
21
21
  # server goes down, then MemCacheStore will ignore it until it comes back up.
22
22
  #
23
23
  # MemCacheStore implements the Strategy::LocalCache strategy which implements
24
- # an in memory cache inside of a block.
24
+ # an in-memory cache inside of a block.
25
25
  class MemCacheStore < Store
26
26
  module Response # :nodoc:
27
27
  STORED = "STORED\r\n"
@@ -183,6 +183,14 @@ module ActiveSupport
183
183
  # Provide support for raw values in the local cache strategy.
184
184
  module LocalCacheWithRaw # :nodoc:
185
185
  protected
186
+ def read_entry(key, options)
187
+ entry = super
188
+ if options[:raw] && local_cache && entry
189
+ entry = deserialize_entry(entry.value)
190
+ end
191
+ entry
192
+ end
193
+
186
194
  def write_entry(key, entry, options) # :nodoc:
187
195
  retval = super
188
196
  if options[:raw] && local_cache && retval
@@ -0,0 +1,44 @@
1
+ module ActiveSupport
2
+ module Cache
3
+ # A cache store implementation which doesn't actually store anything. Useful in
4
+ # development and test environments where you don't want caching turned on but
5
+ # need to go through the caching interface.
6
+ #
7
+ # This cache does implement the local cache strategy, so values will actually
8
+ # be cached inside blocks that utilize this strategy. See
9
+ # ActiveSupport::Cache::Strategy::LocalCache for more details.
10
+ class NullStore < Store
11
+ def initialize(options = nil)
12
+ super(options)
13
+ extend Strategy::LocalCache
14
+ end
15
+
16
+ def clear(options = nil)
17
+ end
18
+
19
+ def cleanup(options = nil)
20
+ end
21
+
22
+ def increment(name, amount = 1, options = nil)
23
+ end
24
+
25
+ def decrement(name, amount = 1, options = nil)
26
+ end
27
+
28
+ def delete_matched(matcher, options = nil)
29
+ end
30
+
31
+ protected
32
+ def read_entry(key, options) # :nodoc:
33
+ end
34
+
35
+ def write_entry(key, entry, options) # :nodoc:
36
+ true
37
+ end
38
+
39
+ def delete_entry(key, options) # :nodoc:
40
+ false
41
+ end
42
+ end
43
+ end
44
+ end
@@ -4,9 +4,9 @@ require 'active_support/core_ext/string/inflections'
4
4
  module ActiveSupport
5
5
  module Cache
6
6
  module Strategy
7
- # Caches that implement LocalCache will be backed by an in memory cache for the
7
+ # Caches that implement LocalCache will be backed by an in-memory cache for the
8
8
  # duration of a block. Repeated calls to the cache for the same key will hit the
9
- # in memory cache for faster access.
9
+ # in-memory cache for faster access.
10
10
  module LocalCache
11
11
  # Simple memory backed cache. This cache is not thread safe and is intended only
12
12
  # for serving as a temporary memory cache for a single thread.
@@ -81,6 +81,14 @@ module ActiveSupport
81
81
  send("_run_#{kind}_callbacks", *args, &block)
82
82
  end
83
83
 
84
+ private
85
+
86
+ # A hook invoked everytime a before callback is halted.
87
+ # This can be overriden in AS::Callback implementors in order
88
+ # to provide better debugging/logging.
89
+ def halted_callback_hook(filter)
90
+ end
91
+
84
92
  class Callback #:nodoc:#
85
93
  @@_callback_sequence = 0
86
94
 
@@ -153,7 +161,7 @@ module ActiveSupport
153
161
 
154
162
  @klass.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
155
163
  def _one_time_conditions_valid_#{@callback_id}?
156
- true #{key_options[0]}
164
+ true if #{key_options}
157
165
  end
158
166
  RUBY_EVAL
159
167
  end
@@ -171,18 +179,18 @@ module ActiveSupport
171
179
  # if condition # before_save :filter_name, :if => :condition
172
180
  # filter_name
173
181
  # end
174
- filter = <<-RUBY_EVAL
175
- unless halted
176
- # This double assignment is to prevent warnings in 1.9.3. I would
177
- # remove the `result` variable, but apparently some other
178
- # generated code is depending on this variable being set sometimes
179
- # and sometimes not.
182
+ <<-RUBY_EVAL
183
+ if !halted && #{@compiled_options}
184
+ # This double assignment is to prevent warnings in 1.9.3 as
185
+ # the `result` variable is not always used except if the
186
+ # terminator code refers to it.
180
187
  result = result = #{@filter}
181
188
  halted = (#{chain.config[:terminator]})
189
+ if halted
190
+ halted_callback_hook(#{@raw_filter.inspect.inspect})
191
+ end
182
192
  end
183
193
  RUBY_EVAL
184
-
185
- [@compiled_options[0], filter, @compiled_options[1]].compact.join("\n")
186
194
  when :around
187
195
  # Compile around filters with conditions into proxy methods
188
196
  # that contain the conditions.
@@ -202,7 +210,7 @@ module ActiveSupport
202
210
  name = "_conditional_callback_#{@kind}_#{next_id}"
203
211
  @klass.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
204
212
  def #{name}(halted)
205
- #{@compiled_options[0] || "if true"} && !halted
213
+ if #{@compiled_options} && !halted
206
214
  #{@filter} do
207
215
  yield self
208
216
  end
@@ -222,10 +230,12 @@ module ActiveSupport
222
230
 
223
231
  case @kind
224
232
  when :after
225
- # if condition # after_save :filter_name, :if => :condition
226
- # filter_name
227
- # end
228
- [@compiled_options[0], @filter, @compiled_options[1]].compact.join("\n")
233
+ # after_save :filter_name, :if => :condition
234
+ <<-RUBY_EVAL
235
+ if #{@compiled_options}
236
+ #{@filter}
237
+ end
238
+ RUBY_EVAL
229
239
  when :around
230
240
  <<-RUBY_EVAL
231
241
  value
@@ -240,9 +250,7 @@ module ActiveSupport
240
250
  # symbols, string, procs, and objects), so compile a conditional
241
251
  # expression based on the options
242
252
  def _compile_options(options)
243
- return [] if options[:if].empty? && options[:unless].empty?
244
-
245
- conditions = []
253
+ conditions = ["true"]
246
254
 
247
255
  unless options[:if].empty?
248
256
  conditions << Array.wrap(_compile_filter(options[:if]))
@@ -252,7 +260,7 @@ module ActiveSupport
252
260
  conditions << Array.wrap(_compile_filter(options[:unless])).map {|f| "!#{f}"}
253
261
  end
254
262
 
255
- ["if #{conditions.flatten.join(" && ")}", "end"]
263
+ conditions.flatten.join(" && ")
256
264
  end
257
265
 
258
266
  # Filters support:
@@ -371,42 +379,37 @@ module ActiveSupport
371
379
  # Generate the internal runner method called by +run_callbacks+.
372
380
  def __define_runner(symbol) #:nodoc:
373
381
  body = send("_#{symbol}_callbacks").compile
382
+ runner_method = "_run_#{symbol}_callbacks"
374
383
 
375
384
  silence_warnings do
376
- undef_method "_run_#{symbol}_callbacks" if method_defined?("_run_#{symbol}_callbacks")
385
+ undef_method runner_method if method_defined?(runner_method)
377
386
  class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
378
- def _run_#{symbol}_callbacks(key = nil, &blk)
387
+ def #{runner_method}(key = nil, &blk)
379
388
  if key
380
- name = "_run__\#{self.class.name.hash.abs}__#{symbol}__\#{key.hash.abs}__callbacks"
381
-
382
- unless respond_to?(name)
383
- self.class.__create_keyed_callback(name, :#{symbol}, self, &blk)
384
- end
385
-
386
- send(name, &blk)
389
+ self.class.__run_keyed_callback(key, :#{symbol}, self, &blk)
387
390
  else
388
391
  #{body}
389
392
  end
390
393
  end
391
- private :_run_#{symbol}_callbacks
394
+ private :#{runner_method}
392
395
  RUBY_EVAL
393
396
  end
394
397
  end
395
398
 
396
- # This is called the first time a callback is called with a particular
397
- # key. It creates a new callback method for the key, calculating
398
- # which callbacks can be omitted because of per_key conditions.
399
+ # This method calls the callback method for the given key.
400
+ # If this called first time it creates a new callback method for the key,
401
+ # calculating which callbacks can be omitted because of per_key conditions.
399
402
  #
400
- def __create_keyed_callback(name, kind, object, &blk) #:nodoc:
401
- @_keyed_callbacks ||= {}
402
- @_keyed_callbacks[name] ||= begin
403
+ def __run_keyed_callback(key, kind, object, &blk) #:nodoc:
404
+ name = "_run__#{self.name.hash.abs}__#{kind}__#{key.hash.abs}__callbacks"
405
+ unless object.respond_to?(name)
403
406
  str = send("_#{kind}_callbacks").compile(name, object)
404
407
  class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
405
408
  def #{name}() #{str} end
406
409
  protected :#{name}
407
410
  RUBY_EVAL
408
- true
409
411
  end
412
+ object.send(name, &blk)
410
413
  end
411
414
 
412
415
  # This is used internally to append, prepend and skip callbacks to the
@@ -4,17 +4,12 @@ module ActiveSupport
4
4
  # module M
5
5
  # def self.included(base)
6
6
  # base.extend ClassMethods
7
- # base.send(:include, InstanceMethods)
8
7
  # scope :disabled, where(:disabled => true)
9
8
  # end
10
9
  #
11
10
  # module ClassMethods
12
11
  # ...
13
12
  # end
14
- #
15
- # module InstanceMethods
16
- # ...
17
- # end
18
13
  # end
19
14
  #
20
15
  # By using <tt>ActiveSupport::Concern</tt> the above module could instead be written as:
@@ -31,10 +26,6 @@ module ActiveSupport
31
26
  # module ClassMethods
32
27
  # ...
33
28
  # end
34
- #
35
- # module InstanceMethods
36
- # ...
37
- # end
38
29
  # end
39
30
  #
40
31
  # Moreover, it gracefully handles module dependencies. Given a +Foo+ module and a +Bar+
@@ -118,7 +109,11 @@ module ActiveSupport
118
109
  @_dependencies.each { |dep| base.send(:include, dep) }
119
110
  super
120
111
  base.extend const_get("ClassMethods") if const_defined?("ClassMethods")
121
- base.send :include, const_get("InstanceMethods") if const_defined?("InstanceMethods")
112
+ if const_defined?("InstanceMethods")
113
+ base.send :include, const_get("InstanceMethods")
114
+ ActiveSupport::Deprecation.warn "The InstanceMethods module inside ActiveSupport::Concern will be " \
115
+ "no longer included automatically. Please define instance methods directly in #{base} instead.", caller
116
+ end
122
117
  base.class_eval(&@_included_block) if instance_variable_defined?("@_included_block")
123
118
  end
124
119
  end
@@ -5,3 +5,4 @@ require 'active_support/core_ext/array/conversions'
5
5
  require 'active_support/core_ext/array/extract_options'
6
6
  require 'active_support/core_ext/array/grouping'
7
7
  require 'active_support/core_ext/array/random_access'
8
+ require 'active_support/core_ext/array/prepend_and_append'
@@ -16,7 +16,7 @@ class Array
16
16
  # %w( a b c d ).to(10) # => %w( a b c d )
17
17
  # %w().to(0) # => %w()
18
18
  def to(position)
19
- self[0..position]
19
+ self.first position + 1
20
20
  end
21
21
 
22
22
  # Equal to <tt>self[1]</tt>.
@@ -0,0 +1,7 @@
1
+ class Array
2
+ # The human way of thinking about adding stuff to the end of a list is with append
3
+ alias_method :append, :<<
4
+
5
+ # The human way of thinking about adding stuff to the beginning of a list is with prepend
6
+ alias_method :prepend, :unshift
7
+ end
@@ -40,7 +40,7 @@ class Array
40
40
  if object.nil?
41
41
  []
42
42
  elsif object.respond_to?(:to_ary)
43
- object.to_ary
43
+ object.to_ary || [object]
44
44
  else
45
45
  [object]
46
46
  end
@@ -1,5 +1,4 @@
1
1
  require 'active_support/core_ext/class/attribute'
2
2
  require 'active_support/core_ext/class/attribute_accessors'
3
- require 'active_support/core_ext/class/inheritable_attributes'
4
3
  require 'active_support/core_ext/class/delegating_attributes'
5
4
  require 'active_support/core_ext/class/subclasses'
@@ -17,6 +17,7 @@ require 'active_support/core_ext/array/extract_options'
17
17
  #
18
18
  # To opt out of the instance writer method, pass :instance_writer => false.
19
19
  # To opt out of the instance reader method, pass :instance_reader => false.
20
+ # To opt out of both instance methods, pass :instance_accessor => false.
20
21
  #
21
22
  # class Person
22
23
  # cattr_accessor :hair_colors, :instance_writer => false, :instance_reader => false
@@ -38,7 +39,7 @@ class Class
38
39
  end
39
40
  EOS
40
41
 
41
- unless options[:instance_reader] == false
42
+ unless options[:instance_reader] == false || options[:instance_accessor] == false
42
43
  class_eval(<<-EOS, __FILE__, __LINE__ + 1)
43
44
  def #{sym}
44
45
  @@#{sym}
@@ -61,7 +62,7 @@ class Class
61
62
  end
62
63
  EOS
63
64
 
64
- unless options[:instance_writer] == false
65
+ unless options[:instance_writer] == false || options[:instance_accessor] == false
65
66
  class_eval(<<-EOS, __FILE__, __LINE__ + 1)
66
67
  def #{sym}=(obj)
67
68
  @@#{sym} = obj
@@ -103,7 +103,7 @@ class Date
103
103
  alias_method :minus_without_duration, :-
104
104
  alias_method :-, :minus_with_duration
105
105
 
106
- # Provides precise Date calculations for years, months, and days. The +options+ parameter takes a hash with
106
+ # Provides precise Date calculations for years, months, and days. The +options+ parameter takes a hash with
107
107
  # any of these keys: <tt>:years</tt>, <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>.
108
108
  def advance(options)
109
109
  options = options.dup
@@ -174,31 +174,54 @@ class Date
174
174
  months_since(1)
175
175
  end unless method_defined?(:next_month)
176
176
 
177
- # Returns a new Date/DateTime representing the "start" of this week (i.e, Monday; DateTime objects will have time set to 0:00).
178
- def beginning_of_week
179
- days_to_monday = self.wday!=0 ? self.wday-1 : 6
180
- result = self - days_to_monday
181
- self.acts_like?(:time) ? result.midnight : result
177
+ # Returns number of days to start of this week. Week is assumed to start on
178
+ # +start_day+, default is +:monday+.
179
+ def days_to_week_start(start_day = :monday)
180
+ start_day_number = DAYS_INTO_WEEK[start_day]
181
+ current_day_number = wday != 0 ? wday - 1 : 6
182
+ (current_day_number - start_day_number) % 7
183
+ end
184
+
185
+ # Returns a new +Date+/+DateTime+ representing the start of this week. Week is
186
+ # assumed to start on +start_day+, default is +:monday+. +DateTime+ objects
187
+ # have their time set to 0:00.
188
+ def beginning_of_week(start_day = :monday)
189
+ days_to_start = days_to_week_start(start_day)
190
+ result = self - days_to_start
191
+ acts_like?(:time) ? result.midnight : result
182
192
  end
183
- alias :monday :beginning_of_week
184
193
  alias :at_beginning_of_week :beginning_of_week
185
194
 
186
- # Returns a new Date/DateTime representing the end of this week (Sunday, DateTime objects will have time set to 23:59:59).
187
- def end_of_week
188
- days_to_sunday = self.wday!=0 ? 7-self.wday : 0
189
- result = self + days_to_sunday.days
195
+ # Returns a new +Date+/+DateTime+ representing the start of this week. Week is
196
+ # assumed to start on a Monday. +DateTime+ objects have their time set to 0:00.
197
+ def monday
198
+ beginning_of_week
199
+ end
200
+
201
+ # Returns a new +Date+/+DateTime+ representing the end of this week. Week is
202
+ # assumed to start on +start_day+, default is +:monday+. +DateTime+ objects
203
+ # have their time set to 23:59:59.
204
+ def end_of_week(start_day = :monday)
205
+ days_to_end = 6 - days_to_week_start(start_day)
206
+ result = self + days_to_end.days
190
207
  self.acts_like?(:time) ? result.end_of_day : result
191
208
  end
192
- alias :sunday :end_of_week
193
209
  alias :at_end_of_week :end_of_week
194
210
 
195
- # Returns a new Date/DateTime representing the start of the given day in the previous week (default is Monday).
211
+ # Returns a new +Date+/+DateTime+ representing the end of this week. Week is
212
+ # assumed to start on a Monday. +DateTime+ objects have their time set to 23:59:59.
213
+ def sunday
214
+ end_of_week
215
+ end
216
+
217
+ # Returns a new +Date+/+DateTime+ representing the given +day+ in the previous
218
+ # week. Default is +:monday+. +DateTime+ objects have their time set to 0:00.
196
219
  def prev_week(day = :monday)
197
220
  result = (self - 7).beginning_of_week + DAYS_INTO_WEEK[day]
198
221
  self.acts_like?(:time) ? result.change(:hour => 0) : result
199
222
  end
200
223
 
201
- # Returns a new Date/DateTime representing the start of the given day in next week (default is Monday).
224
+ # Returns a new Date/DateTime representing the start of the given day in next week (default is :monday).
202
225
  def next_week(day = :monday)
203
226
  result = (self + 7).beginning_of_week + DAYS_INTO_WEEK[day]
204
227
  self.acts_like?(:time) ? result.change(:hour => 0) : result