Skip to content

Commit 3e54482

Browse files
authored
Merge pull request rails#55405 from MatheusRich/relative-time-in-words
Add `relative_time_in_words` helper to ActionView
2 parents 1557b42 + 46c5bc7 commit 3e54482

File tree

4 files changed

+42
-0
lines changed

4 files changed

+42
-0
lines changed

actionview/CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
* Introduce `relative_time_in_words` helper
2+
3+
```ruby
4+
relative_time_in_words(3.minutes.from_now) # => "in 3 minutes"
5+
relative_time_in_words(3.minutes.ago) # => "3 minutes ago"
6+
relative_time_in_words(10.seconds.ago, include_seconds: true) # => "less than 10 seconds ago"
7+
```
8+
9+
*Matheus Richard*
10+
111
* Make `nonce: false` remove the nonce attribute from `javascript_tag`, `javascript_include_tag`, and `stylesheet_link_tag`.
212

313
*francktrouillez*

actionview/lib/action_view/helpers/date_helper.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,23 @@ def time_ago_in_words(from_time, options = {})
186186

187187
alias_method :distance_of_time_in_words_to_now, :time_ago_in_words
188188

189+
# Like <tt>time_ago_in_words</tt>, but adds a prefix/suffix depending on whether the time is in the past or future.
190+
# You can use the <tt>scope</tt> option to customize the translation scope. All other options
191+
# are forwarded to <tt>time_ago_in_words</tt>.
192+
#
193+
# relative_time_in_words(3.minutes.from_now) # => "in 3 minutes"
194+
# relative_time_in_words(3.minutes.ago) # => "3 minutes ago"
195+
# relative_time_in_words(10.seconds.ago, include_seconds: true) # => "less than 10 seconds ago"
196+
#
197+
# See also #time_ago_in_words
198+
def relative_time_in_words(from_time, options = {})
199+
now = Time.now
200+
time = distance_of_time_in_words(from_time, now, options.except(:scope))
201+
key = from_time > now ? :future : :past
202+
203+
I18n.t(key, time: time, scope: options.fetch(:scope, :'datetime.relative'), locale: options[:locale])
204+
end
205+
189206
# Returns a set of select tags (one for year, month, and day) pre-selected for accessing a specified date-based
190207
# attribute (identified by +method+) on an object assigned to the template (identified by +object+).
191208
#

actionview/lib/action_view/locale/en.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@
4343
hour: "Hour"
4444
minute: "Minute"
4545
second: "Seconds"
46+
relative:
47+
future: "in %{time}"
48+
past: "%{time} ago"
4649

4750
helpers:
4851
select:

actionview/test/template/date_helper_test.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,18 @@ def test_time_ago_in_words
203203
assert_equal "about 1 year", time_ago_in_words(1.year.ago - 1.day)
204204
end
205205

206+
def test_relative_time_when_time_is_in_the_past
207+
assert_equal "3 minutes ago", relative_time_in_words(3.minutes.ago)
208+
end
209+
210+
def test_relative_time_when_time_is_in_the_future
211+
assert_equal "in 3 minutes", relative_time_in_words(3.minutes.from_now)
212+
end
213+
214+
def test_relative_time_delegates_options_to_time_ago_in_words
215+
assert_equal "less than 20 seconds ago", relative_time_in_words(10.seconds.ago, include_seconds: true)
216+
end
217+
206218
def test_select_day
207219
expected = +%(<select id="date_day" name="date[day]">\n)
208220
expected << %(<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16" selected="selected">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n)

0 commit comments

Comments
 (0)