Hi, new to elixir and phoenix. I watched videos on elixir and phoenix and noted both creators said that inadequate error messages is a bug. As a relative beginner, I believe the error message I experienced left me in the dark.
Here's how it went... I created a phoenix app, created the database, created a model/scaffold by running a phoenix generator, added the routes, created the migration, ran the server, added some data, I opened the interactive elixir shell with $ iex -S mix
I then ran the query
iex(1)> BlogPhoenix.Repo.all(
...(1)> from p in BlogPhoenix.Post,
...(1)> select: p)
and received this error...
** (CompileError) iex:2: undefined function from/2
I found that error, to be unhelpful, that could be due to a lack of understanding of elixir, of course. I eventually found the answer by reading blog posts about querying in Ecto and Elixir, it took a long time to solve. A couple questions,
1) Where would I put import Ecto.query within my application to not experience this error?
2) why is this not input by default when I run a phoenix generator? Because in my head I think, of course, when I have a model I want to query it, so I'm not sure why this seemingly essential line of code isn't input into my models by default, especially if I run a generator.
Run phoenix generator, be able to query the model out of the box.
Ran phoenix generator, needed additional code to be able to query and did not receive a highly specific error message.
Hi, new to elixir and phoenix.
Greetings!
both creators said that inadequate error messages is a bug
Accurate statement :) but...
...unfortunately in this case, the error message can't be helped because Ecto.Query has not been imported, unless Elixir's compiler could walk beams and look for any module that exposes a from/2 function, but since it's at compile time, it can be a chicken/egg problem because we don't necessarily have beams to crawl if we can't compile.
1) Where would I put import Ecto.query within my application to not experience this error?
In Elixir, imports are lexically scoped, and you cannot use global imports to make from available any place in the app. You must explicitly import Ecto.Query where you'd like to use the functions within it. If you look in web.ex in your application, Phoenix does indeed import Ecto.Query when you use MyApp.Web, :controller/:channel/etc, but we can't import things globally or into iex. You could define a .iex.exs file which contains import Ecto.Query, which would save you from typing it in iex, but it also breaks normal iex shells, so you must always run iex -S mix when it in the app directory.
2) why is this not input by default when I run a phoenix generator? Because in my head I think, of course, when I have a model I want to query it, so I'm not sure why this seemingly essential line of code isn't input into my models by default, especially if I run a generator.
As I mentioned in 1, we do include convenience imports of Ecto.Query so you don't constantly have to import it in all controllers or channels, but in Elixir in general, we favor being explicit with our code, be it module imports, aliases, configuration, etc. Once you get used to this idea, the slight increase in keystrokes is far exceeded by having an immediate overview of what functions are available in your file, and what aliases exist.
Hope that helps and welcome aboard! Hop on elixir-lang irc if you'd like to chat more about this. Thanks!
Thanks for your high quality response. It makes sense now!
** (CompileError) lib/phoenix_trello_web/views/layout_view.ex:12: undefined function static_path/2
Most helpful comment
Greetings!
Accurate statement :) but...
...unfortunately in this case, the error message can't be helped because
Ecto.Queryhas not been imported, unless Elixir's compiler could walk beams and look for any module that exposes afrom/2function, but since it's at compile time, it can be a chicken/egg problem because we don't necessarily have beams to crawl if we can't compile.In Elixir, imports are lexically scoped, and you cannot use global imports to make
fromavailable any place in the app. You must explicitlyimport Ecto.Querywhere you'd like to use the functions within it. If you look inweb.exin your application, Phoenix does indeedimport Ecto.Querywhen youuse MyApp.Web, :controller/:channel/etc, but we can't import things globally or into iex. You could define a.iex.exsfile which containsimport Ecto.Query, which would save you from typing it in iex, but it also breaks normaliexshells, so you must always runiex -S mixwhen it in the app directory.As I mentioned in 1, we do include convenience imports of Ecto.Query so you don't constantly have to import it in all controllers or channels, but in Elixir in general, we favor being explicit with our code, be it module imports, aliases, configuration, etc. Once you get used to this idea, the slight increase in keystrokes is far exceeded by having an immediate overview of what functions are available in your file, and what aliases exist.
Hope that helps and welcome aboard! Hop on elixir-lang irc if you'd like to chat more about this. Thanks!