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.
Files changed (120) hide show
  1. data/.gitignore +17 -0
  2. data/Gemfile +6 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +32 -0
  5. data/Rakefile +1 -0
  6. data/activesupport-refinements.gemspec +21 -0
  7. data/lib/active_support/refinements/core_ext/array.rb +7 -0
  8. data/lib/active_support/refinements/core_ext/array/access.rb +56 -0
  9. data/lib/active_support/refinements/core_ext/array/conversions.rb +224 -0
  10. data/lib/active_support/refinements/core_ext/array/extract_options.rb +31 -0
  11. data/lib/active_support/refinements/core_ext/array/grouping.rb +101 -0
  12. data/lib/active_support/refinements/core_ext/array/prepend_and_append.rb +9 -0
  13. data/lib/active_support/refinements/core_ext/array/uniq_by.rb +21 -0
  14. data/lib/active_support/refinements/core_ext/array/wrap.rb +48 -0
  15. data/lib/active_support/refinements/core_ext/benchmark.rb +7 -0
  16. data/lib/active_support/refinements/core_ext/big_decimal.rb +1 -0
  17. data/lib/active_support/refinements/core_ext/big_decimal/conversions.rb +32 -0
  18. data/lib/active_support/refinements/core_ext/class.rb +4 -0
  19. data/lib/active_support/refinements/core_ext/class/attribute.rb +119 -0
  20. data/lib/active_support/refinements/core_ext/class/attribute_accessors.rb +172 -0
  21. data/lib/active_support/refinements/core_ext/class/delegating_attributes.rb +42 -0
  22. data/lib/active_support/refinements/core_ext/class/subclasses.rb +44 -0
  23. data/lib/active_support/refinements/core_ext/date.rb +5 -0
  24. data/lib/active_support/refinements/core_ext/date/acts_like.rb +10 -0
  25. data/lib/active_support/refinements/core_ext/date/calculations.rb +123 -0
  26. data/lib/active_support/refinements/core_ext/date/conversions.rb +86 -0
  27. data/lib/active_support/refinements/core_ext/date/zones.rb +17 -0
  28. data/lib/active_support/refinements/core_ext/date_and_time/calculations.rb +232 -0
  29. data/lib/active_support/refinements/core_ext/date_time.rb +4 -0
  30. data/lib/active_support/refinements/core_ext/date_time/acts_like.rb +15 -0
  31. data/lib/active_support/refinements/core_ext/date_time/calculations.rb +143 -0
  32. data/lib/active_support/refinements/core_ext/date_time/conversions.rb +93 -0
  33. data/lib/active_support/refinements/core_ext/date_time/zones.rb +26 -0
  34. data/lib/active_support/refinements/core_ext/enumerable.rb +82 -0
  35. data/lib/active_support/refinements/core_ext/exception.rb +5 -0
  36. data/lib/active_support/refinements/core_ext/file.rb +1 -0
  37. data/lib/active_support/refinements/core_ext/file/atomic.rb +60 -0
  38. data/lib/active_support/refinements/core_ext/hash.rb +8 -0
  39. data/lib/active_support/refinements/core_ext/hash/conversions.rb +161 -0
  40. data/lib/active_support/refinements/core_ext/hash/deep_merge.rb +29 -0
  41. data/lib/active_support/refinements/core_ext/hash/diff.rb +15 -0
  42. data/lib/active_support/refinements/core_ext/hash/except.rb +17 -0
  43. data/lib/active_support/refinements/core_ext/hash/indifferent_access.rb +24 -0
  44. data/lib/active_support/refinements/core_ext/hash/keys.rb +140 -0
  45. data/lib/active_support/refinements/core_ext/hash/reverse_merge.rb +24 -0
  46. data/lib/active_support/refinements/core_ext/hash/slice.rb +42 -0
  47. data/lib/active_support/refinements/core_ext/integer.rb +3 -0
  48. data/lib/active_support/refinements/core_ext/integer/inflections.rb +31 -0
  49. data/lib/active_support/refinements/core_ext/integer/multiple.rb +12 -0
  50. data/lib/active_support/refinements/core_ext/integer/time.rb +43 -0
  51. data/lib/active_support/refinements/core_ext/kernel.rb +4 -0
  52. data/lib/active_support/refinements/core_ext/kernel/agnostics.rb +13 -0
  53. data/lib/active_support/refinements/core_ext/kernel/debugger.rb +12 -0
  54. data/lib/active_support/refinements/core_ext/kernel/reporting.rb +97 -0
  55. data/lib/active_support/refinements/core_ext/kernel/singleton_class.rb +8 -0
  56. data/lib/active_support/refinements/core_ext/load_error.rb +27 -0
  57. data/lib/active_support/refinements/core_ext/logger.rb +86 -0
  58. data/lib/active_support/refinements/core_ext/module.rb +10 -0
  59. data/lib/active_support/refinements/core_ext/module/aliasing.rb +69 -0
  60. data/lib/active_support/refinements/core_ext/module/anonymous.rb +21 -0
  61. data/lib/active_support/refinements/core_ext/module/attr_internal.rb +40 -0
  62. data/lib/active_support/refinements/core_ext/module/attribute_accessors.rb +68 -0
  63. data/lib/active_support/refinements/core_ext/module/delegation.rb +172 -0
  64. data/lib/active_support/refinements/core_ext/module/deprecation.rb +27 -0
  65. data/lib/active_support/refinements/core_ext/module/introspection.rb +80 -0
  66. data/lib/active_support/refinements/core_ext/module/qualified_const.rb +54 -0
  67. data/lib/active_support/refinements/core_ext/module/reachable.rb +10 -0
  68. data/lib/active_support/refinements/core_ext/module/remove_method.rb +14 -0
  69. data/lib/active_support/refinements/core_ext/name_error.rb +20 -0
  70. data/lib/active_support/refinements/core_ext/numeric.rb +3 -0
  71. data/lib/active_support/refinements/core_ext/numeric/bytes.rb +46 -0
  72. data/lib/active_support/refinements/core_ext/numeric/conversions.rb +137 -0
  73. data/lib/active_support/refinements/core_ext/numeric/time.rb +81 -0
  74. data/lib/active_support/refinements/core_ext/object.rb +14 -0
  75. data/lib/active_support/refinements/core_ext/object/acts_like.rb +12 -0
  76. data/lib/active_support/refinements/core_ext/object/blank.rb +107 -0
  77. data/lib/active_support/refinements/core_ext/object/conversions.rb +4 -0
  78. data/lib/active_support/refinements/core_ext/object/deep_dup.rb +48 -0
  79. data/lib/active_support/refinements/core_ext/object/duplicable.rb +92 -0
  80. data/lib/active_support/refinements/core_ext/object/inclusion.rb +27 -0
  81. data/lib/active_support/refinements/core_ext/object/instance_variables.rb +30 -0
  82. data/lib/active_support/refinements/core_ext/object/to_json.rb +27 -0
  83. data/lib/active_support/refinements/core_ext/object/to_param.rb +60 -0
  84. data/lib/active_support/refinements/core_ext/object/to_query.rb +29 -0
  85. data/lib/active_support/refinements/core_ext/object/try.rb +72 -0
  86. data/lib/active_support/refinements/core_ext/object/with_options.rb +44 -0
  87. data/lib/active_support/refinements/core_ext/proc.rb +19 -0
  88. data/lib/active_support/refinements/core_ext/range.rb +3 -0
  89. data/lib/active_support/refinements/core_ext/range/conversions.rb +21 -0
  90. data/lib/active_support/refinements/core_ext/range/include_range.rb +23 -0
  91. data/lib/active_support/refinements/core_ext/range/overlaps.rb +10 -0
  92. data/lib/active_support/refinements/core_ext/regexp.rb +7 -0
  93. data/lib/active_support/refinements/core_ext/string.rb +13 -0
  94. data/lib/active_support/refinements/core_ext/string/access.rb +106 -0
  95. data/lib/active_support/refinements/core_ext/string/behavior.rb +8 -0
  96. data/lib/active_support/refinements/core_ext/string/conversions.rb +60 -0
  97. data/lib/active_support/refinements/core_ext/string/encoding.rb +10 -0
  98. data/lib/active_support/refinements/core_ext/string/exclude.rb +13 -0
  99. data/lib/active_support/refinements/core_ext/string/filters.rb +54 -0
  100. data/lib/active_support/refinements/core_ext/string/indent.rb +45 -0
  101. data/lib/active_support/refinements/core_ext/string/inflections.rb +214 -0
  102. data/lib/active_support/refinements/core_ext/string/inquiry.rb +15 -0
  103. data/lib/active_support/refinements/core_ext/string/multibyte.rb +58 -0
  104. data/lib/active_support/refinements/core_ext/string/output_safety.rb +194 -0
  105. data/lib/active_support/refinements/core_ext/string/starts_ends_with.rb +6 -0
  106. data/lib/active_support/refinements/core_ext/string/strip.rb +28 -0
  107. data/lib/active_support/refinements/core_ext/string/xchar.rb +18 -0
  108. data/lib/active_support/refinements/core_ext/time.rb +5 -0
  109. data/lib/active_support/refinements/core_ext/time/acts_like.rb +10 -0
  110. data/lib/active_support/refinements/core_ext/time/calculations.rb +251 -0
  111. data/lib/active_support/refinements/core_ext/time/conversions.rb +65 -0
  112. data/lib/active_support/refinements/core_ext/time/marshal.rb +30 -0
  113. data/lib/active_support/refinements/core_ext/time/zones.rb +98 -0
  114. data/lib/active_support/refinements/core_ext/uri.rb +28 -0
  115. data/lib/activesupport-refinements.rb +9 -0
  116. data/lib/activesupport-refinements/version.rb +5 -0
  117. data/refine_core_ext.rb +45 -0
  118. data/spec/hwia_spec.rb +15 -0
  119. data/spec/try_spec.rb +18 -0
  120. metadata +182 -0
@@ -0,0 +1,4 @@
1
+ require 'active_support/refinements/core_ext/date_time/acts_like'
2
+ require 'active_support/refinements/core_ext/date_time/calculations'
3
+ require 'active_support/refinements/core_ext/date_time/conversions'
4
+ require 'active_support/refinements/core_ext/date_time/zones'
@@ -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,5 @@
1
+ module ExceptionExt
2
+ refine ActiveSupport do
3
+ FrozenObjectError = RuntimeError
4
+ end
5
+ 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'