How to order_by in phoenix 1.3

In a 1.2 project I have the following ecto query to sort results by desc date:

def index(conn, _params) do
  bydesc = Post |> order_by(desc: :inserted_at) |> Repo.all
  render(conn, "index.html", bydesc: bydesc,) 
 end

But I’m struggling to do this in 1.3 since we’re not using Repo here anymore.

def index(conn, _params) do
  bydesc = Post |> order_by(desc: :inserted_at) |> Articles.Post.all
  render(conn, "index.html", bydesc: bydesc,)
end

I just get undefined function order_by/2

You can add a function in the Articles.Post (or something like that) module which would return the ordered results.

The index action in the controller then becomes

def index(conn, _params) do
  bydesc = Articles.Post.fetch_ordered(desc: :inserted_at) # or is it just Articles.fetch_ordered/1?
  render(conn, "index.html", bydesc: bydesc)
end

The function in Articles.Post can be something like

def fetch_ordered(constraint) do
  Post |> order_by(constraint) |> Repo.all()
end

The point of phoenix 1.3 is moving this kind of logic out of the web layer and into the domain layer, I guess. There are quite a few threads around here discussing it.

[1] How to determine contexts with Phoenix 1.3
[2] Lonestar ElixirConf 2017 - KEYNOTE: Phoenix 1.3 by Chris McCord
[3] How context should be used in phoenix 1.3?
[4] Contextual schema VS out-of-context schema (in Phoenix 1.3)
[5] Phoenix 1.3 generated folder structure
[6] Understanding contexts in Phoenix 1.3
[7] Clarity needed on Phoenix 1.3 contexts and schema in controllers
[8] Controller style & structure in Phoenix 1.3

5 Likes

Thanks. Not quite got it working yet, but will have a read through all those links.

Now I’m doing something completely wrong. In post.ex I have:

  def fetch_desc do
    bydesc = Post |> order_by(desc: :inserted_at) |> Repo.all
  end

But I just get lib/driverless/articles/post.ex:33: undefined function order_by/2

It’s probably clear by now I’m fairly new to Phoenix full stop!

Ah! The reason for this, is that the functions like from, where, order_by, etc. are part of the Ecto.Query module. To use them, write import Ecto.Query somewhere in your module (or if you only want to use it in a single function, only in that function).

It might very well be the case that this was part of the modules that were automatically included in the Phoenix controller logic before, but no longer in 1.3. I am not 100% sure. In any case, that’s where you can find those functions :-).

2 Likes

Bingo.