Should I use Ecto.Repo in Controller or Model for

2020-03-01 10:36发布

问题:

For some query in Controller of Phoenix, there're two plans for me

Plan 1:

defmodule Demo.UserController do
  # ...
  def index do
    # This is just for example
    # The point is Repo in used here
    Repo.all(User) 
  end
end

Plan 2:

defmodule Demo.User do
  # ...
  def all do
    # Put all Repo API and building query logic in Model
    Repo.all(__MODULE__)
  end
end

I prefer the Plan 2. Because in most situations, I can put all logic about fetching data in Model.

But I find official guide use Plan 1(docs/model) and Phoenix default code alias Repo in Controller instead of Model (web/web.ex)

Which one is better? And why?

回答1:

You should keep your Repo calls inside your controller. If your logic is complicated then you should consider moving the logic out into its own service module.

You should treat your model functions as pure (free from side effects) so they should only act on data. So for example you could have:

def alphabetical(query)
  order_by(query, [u], u.name)
end

But you should not have:

def alphabetical(query)
  order_by(query, [u], u.name)
  |> Repo.all
end

This is because queries are purely data, the call to Repo.all has side effects (going off to the database) so it belongs in your controller.