0
votes

I have a blog with a backend showing a list of Posts. Each Post has a publish_on value which is a datetime -- if the current time is later than publish_on, the Post is active (Post has a boolean virtual field called active).

When I query the Repo for a list of Posts, I'd like to go through the list, and set Post's active to true if the current time is after publish_on.

What is the most "Elixirian" way to do this? (Also, what is the Elixir community's version of "Pythonic"?)

models/post.ex

defmodule MyApp.Post do
  use MyApp.Web, :model

  schema "posts" do
    field :title, :string
    field :content, :text
    field :publish_on, Ecto.DateTime
    field :active, :boolean, virtual: true, default: false

    timestamps()
  end

controllers/post_controller.ex

MyApp.PostController
  def index(conn, _params) do
    query = from p in Post,
    posts = Repo.all(query)

    ###I assume some kind of mapping goes here

    render(conn, "index.html", posts: posts)
  end

templates/post/index.html.eex

<table class="table">
<%= for post <- @posts do %>
    <%= if post.active do %>
      <tr class="published">
    <% else %>
      <tr class="unpublished">
    <% end %>
2

2 Answers

2
votes

I'd go through the posts using for, compare DateTime.utc_now with post.publish_on using DateTime.compare, and if it's :gt, set active to true:

posts = Repo.all(query)

now = DateTime.utc_now

posts = for post <- posts do
  case DateTime.compare(now, post.publish_on) do
    :gt -> %{post | active: true}
    _ -> post
  end
end
2
votes

You can initialize the virtual field in your query:

query = from p in Post, select: %{p | active: (s.publish_on < ^DateTime.utc_now())}
posts = Repo.all(query)