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.
- data/CHANGELOG.md +1539 -30
- data/README.rdoc +2 -2
- data/lib/active_support.rb +1 -1
- data/lib/active_support/benchmarkable.rb +13 -18
- data/lib/active_support/buffered_logger.rb +43 -55
- data/lib/active_support/cache.rb +109 -115
- data/lib/active_support/cache/file_store.rb +6 -17
- data/lib/active_support/cache/mem_cache_store.rb +10 -2
- data/lib/active_support/cache/null_store.rb +44 -0
- data/lib/active_support/cache/strategy/local_cache.rb +2 -2
- data/lib/active_support/callbacks.rb +38 -35
- data/lib/active_support/concern.rb +5 -10
- data/lib/active_support/core_ext/array.rb +1 -0
- data/lib/active_support/core_ext/array/access.rb +1 -1
- data/lib/active_support/core_ext/array/prepend_and_append.rb +7 -0
- data/lib/active_support/core_ext/array/wrap.rb +1 -1
- data/lib/active_support/core_ext/class.rb +0 -1
- data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -2
- data/lib/active_support/core_ext/date/calculations.rb +37 -14
- data/lib/active_support/core_ext/date/freeze.rb +6 -4
- data/lib/active_support/core_ext/date_time/calculations.rb +1 -1
- data/lib/active_support/core_ext/enumerable.rb +25 -8
- data/lib/active_support/core_ext/file/atomic.rb +1 -2
- data/lib/active_support/core_ext/hash/conversions.rb +7 -25
- data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -1
- data/lib/active_support/core_ext/io.rb +15 -0
- data/lib/active_support/core_ext/kernel.rb +0 -1
- data/lib/active_support/core_ext/kernel/agnostics.rb +2 -2
- data/lib/active_support/core_ext/kernel/debugger.rb +1 -7
- data/lib/active_support/core_ext/module.rb +2 -2
- data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -2
- data/lib/active_support/core_ext/module/delegation.rb +32 -21
- data/lib/active_support/core_ext/module/qualified_const.rb +64 -0
- data/lib/active_support/core_ext/module/reachable.rb +1 -3
- data/lib/active_support/core_ext/module/synchronization.rb +2 -0
- data/lib/active_support/core_ext/object/blank.rb +14 -2
- data/lib/active_support/core_ext/object/inclusion.rb +17 -7
- data/lib/active_support/core_ext/object/to_json.rb +2 -2
- data/lib/active_support/core_ext/range/conversions.rb +1 -1
- data/lib/active_support/core_ext/string/conversions.rb +2 -2
- data/lib/active_support/core_ext/string/inflections.rb +44 -6
- data/lib/active_support/core_ext/string/multibyte.rb +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +22 -25
- data/lib/active_support/core_ext/time/calculations.rb +66 -12
- data/lib/active_support/dependencies.rb +51 -52
- data/lib/active_support/file_update_checker.rb +100 -15
- data/lib/active_support/hash_with_indifferent_access.rb +5 -1
- data/lib/active_support/i18n.rb +1 -1
- data/lib/active_support/i18n_railtie.rb +9 -4
- data/lib/active_support/inflections.rb +3 -3
- data/lib/active_support/inflector/inflections.rb +53 -92
- data/lib/active_support/inflector/methods.rb +173 -9
- data/lib/active_support/json/decoding.rb +3 -17
- data/lib/active_support/json/encoding.rb +11 -14
- data/lib/active_support/memoizable.rb +12 -1
- data/lib/active_support/message_encryptor.rb +52 -20
- data/lib/active_support/message_verifier.rb +15 -4
- data/lib/active_support/notifications.rb +87 -14
- data/lib/active_support/notifications/instrumenter.rb +1 -2
- data/lib/active_support/ordered_hash.rb +7 -3
- data/lib/active_support/tagged_logging.rb +63 -0
- data/lib/active_support/testing/assertions.rb +1 -1
- data/lib/active_support/testing/mochaing.rb +2 -2
- data/lib/active_support/testing/performance/ruby.rb +1 -1
- data/lib/active_support/testing/setup_and_teardown.rb +4 -12
- data/lib/active_support/time_with_zone.rb +6 -3
- data/lib/active_support/values/time_zone.rb +3 -7
- data/lib/active_support/version.rb +3 -3
- data/lib/active_support/xml_mini.rb +3 -3
- data/lib/active_support/xml_mini/jdom.rb +4 -10
- metadata +28 -21
- checksums.yaml +0 -7
- data/lib/active_support/cache/compressed_mem_cache_store.rb +0 -13
- data/lib/active_support/cache/synchronized_memory_store.rb +0 -11
- data/lib/active_support/core_ext/class/inheritable_attributes.rb +0 -178
- data/lib/active_support/core_ext/kernel/requires.rb +0 -28
- data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +0 -31
- 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
|
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
|
-
|
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?(
|
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
|
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://
|
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
|
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
|
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
|
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
|
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
|
-
|
175
|
-
|
176
|
-
# This double assignment is to prevent warnings in 1.9.3
|
177
|
-
#
|
178
|
-
#
|
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
|
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
|
-
#
|
226
|
-
|
227
|
-
#
|
228
|
-
|
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
|
-
|
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
|
-
|
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
|
385
|
+
undef_method runner_method if method_defined?(runner_method)
|
377
386
|
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
378
|
-
def
|
387
|
+
def #{runner_method}(key = nil, &blk)
|
379
388
|
if key
|
380
|
-
|
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
|
394
|
+
private :#{runner_method}
|
392
395
|
RUBY_EVAL
|
393
396
|
end
|
394
397
|
end
|
395
398
|
|
396
|
-
# This
|
397
|
-
#
|
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
|
401
|
-
|
402
|
-
|
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
|
-
|
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'
|
@@ -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.
|
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
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
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
|
187
|
-
|
188
|
-
|
189
|
-
|
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
|
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
|
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
|