diff options
Diffstat (limited to 'activesupport/lib/active_support/core_ext')
8 files changed, 112 insertions, 26 deletions
diff --git a/activesupport/lib/active_support/core_ext/date/calculations.rb b/activesupport/lib/active_support/core_ext/date/calculations.rb index c6eec9c486..a7551d9c64 100644 --- a/activesupport/lib/active_support/core_ext/date/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date/calculations.rb @@ -9,6 +9,29 @@ class Date include DateAndTime::Calculations class << self + attr_accessor :beginning_of_week_default + + # Returns the week start (e.g. :monday) for the current request, if this has been set (via Date.beginning_of_week=). + # If <tt>Date.beginning_of_week</tt> has not been set for the current request, returns the week start specified in <tt>config.beginning_of_week</tt>. + # If no config.beginning_of_week was specified, returns :monday. + def beginning_of_week + Thread.current[:beginning_of_week] || beginning_of_week_default || :monday + end + + # Sets <tt>Date.beginning_of_week</tt> to a week start (e.g. :monday) for current request/thread. + # + # This method accepts any of the following day symbols: + # :monday, :tuesday, :wednesday, :thursday, :friday, :saturday, :sunday + def beginning_of_week=(week_start) + Thread.current[:beginning_of_week] = find_beginning_of_week!(week_start) + end + + # Returns week start day symbol (e.g. :monday), or raises an ArgumentError for invalid day symbol. + def find_beginning_of_week!(week_start) + raise ArgumentError, "Invalid beginning of week: #{week_start}" unless ::Date::DAYS_INTO_WEEK.keys.include?(week_start) + week_start + end + # Returns a new Date representing the date 1 day ago (i.e. yesterday's date). def yesterday ::Date.current.yesterday diff --git a/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb b/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb index e703fca7a7..1f78b9eb5a 100644 --- a/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb @@ -109,10 +109,11 @@ module DateAndTime alias :at_beginning_of_year :beginning_of_year # Returns a new date/time representing the given day in the next week. - # Default is :monday. + # Week is assumed to start on +start_day+, default is + # +Date.beginning_of_week+ or +config.beginning_of_week+ when set. # DateTime objects have their time set to 0:00. - def next_week(day = :monday) - first_hour{ weeks_since(1).beginning_of_week.days_since(DAYS_INTO_WEEK[day]) } + def next_week(start_day = Date.beginning_of_week) + first_hour{ weeks_since(1).beginning_of_week.days_since(days_span(start_day)) } end # Short-hand for months_since(1). @@ -131,10 +132,11 @@ module DateAndTime end # Returns a new date/time representing the given day in the previous week. - # Default is :monday. + # Week is assumed to start on +start_day+, default is + # +Date.beginning_of_week+ or +config.beginning_of_week+ when set. # DateTime objects have their time set to 0:00. - def prev_week(day = :monday) - first_hour{ weeks_ago(1).beginning_of_week.days_since(DAYS_INTO_WEEK[day]) } + def prev_week(start_day = Date.beginning_of_week) + first_hour{ weeks_ago(1).beginning_of_week.days_since(days_span(start_day)) } end alias_method :last_week, :prev_week @@ -157,31 +159,44 @@ module DateAndTime alias_method :last_year, :prev_year # Returns the number of days to the start of the week on the given day. - # Default is :monday. - def days_to_week_start(start_day = :monday) + # Week is assumed to start on +start_day+, default is + # +Date.beginning_of_week+ or +config.beginning_of_week+ when set. + def days_to_week_start(start_day = Date.beginning_of_week) 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/time representing the start of this week on the given day. - # Default is :monday. - # DateTime objects have their time set to 0:00. - def beginning_of_week(start_day = :monday) + # Week is assumed to start on +start_day+, default is + # +Date.beginning_of_week+ or +config.beginning_of_week+ when set. + # +DateTime+ objects have their time set to 0:00. + def beginning_of_week(start_day = Date.beginning_of_week) result = days_ago(days_to_week_start(start_day)) acts_like?(:time) ? result.midnight : result end alias :at_beginning_of_week :beginning_of_week - alias :monday :beginning_of_week + + # Returns Monday of this week assuming that week starts on Monday. + # +DateTime+ objects have their time set to 0:00. + def monday + beginning_of_week(:monday) + end # Returns a new date/time representing the end of this week on the given day. - # Default is :monday (i.e end of Sunday). + # Week is assumed to start on +start_day+, default is + # +Date.beginning_of_week+ or +config.beginning_of_week+ when set. # DateTime objects have their time set to 23:59:59. - def end_of_week(start_day = :monday) + def end_of_week(start_day = Date.beginning_of_week) last_hour{ days_since(6 - days_to_week_start(start_day)) } end alias :at_end_of_week :end_of_week - alias :sunday :end_of_week + + # Returns Sunday of this week assuming that week starts on Monday. + # +DateTime+ objects have their time set to 23:59:59. + def sunday + end_of_week(:monday) + end # Returns a new date/time representing the end of the month. # DateTime objects will have a time set to 23:59:59. @@ -209,5 +224,9 @@ module DateAndTime result = yield acts_like?(:time) ? result.end_of_day : result end + + def days_span(day) + (DAYS_INTO_WEEK[day] - DAYS_INTO_WEEK[Date.beginning_of_week]) % 7 + end end end diff --git a/activesupport/lib/active_support/core_ext/hash/deep_merge.rb b/activesupport/lib/active_support/core_ext/hash/deep_merge.rb index 485f88cc06..83f0c87b04 100644 --- a/activesupport/lib/active_support/core_ext/hash/deep_merge.rb +++ b/activesupport/lib/active_support/core_ext/hash/deep_merge.rb @@ -6,15 +6,21 @@ class Hash # # h1.deep_merge(h2) #=> {:x => {:y => [7, 8, 9]}, :z => "xyz"} # h2.deep_merge(h1) #=> {:x => {:y => [4, 5, 6]}, :z => [7, 8, 9]} - def deep_merge(other_hash) - dup.deep_merge!(other_hash) + # h1.deep_merge(h2) { |key, old, new| Array.wrap(old) + Array.wrap(new) } + # #=> {:x => {:y => [4, 5, 6, 7, 8, 9]}, :z => [7, 8, 9, "xyz"]} + def deep_merge(other_hash, &block) + dup.deep_merge!(other_hash, &block) end # Same as +deep_merge+, but modifies +self+. - def deep_merge!(other_hash) + def deep_merge!(other_hash, &block) other_hash.each_pair do |k,v| tv = self[k] - self[k] = tv.is_a?(Hash) && v.is_a?(Hash) ? tv.deep_merge(v) : v + if tv.is_a?(Hash) && v.is_a?(Hash) + self[k] = tv.deep_merge(v, &block) + else + self[k] = block && tv ? block.call(k, tv, v) : v + end end self end diff --git a/activesupport/lib/active_support/core_ext/module/delegation.rb b/activesupport/lib/active_support/core_ext/module/delegation.rb index 55966ffd15..e608eeaf42 100644 --- a/activesupport/lib/active_support/core_ext/module/delegation.rb +++ b/activesupport/lib/active_support/core_ext/module/delegation.rb @@ -52,6 +52,18 @@ class Module # Foo.new.min # => 4 # Foo.new.max # => 11 # + # It's also possible to delegate a method to the class by using +:class+: + # + # class Foo + # def self.hello + # "world" + # end + # + # delegate :hello, to: :class + # end + # + # Foo.new.hello # => "world" + # # Delegates can optionally be prefixed using the <tt>:prefix</tt> option. If the value # is <tt>true</tt>, the delegate methods are prefixed with the name of the object being # delegated to. @@ -103,7 +115,7 @@ class Module def delegate(*methods) options = methods.pop unless options.is_a?(Hash) && to = options[:to] - raise ArgumentError, 'Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, :to => :greeter).' + raise ArgumentError, 'Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, to: :greeter).' end prefix, allow_nil = options.values_at(:prefix, :allow_nil) @@ -122,6 +134,9 @@ class Module file, line = caller.first.split(':', 2) line = line.to_i + to = to.to_s + to = 'self.class' if to == 'class' + methods.each do |method| # Attribute writer methods only accept one argument. Makes sure []= # methods still accept two arguments. diff --git a/activesupport/lib/active_support/core_ext/module/deprecation.rb b/activesupport/lib/active_support/core_ext/module/deprecation.rb index 4f629240fe..34ec6a3d8f 100644 --- a/activesupport/lib/active_support/core_ext/module/deprecation.rb +++ b/activesupport/lib/active_support/core_ext/module/deprecation.rb @@ -1,10 +1,24 @@ require 'active_support/deprecation/method_wrappers' class Module - # Declare that a method has been deprecated. # deprecate :foo - # deprecate bar: 'message' - # deprecate :foo, :bar, baz: 'warning!', qux: 'gone!' + # deprecate :bar => 'message' + # deprecate :foo, :bar, :baz => 'warning!', :qux => 'gone!' + # + # You can also use custom deprecator instance: + # + # deprecate :foo, :deprecator => MyLib::Deprecator.new + # deprecate :foo, :bar => "warning!", :deprecator => MyLib::Deprecator.new + # + # \Custom deprecators must respond to <tt>deprecation_warning(deprecated_method_name, message, caller_backtrace)</tt> + # method where you can implement your custom warning behavior. + # + # class MyLib::Deprecator + # def deprecation_warning(deprecated_method_name, message, caller_backtrace) + # message = "#{method_name} is deprecated and will be removed from MyLibrary | #{message}" + # Kernel.warn message + # end + # end def deprecate(*method_names) ActiveSupport::Deprecation.deprecate_methods(self, *method_names) 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 e7dc60a612..83cc8066e7 100644 --- a/activesupport/lib/active_support/core_ext/object/to_json.rb +++ b/activesupport/lib/active_support/core_ext/object/to_json.rb @@ -17,3 +17,11 @@ end end end end + +module Process + class Status + def as_json(options = nil) + { :exitstatus => exitstatus, :pid => pid } + end + end +end diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index 7d9e5bbe7d..5f85cedcf5 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -3,7 +3,7 @@ require 'active_support/core_ext/kernel/singleton_class' class ERB module Util - HTML_ESCAPE = { '&' => '&', '>' => '>', '<' => '<', '"' => '"', "'" => ''' } + HTML_ESCAPE = { '&' => '&', '>' => '>', '<' => '<', '"' => '"', "'" => ''' } JSON_ESCAPE = { '&' => '\u0026', '>' => '\u003E', '<' => '\u003C' } HTML_ESCAPE_ONCE_REGEXP = /["><']|&(?!([a-zA-Z]+|(#\d+));)/ JSON_ESCAPE_REGEXP = /[&"><]/ diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index 359f6fa716..e3665cd896 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -172,8 +172,9 @@ class Time beginning_of_day..end_of_day end - # Returns a Range representing the whole week of the current time. Week starts on start_day (default is :monday, i.e. end of Sunday). - def all_week(start_day = :monday) + # Returns a Range representing the whole week of the current time. + # Week starts on start_day, default is <tt>Date.week_start</tt> or <tt>config.week_start</tt> when set. + def all_week(start_day = Date.beginning_of_week) beginning_of_week(start_day)..end_of_week(start_day) end |