onelixir

onelixir

Question about Phoenix Directory Structure

The Phoenix Framework Doc shows the Directory Structure like this:

lib/hello_web
├── controllers
│   ├── page_controller.ex
│   ├── page_html.ex
│   ├── error_html.ex
│   ├── error_json.ex
│   └── page_html
│       └── home.html.heex
├── components
│   ├── core_components.ex
│   ├── layouts.ex
│   └── layouts
│       ├── app.html.heex
│       └── root.html.heex
├── endpoint.ex
├── gettext.ex
├── router.ex
└── telemetry.ex

I have some question about this:

  1. Now we have just one page controller, inside controllers directory we have 2 page_* files and 1 page_* directory, if we also add JSON support, then one more file, one controller = 3 files + 1 directory, if we have 10 controllers, will we have 30 files + 10 directories in controllers directory?
  2. If we also need email, like in Rails, where should we put its directory, do we have some generator? And how about jobs?

I ask these questions because I just come from Rails, Phoenix looks simple but also brought too much confuse.

I truely hope Phoenix world have a book like 《 Agile Web Development with Rails 7》, The official document is good, but lack of focus and best practices.

Most Liked

sodapopcan

sodapopcan

It’s really just because the framework isn’t concerned about where your files are. For example, our Rails app was split up by feature so we ended up with many directories that essentially each had a mini Rails apps in them. It’s not the biggest deal in to make this work but you’re still going against the framework conventions. You also lose the social friction of new people coming into the app expecting it to look like a Rails app and it doesn’t. Phoenix doesn’t set up any such expectation. I’m not really saying it’s a massive, life-changing improvement but it is part of what drew me to Phoenix even if I do miss some stuff about Rails.

As far as Ecto vs ActiveRecord goes, I would say that is a massive improvement. It takes a bit to get comfortable with the shift away from an ORM, but Ecto is essentially like a super powerful and better designed arel. You don’t run into the same scaling issues with it since it just returns structs (which are no heavier than bare maps) as opposed to massive objects with methods spanning at least five different concerns.

sodapopcan

sodapopcan

Phoenix is not opinionated like Rails. There is a tiny bit of “magic” happening with via some dabs of reflection but it’s not pervasive. Phoenix doesn’t care at all where you put your files and the generated structure is more of a guideline. In fact, Phoenix is arguably closer to Sinatra than it is to Rails with $ mix phx.new being what makes it a full fullstack framework. There are single file examples of Phoenix apps out there!

I also came from Rails so I definitely shared some of your pain. I was particularly perturbed that many examples don’t show you exactly were to put files. I’m not saying this is better or worse, but you get used to it pretty quickly.

Your example is actually slightly flawed when comparing number of files to Rails. In Rails, the equivalent page_ files you mentioned would be controllers/page_controller.rb and views/pages/show.html.erb and helpers/page_helper.rb, so actually 3 files and 3 directories! The _html files in Phoenix are a new concept but basically they used to be called views. Phoenix splits up the concept of “view” into “html” and “template” (it used to be “view” and “template”) where html compiles the templates and controllers render the html. This is actually closer to how the general concept of a view quote-unquote “should” work (the “view” is the presentation logic whereas the “template” is the static markup) whereas Rails simplifies it by combining view+template then optionally allowing a ‘helper’ file if you need added presentation logic. In Phoenix, you would put your “helpers” in the PageHTML module. So, you are right in that Phoenix always forces you to have three modules (er, two modules + one template). If you’re strictly concerned about number of files and you don’t mind putting your templates in functions, you can actually define your templates right in PageHTML then you don’t need the show.html.heex file:

defmodule MyAppWeb.PageHTML do
  # ...
  def show(assigns) do
    ~H"""
    <h1>I'm the show page</h1>
    """
  end
end

I actually don’t use the default directory structure at all for web. I don’t have many controllers as I often have LiveViews but I break up my Web module into site sections, so I don’t have a controllers or live directory. Mine would look like this:

my_app_web/
  page/
    page_controller.ex
    page_html.ex
    html/
      show.html.heex

You don’t have to do anything special to make this work—just move the files around. Although you’ll have to likely have to change the glob given to PageHTML.embed_templates.

onelixir

onelixir

Thank you so much again, I think I learn a lot from your answers, I will dive into Phoenix to feel the feeling you feel.

Also, one of the most happy thing in Elixir land is because we have so kindly people like you :heart:

Where Next?

Popular in Discussions Top

PragTob
Hello everyone, I know we had quite some threads (read through lots of them) about background job processing but it remains a hotly deba...
New
thojanssens1
It would be nice to be able to define a redirect from one route to another from the router.ex file. E.g.: redirect "/", UserController, ...
New
AstonJ
If a newbie asked you about Phoenix Contexts, how would you explain the basics to them? Feel free to be as concise or in-depth as you li...
New
CharlesO
Erlang :list.nth simple, but 1 - based nth(1, [H|_]) -&gt; H; nth(N, [_|T]) when N &gt; 1 -&gt; nth(N - 1, T). Elixir Enum.at … coo...
New
marciol
Please, let me know if this kind of discussion already took place in another topic . Hi all, how do you consider if is better to build ...
New
PragTob
Hey everyone, this has been brewing in my head some time and it came up again while reading Adopting Elixir. GenServers, supervisors et...
New
rower687
Hi all, I’ve been reading a lot about the “let it crash” term and how supervising processes and the whole messaging passing make an elixi...
New
rms.mrcs
A couple of days ago I was discussing with a friend about different approaches to write microservices. He said that if he was going to w...
New
cblavier
Hey there, It’s been more than a year since we started using LiveView as our main UI library and building a whole library of UI componen...
New
scouten
I’m looking for a host for the server part of a small (personal) side project that I’m working on. It’s currently written in Node.js and ...
New

Other popular topics Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 36128 110
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
marick
I had some trouble figuring out how to make many-to-many associations work. Once I got it working, I wrote a blog post. Because I’m a nov...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

We're in Beta

About us Mission Statement