activesupport-refinements 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +32 -0
- data/Rakefile +1 -0
- data/activesupport-refinements.gemspec +21 -0
- data/lib/active_support/refinements/core_ext/array.rb +7 -0
- data/lib/active_support/refinements/core_ext/array/access.rb +56 -0
- data/lib/active_support/refinements/core_ext/array/conversions.rb +224 -0
- data/lib/active_support/refinements/core_ext/array/extract_options.rb +31 -0
- data/lib/active_support/refinements/core_ext/array/grouping.rb +101 -0
- data/lib/active_support/refinements/core_ext/array/prepend_and_append.rb +9 -0
- data/lib/active_support/refinements/core_ext/array/uniq_by.rb +21 -0
- data/lib/active_support/refinements/core_ext/array/wrap.rb +48 -0
- data/lib/active_support/refinements/core_ext/benchmark.rb +7 -0
- data/lib/active_support/refinements/core_ext/big_decimal.rb +1 -0
- data/lib/active_support/refinements/core_ext/big_decimal/conversions.rb +32 -0
- data/lib/active_support/refinements/core_ext/class.rb +4 -0
- data/lib/active_support/refinements/core_ext/class/attribute.rb +119 -0
- data/lib/active_support/refinements/core_ext/class/attribute_accessors.rb +172 -0
- data/lib/active_support/refinements/core_ext/class/delegating_attributes.rb +42 -0
- data/lib/active_support/refinements/core_ext/class/subclasses.rb +44 -0
- data/lib/active_support/refinements/core_ext/date.rb +5 -0
- data/lib/active_support/refinements/core_ext/date/acts_like.rb +10 -0
- data/lib/active_support/refinements/core_ext/date/calculations.rb +123 -0
- data/lib/active_support/refinements/core_ext/date/conversions.rb +86 -0
- data/lib/active_support/refinements/core_ext/date/zones.rb +17 -0
- data/lib/active_support/refinements/core_ext/date_and_time/calculations.rb +232 -0
- data/lib/active_support/refinements/core_ext/date_time.rb +4 -0
- data/lib/active_support/refinements/core_ext/date_time/acts_like.rb +15 -0
- data/lib/active_support/refinements/core_ext/date_time/calculations.rb +143 -0
- data/lib/active_support/refinements/core_ext/date_time/conversions.rb +93 -0
- data/lib/active_support/refinements/core_ext/date_time/zones.rb +26 -0
- data/lib/active_support/refinements/core_ext/enumerable.rb +82 -0
- data/lib/active_support/refinements/core_ext/exception.rb +5 -0
- data/lib/active_support/refinements/core_ext/file.rb +1 -0
- data/lib/active_support/refinements/core_ext/file/atomic.rb +60 -0
- data/lib/active_support/refinements/core_ext/hash.rb +8 -0
- data/lib/active_support/refinements/core_ext/hash/conversions.rb +161 -0
- data/lib/active_support/refinements/core_ext/hash/deep_merge.rb +29 -0
- data/lib/active_support/refinements/core_ext/hash/diff.rb +15 -0
- data/lib/active_support/refinements/core_ext/hash/except.rb +17 -0
- data/lib/active_support/refinements/core_ext/hash/indifferent_access.rb +24 -0
- data/lib/active_support/refinements/core_ext/hash/keys.rb +140 -0
- data/lib/active_support/refinements/core_ext/hash/reverse_merge.rb +24 -0
- data/lib/active_support/refinements/core_ext/hash/slice.rb +42 -0
- data/lib/active_support/refinements/core_ext/integer.rb +3 -0
- data/lib/active_support/refinements/core_ext/integer/inflections.rb +31 -0
- data/lib/active_support/refinements/core_ext/integer/multiple.rb +12 -0
- data/lib/active_support/refinements/core_ext/integer/time.rb +43 -0
- data/lib/active_support/refinements/core_ext/kernel.rb +4 -0
- data/lib/active_support/refinements/core_ext/kernel/agnostics.rb +13 -0
- data/lib/active_support/refinements/core_ext/kernel/debugger.rb +12 -0
- data/lib/active_support/refinements/core_ext/kernel/reporting.rb +97 -0
- data/lib/active_support/refinements/core_ext/kernel/singleton_class.rb +8 -0
- data/lib/active_support/refinements/core_ext/load_error.rb +27 -0
- data/lib/active_support/refinements/core_ext/logger.rb +86 -0
- data/lib/active_support/refinements/core_ext/module.rb +10 -0
- data/lib/active_support/refinements/core_ext/module/aliasing.rb +69 -0
- data/lib/active_support/refinements/core_ext/module/anonymous.rb +21 -0
- data/lib/active_support/refinements/core_ext/module/attr_internal.rb +40 -0
- data/lib/active_support/refinements/core_ext/module/attribute_accessors.rb +68 -0
- data/lib/active_support/refinements/core_ext/module/delegation.rb +172 -0
- data/lib/active_support/refinements/core_ext/module/deprecation.rb +27 -0
- data/lib/active_support/refinements/core_ext/module/introspection.rb +80 -0
- data/lib/active_support/refinements/core_ext/module/qualified_const.rb +54 -0
- data/lib/active_support/refinements/core_ext/module/reachable.rb +10 -0
- data/lib/active_support/refinements/core_ext/module/remove_method.rb +14 -0
- data/lib/active_support/refinements/core_ext/name_error.rb +20 -0
- data/lib/active_support/refinements/core_ext/numeric.rb +3 -0
- data/lib/active_support/refinements/core_ext/numeric/bytes.rb +46 -0
- data/lib/active_support/refinements/core_ext/numeric/conversions.rb +137 -0
- data/lib/active_support/refinements/core_ext/numeric/time.rb +81 -0
- data/lib/active_support/refinements/core_ext/object.rb +14 -0
- data/lib/active_support/refinements/core_ext/object/acts_like.rb +12 -0
- data/lib/active_support/refinements/core_ext/object/blank.rb +107 -0
- data/lib/active_support/refinements/core_ext/object/conversions.rb +4 -0
- data/lib/active_support/refinements/core_ext/object/deep_dup.rb +48 -0
- data/lib/active_support/refinements/core_ext/object/duplicable.rb +92 -0
- data/lib/active_support/refinements/core_ext/object/inclusion.rb +27 -0
- data/lib/active_support/refinements/core_ext/object/instance_variables.rb +30 -0
- data/lib/active_support/refinements/core_ext/object/to_json.rb +27 -0
- data/lib/active_support/refinements/core_ext/object/to_param.rb +60 -0
- data/lib/active_support/refinements/core_ext/object/to_query.rb +29 -0
- data/lib/active_support/refinements/core_ext/object/try.rb +72 -0
- data/lib/active_support/refinements/core_ext/object/with_options.rb +44 -0
- data/lib/active_support/refinements/core_ext/proc.rb +19 -0
- data/lib/active_support/refinements/core_ext/range.rb +3 -0
- data/lib/active_support/refinements/core_ext/range/conversions.rb +21 -0
- data/lib/active_support/refinements/core_ext/range/include_range.rb +23 -0
- data/lib/active_support/refinements/core_ext/range/overlaps.rb +10 -0
- data/lib/active_support/refinements/core_ext/regexp.rb +7 -0
- data/lib/active_support/refinements/core_ext/string.rb +13 -0
- data/lib/active_support/refinements/core_ext/string/access.rb +106 -0
- data/lib/active_support/refinements/core_ext/string/behavior.rb +8 -0
- data/lib/active_support/refinements/core_ext/string/conversions.rb +60 -0
- data/lib/active_support/refinements/core_ext/string/encoding.rb +10 -0
- data/lib/active_support/refinements/core_ext/string/exclude.rb +13 -0
- data/lib/active_support/refinements/core_ext/string/filters.rb +54 -0
- data/lib/active_support/refinements/core_ext/string/indent.rb +45 -0
- data/lib/active_support/refinements/core_ext/string/inflections.rb +214 -0
- data/lib/active_support/refinements/core_ext/string/inquiry.rb +15 -0
- data/lib/active_support/refinements/core_ext/string/multibyte.rb +58 -0
- data/lib/active_support/refinements/core_ext/string/output_safety.rb +194 -0
- data/lib/active_support/refinements/core_ext/string/starts_ends_with.rb +6 -0
- data/lib/active_support/refinements/core_ext/string/strip.rb +28 -0
- data/lib/active_support/refinements/core_ext/string/xchar.rb +18 -0
- data/lib/active_support/refinements/core_ext/time.rb +5 -0
- data/lib/active_support/refinements/core_ext/time/acts_like.rb +10 -0
- data/lib/active_support/refinements/core_ext/time/calculations.rb +251 -0
- data/lib/active_support/refinements/core_ext/time/conversions.rb +65 -0
- data/lib/active_support/refinements/core_ext/time/marshal.rb +30 -0
- data/lib/active_support/refinements/core_ext/time/zones.rb +98 -0
- data/lib/active_support/refinements/core_ext/uri.rb +28 -0
- data/lib/activesupport-refinements.rb +9 -0
- data/lib/activesupport-refinements/version.rb +5 -0
- data/refine_core_ext.rb +45 -0
- data/spec/hwia_spec.rb +15 -0
- data/spec/try_spec.rb +18 -0
- metadata +182 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module DateTimeExt; end; module DateTimeExt::ActsLike
|
|
2
|
+
require 'active_support/refinements/core_ext/object/acts_like'
|
|
3
|
+
|
|
4
|
+
refine DateTime do
|
|
5
|
+
# Duck-types as a Date-like class. See Object#acts_like?.
|
|
6
|
+
def acts_like_date?
|
|
7
|
+
true
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Duck-types as a Time-like class. See Object#acts_like?.
|
|
11
|
+
def acts_like_time?
|
|
12
|
+
true
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
module DateTimeExt; end; module DateTimeExt::Calculations
|
|
2
|
+
require 'active_support/deprecation'
|
|
3
|
+
|
|
4
|
+
refine DateTime do
|
|
5
|
+
class << self
|
|
6
|
+
# *DEPRECATED*: Use +DateTime.civil_from_format+ directly.
|
|
7
|
+
def local_offset
|
|
8
|
+
ActiveSupport::Deprecation.warn 'DateTime.local_offset is deprecated. Use DateTime.civil_from_format directly.', caller
|
|
9
|
+
|
|
10
|
+
::Time.local(2012).utc_offset.to_r / 86400
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Returns <tt>Time.zone.now.to_datetime</tt> when <tt>Time.zone</tt> or
|
|
14
|
+
# <tt>config.time_zone</tt> are set, otherwise returns
|
|
15
|
+
# <tt>Time.now.to_datetime</tt>.
|
|
16
|
+
def current
|
|
17
|
+
::Time.zone ? ::Time.zone.now.to_datetime : ::Time.now.to_datetime
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Tells whether the DateTime object's datetime lies in the past.
|
|
22
|
+
def past?
|
|
23
|
+
self < ::DateTime.current
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Tells whether the DateTime object's datetime lies in the future.
|
|
27
|
+
def future?
|
|
28
|
+
self > ::DateTime.current
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Seconds since midnight: DateTime.now.seconds_since_midnight.
|
|
32
|
+
def seconds_since_midnight
|
|
33
|
+
sec + (min * 60) + (hour * 3600)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Returns a new DateTime where one or more of the elements have been changed
|
|
37
|
+
# according to the +options+ parameter. The time options (<tt>:hour</tt>,
|
|
38
|
+
# <tt>:minute</tt>, <tt>:sec</tt>) reset cascadingly, so if only the hour is
|
|
39
|
+
# passed, then minute and sec is set to 0. If the hour and minute is passed,
|
|
40
|
+
# then sec is set to 0. The +options+ parameter takes a hash with any of these
|
|
41
|
+
# keys: <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>, <tt>:hour</tt>,
|
|
42
|
+
# <tt>:min</tt>, <tt>:sec</tt>, <tt>:offset</tt>, <tt>:start</tt>.
|
|
43
|
+
#
|
|
44
|
+
# DateTime.new(2012, 8, 29, 22, 35, 0).change(day: 1) # => DateTime.new(2012, 8, 1, 22, 35, 0)
|
|
45
|
+
# DateTime.new(2012, 8, 29, 22, 35, 0).change(year: 1981, day: 1) # => DateTime.new(1981, 8, 1, 22, 35, 0)
|
|
46
|
+
# DateTime.new(2012, 8, 29, 22, 35, 0).change(year: 1981, hour: 0) # => DateTime.new(1981, 8, 29, 0, 0, 0)
|
|
47
|
+
def change(options)
|
|
48
|
+
::DateTime.civil(
|
|
49
|
+
options.fetch(:year, year),
|
|
50
|
+
options.fetch(:month, month),
|
|
51
|
+
options.fetch(:day, day),
|
|
52
|
+
options.fetch(:hour, hour),
|
|
53
|
+
options.fetch(:min, options[:hour] ? 0 : min),
|
|
54
|
+
options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec),
|
|
55
|
+
options.fetch(:offset, offset),
|
|
56
|
+
options.fetch(:start, start)
|
|
57
|
+
)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Uses Date to provide precise Time calculations for years, months, and days.
|
|
61
|
+
# The +options+ parameter takes a hash with any of these keys: <tt>:years</tt>,
|
|
62
|
+
# <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>, <tt>:hours</tt>,
|
|
63
|
+
# <tt>:minutes</tt>, <tt>:seconds</tt>.
|
|
64
|
+
def advance(options)
|
|
65
|
+
d = to_date.advance(options)
|
|
66
|
+
datetime_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day)
|
|
67
|
+
seconds_to_advance = \
|
|
68
|
+
options.fetch(:seconds, 0) +
|
|
69
|
+
options.fetch(:minutes, 0) * 60 +
|
|
70
|
+
options.fetch(:hours, 0) * 3600
|
|
71
|
+
|
|
72
|
+
if seconds_to_advance.zero?
|
|
73
|
+
datetime_advanced_by_date
|
|
74
|
+
else
|
|
75
|
+
datetime_advanced_by_date.since seconds_to_advance
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Returns a new DateTime representing the time a number of seconds ago.
|
|
80
|
+
# Do not use this method in combination with x.months, use months_ago instead!
|
|
81
|
+
def ago(seconds)
|
|
82
|
+
since(-seconds)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Returns a new DateTime representing the time a number of seconds since the
|
|
86
|
+
# instance time. Do not use this method in combination with x.months, use
|
|
87
|
+
# months_since instead!
|
|
88
|
+
def since(seconds)
|
|
89
|
+
self + Rational(seconds.round, 86400)
|
|
90
|
+
end
|
|
91
|
+
# alias :in :since
|
|
92
|
+
|
|
93
|
+
# Returns a new DateTime representing the start of the day (0:00).
|
|
94
|
+
def beginning_of_day
|
|
95
|
+
change(:hour => 0)
|
|
96
|
+
end
|
|
97
|
+
# alias :midnight :beginning_of_day
|
|
98
|
+
# alias :at_midnight :beginning_of_day
|
|
99
|
+
# alias :at_beginning_of_day :beginning_of_day
|
|
100
|
+
|
|
101
|
+
# Returns a new DateTime representing the end of the day (23:59:59).
|
|
102
|
+
def end_of_day
|
|
103
|
+
change(:hour => 23, :min => 59, :sec => 59)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Returns a new DateTime representing the start of the hour (hh:00:00).
|
|
107
|
+
def beginning_of_hour
|
|
108
|
+
change(:min => 0)
|
|
109
|
+
end
|
|
110
|
+
# alias :at_beginning_of_hour :beginning_of_hour
|
|
111
|
+
|
|
112
|
+
# Returns a new DateTime representing the end of the hour (hh:59:59).
|
|
113
|
+
def end_of_hour
|
|
114
|
+
change(:min => 59, :sec => 59)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Adjusts DateTime to UTC by adding its offset value; offset is set to 0.
|
|
118
|
+
#
|
|
119
|
+
# DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)) # => Mon, 21 Feb 2005 10:11:12 -0600
|
|
120
|
+
# DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)).utc # => Mon, 21 Feb 2005 16:11:12 +0000
|
|
121
|
+
def utc
|
|
122
|
+
new_offset(0)
|
|
123
|
+
end
|
|
124
|
+
# alias_method :getutc, :utc
|
|
125
|
+
|
|
126
|
+
# Returns +true+ if <tt>offset == 0</tt>.
|
|
127
|
+
def utc?
|
|
128
|
+
offset == 0
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Returns the offset value in seconds.
|
|
132
|
+
def utc_offset
|
|
133
|
+
(offset * 86400).to_i
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Layers additional behavior on DateTime#<=> so that Time and
|
|
137
|
+
# ActiveSupport::TimeWithZone instances can be compared with a DateTime.
|
|
138
|
+
def <=>(other)
|
|
139
|
+
super other.to_datetime
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
end
|
|
143
|
+
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
module DateTimeExt; end; module DateTimeExt::Conversions
|
|
2
|
+
require 'active_support/inflector/methods'
|
|
3
|
+
require 'active_support/refinements/core_ext/time/conversions'
|
|
4
|
+
require 'active_support/refinements/core_ext/date_time/calculations'
|
|
5
|
+
require 'active_support/values/time_zone'
|
|
6
|
+
|
|
7
|
+
refine DateTime do
|
|
8
|
+
# Convert to a formatted string. See Time::DATE_FORMATS for predefined formats.
|
|
9
|
+
#
|
|
10
|
+
# This method is aliased to <tt>to_s</tt>.
|
|
11
|
+
#
|
|
12
|
+
# === Examples
|
|
13
|
+
# datetime = DateTime.civil(2007, 12, 4, 0, 0, 0, 0) # => Tue, 04 Dec 2007 00:00:00 +0000
|
|
14
|
+
#
|
|
15
|
+
# datetime.to_formatted_s(:db) # => "2007-12-04 00:00:00"
|
|
16
|
+
# datetime.to_s(:db) # => "2007-12-04 00:00:00"
|
|
17
|
+
# datetime.to_s(:number) # => "20071204000000"
|
|
18
|
+
# datetime.to_formatted_s(:short) # => "04 Dec 00:00"
|
|
19
|
+
# datetime.to_formatted_s(:long) # => "December 04, 2007 00:00"
|
|
20
|
+
# datetime.to_formatted_s(:long_ordinal) # => "December 4th, 2007 00:00"
|
|
21
|
+
# datetime.to_formatted_s(:rfc822) # => "Tue, 04 Dec 2007 00:00:00 +0000"
|
|
22
|
+
#
|
|
23
|
+
# == Adding your own datetime formats to to_formatted_s
|
|
24
|
+
# DateTime formats are shared with Time. You can add your own to the
|
|
25
|
+
# Time::DATE_FORMATS hash. Use the format name as the hash key and
|
|
26
|
+
# either a strftime string or Proc instance that takes a time or
|
|
27
|
+
# datetime argument as the value.
|
|
28
|
+
#
|
|
29
|
+
# # config/initializers/time_formats.rb
|
|
30
|
+
# Time::DATE_FORMATS[:month_and_year] = '%B %Y'
|
|
31
|
+
# Time::DATE_FORMATS[:short_ordinal] = lambda { |time| time.strftime("%B #{time.day.ordinalize}") }
|
|
32
|
+
def to_formatted_s(format = :default)
|
|
33
|
+
if formatter = ::Time::DATE_FORMATS[format]
|
|
34
|
+
formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
|
|
35
|
+
else
|
|
36
|
+
to_default_s
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
# alias_method :to_default_s, :to_s if instance_methods(false).include?(:to_s)
|
|
40
|
+
# alias_method :to_s, :to_formatted_s
|
|
41
|
+
|
|
42
|
+
#
|
|
43
|
+
# datetime = DateTime.civil(2000, 1, 1, 0, 0, 0, Rational(-6, 24))
|
|
44
|
+
# datetime.formatted_offset # => "-06:00"
|
|
45
|
+
# datetime.formatted_offset(false) # => "-0600"
|
|
46
|
+
def formatted_offset(colon = true, alternate_utc_string = nil)
|
|
47
|
+
utc? && alternate_utc_string || ActiveSupport::TimeZone.seconds_to_utc_offset(utc_offset, colon)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005 14:30:00 +0000".
|
|
51
|
+
def readable_inspect
|
|
52
|
+
to_s(:rfc822)
|
|
53
|
+
end
|
|
54
|
+
# alias_method :default_inspect, :inspect
|
|
55
|
+
# alias_method :inspect, :readable_inspect
|
|
56
|
+
|
|
57
|
+
# Returns DateTime with local offset for given year if format is local else
|
|
58
|
+
# offset is zero.
|
|
59
|
+
#
|
|
60
|
+
# DateTime.civil_from_format :local, 2012
|
|
61
|
+
# # => Sun, 01 Jan 2012 00:00:00 +0300
|
|
62
|
+
# DateTime.civil_from_format :local, 2012, 12, 17
|
|
63
|
+
# # => Mon, 17 Dec 2012 00:00:00 +0000
|
|
64
|
+
def self.civil_from_format(utc_or_local, year, month=1, day=1, hour=0, min=0, sec=0)
|
|
65
|
+
if utc_or_local.to_sym == :local
|
|
66
|
+
offset = ::Time.local(year, month, day).utc_offset.to_r / 86400
|
|
67
|
+
else
|
|
68
|
+
offset = 0
|
|
69
|
+
end
|
|
70
|
+
civil(year, month, day, hour, min, sec, offset)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Converts +self+ to a floating-point number of seconds since the Unix epoch.
|
|
74
|
+
def to_f
|
|
75
|
+
seconds_since_unix_epoch.to_f
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Converts +self+ to an integer number of seconds since the Unix epoch.
|
|
79
|
+
def to_i
|
|
80
|
+
seconds_since_unix_epoch.to_i
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
private
|
|
84
|
+
|
|
85
|
+
def offset_in_seconds
|
|
86
|
+
(offset * 86400).to_i
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def seconds_since_unix_epoch
|
|
90
|
+
(jd - 2440588) * 86400 - offset_in_seconds + seconds_since_midnight
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module DateTimeExt; end; module DateTimeExt::Zones
|
|
2
|
+
require 'active_support/refinements/core_ext/time/zones'
|
|
3
|
+
|
|
4
|
+
refine DateTime do
|
|
5
|
+
# Returns the simultaneous time in <tt>Time.zone</tt>.
|
|
6
|
+
#
|
|
7
|
+
# Time.zone = 'Hawaii' # => 'Hawaii'
|
|
8
|
+
# DateTime.new(2000).in_time_zone # => Fri, 31 Dec 1999 14:00:00 HST -10:00
|
|
9
|
+
#
|
|
10
|
+
# This method is similar to Time#localtime, except that it uses <tt>Time.zone</tt>
|
|
11
|
+
# as the local zone instead of the operating system's time zone.
|
|
12
|
+
#
|
|
13
|
+
# You can also pass in a TimeZone instance or string that identifies a TimeZone
|
|
14
|
+
# as an argument, and the conversion will be based on that zone instead of
|
|
15
|
+
# <tt>Time.zone</tt>.
|
|
16
|
+
#
|
|
17
|
+
# DateTime.new(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00
|
|
18
|
+
def in_time_zone(zone = ::Time.zone)
|
|
19
|
+
if zone
|
|
20
|
+
ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.find_zone!(zone))
|
|
21
|
+
else
|
|
22
|
+
self
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
module EnumerableExt
|
|
2
|
+
refine Enumerable do
|
|
3
|
+
# Calculates a sum from the elements.
|
|
4
|
+
#
|
|
5
|
+
# payments.sum { |p| p.price * p.tax_rate }
|
|
6
|
+
# payments.sum(&:price)
|
|
7
|
+
#
|
|
8
|
+
# The latter is a shortcut for:
|
|
9
|
+
#
|
|
10
|
+
# payments.inject(0) { |sum, p| sum + p.price }
|
|
11
|
+
#
|
|
12
|
+
# It can also calculate the sum without the use of a block.
|
|
13
|
+
#
|
|
14
|
+
# [5, 15, 10].sum # => 30
|
|
15
|
+
# ['foo', 'bar'].sum # => "foobar"
|
|
16
|
+
# [[1, 2], [3, 1, 5]].sum => [1, 2, 3, 1, 5]
|
|
17
|
+
#
|
|
18
|
+
# The default sum of an empty list is zero. You can override this default:
|
|
19
|
+
#
|
|
20
|
+
# [].sum(Payment.new(0)) { |i| i.amount } # => Payment.new(0)
|
|
21
|
+
def sum(identity = 0, &block)
|
|
22
|
+
if block_given?
|
|
23
|
+
map(&block).sum(identity)
|
|
24
|
+
else
|
|
25
|
+
inject { |sum, element| sum + element } || identity
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Convert an enumerable to a hash.
|
|
30
|
+
#
|
|
31
|
+
# people.index_by(&:login)
|
|
32
|
+
# => { "nextangle" => <Person ...>, "chade-" => <Person ...>, ...}
|
|
33
|
+
# people.index_by { |person| "#{person.first_name} #{person.last_name}" }
|
|
34
|
+
# => { "Chade- Fowlersburg-e" => <Person ...>, "David Heinemeier Hansson" => <Person ...>, ...}
|
|
35
|
+
def index_by
|
|
36
|
+
if block_given?
|
|
37
|
+
Hash[map { |elem| [yield(elem), elem] }]
|
|
38
|
+
else
|
|
39
|
+
to_enum :index_by
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Returns +true+ if the enumerable has more than 1 element. Functionally
|
|
44
|
+
# equivalent to <tt>enum.to_a.size > 1</tt>. Can be called with a block too,
|
|
45
|
+
# much like any?, so <tt>people.many? { |p| p.age > 26 }</tt> returns +true+
|
|
46
|
+
# if more than one person is over 26.
|
|
47
|
+
def many?
|
|
48
|
+
cnt = 0
|
|
49
|
+
if block_given?
|
|
50
|
+
any? do |element|
|
|
51
|
+
cnt += 1 if yield element
|
|
52
|
+
cnt > 1
|
|
53
|
+
end
|
|
54
|
+
else
|
|
55
|
+
any? { (cnt += 1) > 1 }
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# The negative of the <tt>Enumerable#include?</tt>. Returns +true+ if the
|
|
60
|
+
# collection does not include the object.
|
|
61
|
+
def exclude?(object)
|
|
62
|
+
!include?(object)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
refine Range do
|
|
67
|
+
# Optimize range sum to use arithmetic progression if a block is not given and
|
|
68
|
+
# we have a range of numeric values.
|
|
69
|
+
def sum(identity = 0)
|
|
70
|
+
if block_given? || !(first.is_a?(Integer) && last.is_a?(Integer))
|
|
71
|
+
super
|
|
72
|
+
else
|
|
73
|
+
actual_last = exclude_end? ? (last - 1) : last
|
|
74
|
+
if actual_last >= first
|
|
75
|
+
(actual_last - first + 1) * (actual_last + first) / 2
|
|
76
|
+
else
|
|
77
|
+
identity
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'active_support/refinements/core_ext/file/atomic'
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module FileExt; end; module FileExt::Atomic
|
|
2
|
+
require 'fileutils'
|
|
3
|
+
|
|
4
|
+
refine File do
|
|
5
|
+
# Write to a file atomically. Useful for situations where you don't
|
|
6
|
+
# want other processes or threads to see half-written files.
|
|
7
|
+
#
|
|
8
|
+
# File.atomic_write('important.file') do |file|
|
|
9
|
+
# file.write('hello')
|
|
10
|
+
# end
|
|
11
|
+
#
|
|
12
|
+
# If your temp directory is not on the same filesystem as the file you're
|
|
13
|
+
# trying to write, you can provide a different temporary directory.
|
|
14
|
+
#
|
|
15
|
+
# File.atomic_write('/data/something.important', '/data/tmp') do |file|
|
|
16
|
+
# file.write('hello')
|
|
17
|
+
# end
|
|
18
|
+
def self.atomic_write(file_name, temp_dir = Dir.tmpdir)
|
|
19
|
+
require 'tempfile' unless defined?(Tempfile)
|
|
20
|
+
require 'fileutils' unless defined?(FileUtils)
|
|
21
|
+
|
|
22
|
+
temp_file = Tempfile.new(basename(file_name), temp_dir)
|
|
23
|
+
temp_file.binmode
|
|
24
|
+
yield temp_file
|
|
25
|
+
temp_file.close
|
|
26
|
+
|
|
27
|
+
if File.exists?(file_name)
|
|
28
|
+
# Get original file permissions
|
|
29
|
+
old_stat = stat(file_name)
|
|
30
|
+
else
|
|
31
|
+
# If not possible, probe which are the default permissions in the
|
|
32
|
+
# destination directory.
|
|
33
|
+
old_stat = probe_stat_in(dirname(file_name))
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Overwrite original file with temp file
|
|
37
|
+
FileUtils.mv(temp_file.path, file_name)
|
|
38
|
+
|
|
39
|
+
# Set correct permissions on new file
|
|
40
|
+
chown(old_stat.uid, old_stat.gid, file_name)
|
|
41
|
+
chmod(old_stat.mode, file_name)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Private utility method.
|
|
45
|
+
def self.probe_stat_in(dir) #:nodoc:
|
|
46
|
+
basename = [
|
|
47
|
+
'.permissions_check',
|
|
48
|
+
Thread.current.object_id,
|
|
49
|
+
Process.pid,
|
|
50
|
+
rand(1000000)
|
|
51
|
+
].join('.')
|
|
52
|
+
|
|
53
|
+
file_name = join(dir, basename)
|
|
54
|
+
FileUtils.touch(file_name)
|
|
55
|
+
stat(file_name)
|
|
56
|
+
ensure
|
|
57
|
+
FileUtils.rm_f(file_name) if file_name
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
require 'active_support/refinements/core_ext/hash/conversions'
|
|
2
|
+
require 'active_support/refinements/core_ext/hash/deep_merge'
|
|
3
|
+
require 'active_support/refinements/core_ext/hash/diff'
|
|
4
|
+
require 'active_support/refinements/core_ext/hash/except'
|
|
5
|
+
require 'active_support/refinements/core_ext/hash/indifferent_access'
|
|
6
|
+
require 'active_support/refinements/core_ext/hash/keys'
|
|
7
|
+
require 'active_support/refinements/core_ext/hash/reverse_merge'
|
|
8
|
+
require 'active_support/refinements/core_ext/hash/slice'
|