aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activesupport/CHANGELOG.md7
-rw-r--r--activesupport/lib/active_support/duration.rb20
-rw-r--r--activesupport/test/core_ext/duration_test.rb15
-rw-r--r--guides/source/active_support_core_extensions.md15
4 files changed, 57 insertions, 0 deletions
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index f1dd7c312d..478fef2baf 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,3 +1,10 @@
+* Add `flatten` and `flatten!` methods to Duration objects.
+
+ Example:
+ Date.today + (1.month + 1.month).flatten == Date.today + 2.months
+
+ *Ionatan Wiznia*
+
* `require_dependency` accepts objects that respond to `to_path`, in
particular `Pathname` instances.
diff --git a/activesupport/lib/active_support/duration.rb b/activesupport/lib/active_support/duration.rb
index 87b6407038..1db0ca51ae 100644
--- a/activesupport/lib/active_support/duration.rb
+++ b/activesupport/lib/active_support/duration.rb
@@ -81,6 +81,18 @@ module ActiveSupport
to_i
end
+ # Flattens all the +parts+ of the duration, and returns a
+ # new duration object.
+ def flatten
+ Duration.new(@value, flatten_parts)
+ end
+
+ # Flattens all the +parts+ of this duration.
+ def flatten!
+ @parts = flatten_parts
+ self
+ end
+
protected
def sum(sign, time = ::Time.current) #:nodoc:
@@ -97,6 +109,14 @@ module ActiveSupport
end
end
+ def flatten_parts
+ @parts.inject({}) do |result, (name, value)|
+ result[name] ||= 0
+ result[name] += value
+ result
+ end.to_a
+ end
+
private
def method_missing(method, *args, &block) #:nodoc:
diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb
index ed267cf4b9..cc24d7c74c 100644
--- a/activesupport/test/core_ext/duration_test.rb
+++ b/activesupport/test/core_ext/duration_test.rb
@@ -145,6 +145,21 @@ class DurationTest < ActiveSupport::TestCase
assert_equal '172800', 2.days.to_json
end
+ def test_flatten
+ a = 2.months
+ b = (1.month + 1.month).flatten
+
+ assert_equal a.parts, b.parts
+ end
+
+ def test_flatten!
+ a = (1.month + 1.month)
+ b = a.flatten
+ a.flatten!
+
+ assert_equal a.parts, b.parts
+ end
+
protected
def with_env_tz(new_tz = 'US/Eastern')
old_tz, ENV['TZ'] = ENV['TZ'], new_tz
diff --git a/guides/source/active_support_core_extensions.md b/guides/source/active_support_core_extensions.md
index d3f49b19fa..d11c17117e 100644
--- a/guides/source/active_support_core_extensions.md
+++ b/guides/source/active_support_core_extensions.md
@@ -3699,6 +3699,21 @@ Time.utc(1582, 10, 3) + 5.days
# => Mon Oct 18 00:00:00 UTC 1582
```
+When addinng or substracting durations, the resulting duration will be equivalent to subsequent calls to since or advance, so:
+
+```ruby
+Date.new(2013,1,28) + 1.month + 1.month
+# => Thu, 28 Mar 2013
+```
+
+If you want to add durations and then use them as just one call to since or advance, you can use the flatten or flatten! method:
+
+```ruby
+Date.new(2013,1,31) + (1.month + 1.month).flatten
+# => Sun, 31 Mar 2013
+```
+
+
Extensions to `File`
--------------------