Relative time in Phoenix

In my last project I’m writing in Phoenix, I needed to display relative time on insertion time, something like time_ago_in_words in Rails. As such function doesn’t exist in Phoenix framework, I wrote it myself.

First, I wrote a seconds_ago  view function so I can get how many seconds has passed from inserted Ecto.DateTime  to current time:

[code lang="elixir"]
def seconds_ago(datetime) do
  :calendar.datetime_to_gregorian_seconds(:calendar.local_time()) - :calendar.datetime_to_gregorian_seconds(Ecto.DateTime.to_erl(datetime))
end
[/code]

When I have information how many seconds has passed, I can calculate relative time and output it as text:
def time_ago_in_words(seconds) when seconds < 60 do
  "#{seconds} second(s) ago"
end
def time_ago_in_words(seconds) when seconds < 3600 do
  "#{round(seconds/60)} minute(s) ago"
end
def time_ago_in_words(seconds) when seconds < 86400 do
  "#{round(seconds/3600)} hour(s) ago"
end
def time_ago_in_words(seconds) do
  "#{round(seconds/86400)} day(s) ago"
end

To display relative time in template, it’s simple as this:

<%= model.inserted_at |> seconds_ago |> time_ago_in_words %>

UPDATE: Here you can get better version of  time_ago_in_words  which acts like the one in Rails.

Setting page title in Phoenix

In Rails, you probably used content_for  for setting every page title. In Phoenix, layout is rendered before page template is rendered so content_for  approach will not work. Instead, here’s how you can set different page title for every action.

In layout_view.ex file, add get_page_title  function:

def get_page_title(conn) do
  if conn.assigns[:page_title] do
    "#{conn.assigns[:page_title]} - ApplicationName"
  else
    "ApplicationName"
  end
end

Continue reading