Domain-oriented web folder structure

I’m trying to find a way to organize my web folder into high-level application areas, and I’m starting with an admin area. However, the way I understand it, Phoenix encourages the following web folder structure:

hello_web
├── controllers
│   ├── foo_controller.ex
│   ├── bar_controller.ex
├── templates
│   ├── foo
│   │   ├── index.html.eex
│   │   ├── ...
│   ├── bar
│   │   ├── index.html.eex
│   │   ├── ...
├── views
│   ├── foo_view.ex
│   ├── bar_view.ex

while I’m trying to organize my folder structure like so:

hello_web
├── foo
│   ├── foo_controller.ex
│   ├── foo_view.ex
│   ├── templates
│   │   ├── index.html.eex
│   │   ├── ...
├── bar
│   ├── bar_controller.ex
│   ├── bar_view.ex
│   ├── templates
│   │   ├── index.html.eex
│   │   ├── ...

It seems a bit odd that on one hand Phoenix encourages domain-oriented organization of code into contexts (each with its own folder structure) in the main application folder, while on the other hand it encourages framework-oriented organization in the web folder.

What I tried so far is enforce the above folder organization, which seems OK up to the point when I try to override the template folder location per view. I don’t see a way to do this. The only option I found was in hello_web.ex, with the root: option to Phoenix.View:

use Phoenix.View, root: "lib/hello_web/templates"

but that seems to just change the root template folder for all views, and cannot be set on a view-by-view basis.

5 Likes

I’m doing the same thing. You can set it on a view-by-view basis. Just modify the view function in your hello_web.ex file so it starts like this:

  def view(opts \\ [root: "lib/hello_web/templates"]) do
    opts = opts ++ [namespace: HelloWeb]

    quote do
      use Phoenix.View, unquote(opts)

At the bottom of the file add a second macro to the one that is already there:

  defmacro __using__({which, opts}) when is_atom(which) do
    apply(__MODULE__, which, [opts])
  end

Now start every view where you want to override the template location with code like this:

defmodule HelloWeb.UserView do
  use HelloWeb, {:view, [root: "lib/hello_web/user/templates", path: ""]}

That should do the trick!

8 Likes

20 posts were split to a new topic: Discussion about domain-orientated folder structures in Phoenix