I just refactored a project I’m working on to address precisely this issue. I added a new function to myapp_web.ex
, so now I have both view
and accounts_view
:
def view do
quote do
use Phoenix.View,
root: "lib/quizdrill_web/templates",
namespace: QuizdrillWeb
# Import convenience functions from controllers
import Phoenix.Controller,
only: [get_flash: 1, get_flash: 2, view_module: 1, view_template: 1]
# Include shared imports and aliases for views
unquote(view_helpers())
end
end
def accounts_view do
quote do
use Phoenix.View,
root: "lib/quizdrill_web/accounts/templates",
namespace: QuizdrillWeb
# Import convenience functions from controllers
import Phoenix.Controller,
only: [get_flash: 1, get_flash: 2, view_module: 1, view_template: 1]
# Include shared imports and aliases for views
unquote(view_helpers())
end
end
Then, I created a new accounts/
folder at lib/myapp_web/accounts/
and I created three directories inside it: controllers/
, views/
, templates/
. So my directory structure inside myapp_web
looks like this:
myapp_web/
├── accounts/
│ ├── controllers/
│ │ ├── user_auth.ex
│ │ ├── user_confirmation_controller.ex
│ │ ├── user_registration_controller.ex
│ │ ├── user_reset_password_controller.ex
│ │ ├── user_session_controller.ex
│ │ └── user_settings_controller.ex
│ ├── templates/
│ │ ├── user_confirmation/
│ │ ├── user_registration/
│ │ ├── user_reset_password/
│ │ ├── user_session/
│ │ └── user_settings/
│ └── views/
│ ├── user_confirmation_view.ex
│ ├── user_registration_view.ex
│ ├── user_reset_password_view.ex
│ ├── user_session_view.ex
│ └── user_settings_view.ex
├── controllers/
│ └── page_controller.ex
├── templates/
│ ├── dashboard/
│ │ └── index.html.heex
│ ├── layout/
│ │ ├── live.html.heex
│ │ ├── _user_menu.html.heex
│ │ ├── root.html.heex
│ │ ├── admin.html.heex
│ │ └── app.html.heex
│ └── page/
│ ├── index.html.heex
│ └── dashboard.html.heex
├── views/
│ ├── error_helpers.ex
│ ├── error_view.ex
│ ├── layout_view.ex
│ ├── page_view.ex
│ └── dashboard_view.ex
├── endpoint.ex
├── gettext.ex
├── telemetry.ex
└── router.ex
The controllers and the views can be moved into the new directories without affecting anything, but if the templates are moved then they will be in the wrong location – so I have edited each of the view files so it is an :accounts_view
rather than a :view
, following the adjustment I made to lib/myapp_web.ex
. For example:
defmodule QuizdrillWeb.UserConfirmationView do
use QuizdrillWeb, :accounts_view
end
Now I have everything having to do with user accounts under the accounts/
directory and out of the way.
I’d appreciate any feedback, incidentally – the one thing I don’t like about this approach is the code-duplication between the view
and accounts_view
functions in lib/myapp_web.ex
– I’d prefer to only change the root directory for the templates rather than copy-paste the whole function in the way that I did.