I'm not affiliated with the language but I just want to throw out that I've been around since the Geocities era as a web developer and I haven't seen a tech stack or platform this well thought out and so in tune with what makes developing (and testing!) modern web applications an absolute joy. There's really something special here. I see myself sticking with it for 10+ years with 0 regrets.
The best part about it is everything is ready today (and was before 1.9 too btw).
If you only need basic functionality and absolutely have to use Phoenix, Pow is a good choice:
Personally I haven't found auth to be a problem in Phoenix and I have lots of experience with Rails (and using Devise).
You can put together an iron clad user registration + auth system in about 150 lines of app-level code (not including lines of code for the template forms, but with Devise you would end up customizing your own forms anyways). This includes registering new users, authenticating by email + encrypted password, logging in, logging out, session management and having the idea of a current_user in your system, along with a way to restrict routes, controllers or actions to only logged in users. The essentials basically.
I would much rather manage ~150 lines of code in my own project that I fully know and can easily customize than pull in something like Devise which is 6,000+ lines of Ruby and have to configure / override a number of things.
Everyone has their own opinions but I would much rather spend my time developing features for my app than trying to figure out how to customize a massive third party dependency.
Personally I'm rolling with a magic link authentication system in my Phoenix app and it was also around 200 lines of code to implement everything, including configuring and sending the emails out. There's no external libs beyond Phoenix to get it all working (except for sending the emails out, in which case I use Bamboo which is a lib dedicated to sending emails).
In one day I can quickly get something up and running with Guardian and have full control over how my app does authentication. Password reset and confirmation are easily done with Phoenix.Token without a need to touch the database.
Also, authorisation is a breeze on Phoenix. Take a look at Canada: https://github.com/jarednorman/canada - and it is only 10 LOC.
I agree, but it's not unique to Phoenix. In the PHP world the otherwise excellent Symfony framework is only starting to add generation of authentication/authorization, and email confirmation and password reset remains the developer's responsibility.
I see two reasons for this.
1. Frameworks see themselves as building blocks, not RAD systems. When the core framework developers are (mostly) working on APIs they don't see the need for approval/password reset. After all "you'll issue the user with a JWT so who cares about the rest (shrug)"
2. Flexibility to auth with anything. Apparently not bundling a system makes it more "flexible".
I believe (1) to (a) be shortsighted and (b) we need RAD frameworks, of higher-level flexible components that can be bolted together.
I believe (2) is wrong, and bundling standard auth flows does not reduce flexibility: you implement your own if you need something else.
Maybe for AuthN, but AuthZ is pretty far from the business of a web framework. The framework authors seem, for the most part, to be avoiding first-party endorsement of secondary tooling that doesn't deeply benefit from being first-party. I find it super refreshing coming from Rails where it is either the golden path or good luck.
A lot of the early AuthN libraries seem to target the controller layer, but I've found, having worked on a couple of sizeable Phoenix production codebases, that AuthN at the app domain layer works better. Regular use of channels as an alternate entrypoint to web request controllers means that controller based helper libraries are less valuable. Once you push this logic inside the app domain, it really isn't the business of Phoenix to know or care about it, since you're just working in plain Elixir, probably with some sort of Ecto struct to represent identity.
But recently I read the Programming Phoenix 1.4 book (written by the authors of Elixir and Phoenix) and it really filled in a ton of gaps and made so many things click together. I can't speak highly enough about it. In fact, finishing that book today is what provoked me to write my comment here. The book might be exactly what you're looking for as like 5% of the book focuses on the super basics and a toy example, but 95% of the book focuses on building up a pretty real app and layering on features as you go. It's also up to date and feature complete even though the book is labeled as a beta release.
By the time you finish the book, you exercise a ton of interesting things along the way (including how to take advantage of Erlang's VM to build features that would be 100x more effort and probably 10x worse in other tech stacks). You definitely don't just build a simple todo app. I don't even want to say what we build in the end because it feels like a spoiler. I only say that because when I hit the last section of the book I had no idea what was coming and was blown away by what it covers. It literally made me smile for hours just thinking about how badass everything is when it all comes together.
I've also put up about a hundred screencasts at http://youtube.com/alchemistcamp.
https://pragmaticstudio.com/courses/unpacked-full-stack-grap...
These have been my go-to that seem to fit what you're describing. I hope this helps.
Another example is: https://github.com/AltTracker/alttracker
It's an implementation of fully functional site. The beauty of Elixir is that the code is very readable.
Trust me, if somebody puts that in Go, Rust or OCaml -- I'd ditch Elixir tomorrow.
The BEAM VM is just too good. You can have thousands of smaller tasks running in parallel and nothing lags until you hit the physical limits of the hardware -- which 99% of the apps never do.
Knowing that, it's perhaps more pertinent to talk about what you can actually bring to that VM. Alpaca [0] could potentially be the solution. Interoperation with the rest of the VM languages and static typing on top of that. I have no doubt that most of the community would simply not use it, because they don't care about static typing, but I have zero reservations about saying it would be a better way to write code for the BEAM in the future.
Without something like that, it's unlikely that I will actually put any code that does more than something like routing messages to other services or the like on the BEAM in the future. Beyond a fairly low number of lines I simply don't trust anyone to write code that does exactly what they think it will do and no more in a dynamically typed language.
Anyways, this subject occasionally comes up for discussion in the community. This post sums up my thoughts fairly well: https://elixirforum.com/t/static-vs-dynamic-typing/9824/3
Even if you disregard the modeling power that you can get from this there is an upper bound on any elixir project after which any work on it becomes less and less easy to do, as with all languages that lack a static type system. We write assertive elixir code as much as we can, but that doesn't mean that you can actually guarantee anything about a code path that is less traveled.
dialyzer is also not the answer. Oftentimes we'll find ourselves in a situation where dialyzer complains because someone who made a major library simply doesn't use dialyzer. You might wonder why they don't in that case, because it would pick this particular issue up very easily, but the next time you run into some garbage error that dialyzer spat out that you are instantly reminded that you can neither trust it to be correct or safe, so people turn it off.
Elixir has upsides: I think it's solidly the best language for creating servers of different kinds, but it's near useless after you pass a fairly short distance with it. I would absolutely never, in my personal endeavors (as opposed to my working contract) write an elixir server that actually tries to do anything meaningful itself other than just route messages to other servers.
It's always a little frustrating that folks pass on Erlang or Elixir as entirely dynamic. It's a lot closer to what you find in gradually typed languages if you take advantage of the tools available.
[0]: I know there are a few of these elixir projects, though I am not familiar with the parent's. Perhaps it's a typo?
I currently use Windows (where I spend 99% of my time in WSL) and everything runs great.
Stories to the contrary and hints how to make it work are welcome.
I've used the Windows installer[1] and have had no issues.
I know it is very similar to Ruby.
I wish there was a ElixirC syntax that would also compile to Earlang.
* Capitalized variables names
* use of comma, semi-colon, and period as clause delimiters
It's interesting, but I think that Prolog-style syntax is probably the easiest to read if you don't have syntax highlighting available (though I don't think there is as much of a difference with syntax highlighting).
Elixir has been second or third on my todo list for a long time. With the scary news from Vue, it might have just jumped the queue.
http://rvirding.blogspot.com/2008/01/virdings-first-rule-of-...
Or Poe's law, thus named in 2005, but based on a phenomenon that was well known by the time of Godwin's law.
Do you have a link?
Which is a bunch of FUD (see top comment by EvanYou).
Something striking from the release announcement:
> As mentioned earlier, releases was the last planned feature for Elixir. We don’t have any major user-facing feature in the works nor planned.
Part of me is a little alarmed—no one wants a language to stagnate. José makes it clear that this doesn't mean it's the last version:
> Of course, it does not mean that v1.9 is the last Elixir version. We will continue releasing shipping new releases every 6 months with enhancements, bug fixes and improvements.
Elixir is remarkably extensible. When I was first getting acquainted with the language finding macros with all the expressive ability of a LISP blew my mind. Making powerful macros a core part of the language meant that the language could grow. That in my mind is the most important part of any language's long-term viability.
Fantastic work all who contributed. Thank you for making a fast, functional, and fun language to work with!
In the sense of the language itself, I do. The language community should keep growing, libraries, frameworks, etc., but I'd like to see more languages qua languages declare themselves "done" sooner and more often, or failing a sudden cutoff, start seriously raising the bar on the next "new feature". There's a lot of good languages out there that were great in years 5-15 and then choked on all the features they kept adding to the core language.
I used to be so happy when there was a new Java version every year, something new is good, something better is good, some hype is good. Now I am getting old I just want to use the same tools for the next 15 years. I mean it is not like most of the problem we are trying to solves were limited by the languages itself. ( Mostly the ecosystem around it )
Elixir doesn't hold the same position for its abstract machine. BEAM, the abstract machine, has its development intertwined with that of Erlang's language development, but not-so-much with Elixir's. Elixir can stabilize while BEAM+Erlang continue to evolve "underneath" it. Given that Erlang syntax is pretty much† always valid Elixir syntax, Elixir doesn't even need to change to expose new Erlang stuff!
† There were big changes when maps were introduced, but another change of that scale seems unlikely at this point. (Unless Erlang gets a mutable byte-array type or something.)
In the end, I agree that the idea of a language which could be stable for a decade or more sounds fantastic! Given macros could add almost any other required feature should a good idea arise. Plus the BEAM and elixir compiler can continue improving performance and tooling.
Yes, of course 99% of the book is probably still relevant and all, but I believe it is important to brand a language as having reached maturity and stability.
However, in terms of new features, we have already been slowing down over the last releases.
That they are willing to put that in a primary book title is pretty bold.
That interchange library can then be integrated into the Elixir stdlib—that's what happened with DateTimes in Elixir—but there's no reason it needs to be. It works just as well to just keep the interchange-type library as its own tiny little dependency that all these libraries pull in.
Distillery has helped a lot for sure, so it's nice that it's basically been rolled into the base elixir distro.
It was clear to both Paul (Distillery author) and the Elixir team that Elixir releases were going to be a subset of what Distillery provides. There is a good chunk of what Distillery does that is well established and that's what we streamlined and brought into Elixir. Some other areas were left out, such as a complete structure for setting up CLI hooks, and most notably, hot code upgrades.
The documentation explains some of the complexities behind hot code upgrades: https://hexdocs.pm/mix/Mix.Tasks.Release.html#module-hot-cod... - so I won't go over those. More importantly, during discussions with different teams and library authors, it was clear there is not a golden path for hot code upgrades. There are different approaches, with different gains and pitfalls, and it would be too premature to choose one as blessed.
So what is the path forward?
While Elixir releases don't do hot code upgrades by default, its whole structure supports it. We use the proper names and structure everywhere. But the front-end to start the upgrade is not there.
I have discussed with Paul the possibility of Distillery building on top of what Elixir releases provide with a more complete feature set. It doesn't have to be done by Distillery either. Maybe someone (or multiple people) will provide a smaller package that focuses on hot code upgrades. Then once we gather enough collective knowledge, we can choose if and how to proceed.
Still, I believe Elixir releases cover the majority of use cases out there. But we will know for sure over the next months. At least, by making releases part of core, we hope we are easing the learning curve for releases altogether, which we will naturally lead more people to explore hot code upgrades.
Similarly I suspect many users of elixir are doing the "boring" thing that we're doing – load balancer -> stateless web server(s) running phx -> DB server. And they'd probably be more than happy with this.
This means that Distillery will remain the best choice for many of us, including myself.
I have a very simple deploy process with Edeliver and Gitlab CI/CD that basically just consists of pushing or merging a commit to master that passes the tests. There's zero down-time and it doesn't require containers on the server.
I'd also say that the "deployment story" wasn't any worse than Rails or other stacks in the past except in that people have a choice of having a stateful server.
This is how I'm doing it now: https://youtu.be/-mm44ADU3kc?t=172
You CAN do hot upgrades, but many times the complexity of doing so far outweighs the benefits. For any non trivial app it makes updates/deploys to the app non trivial as well.
Digging deeper the line from folks using erlang/elixir "in anger" was always that it was a supported feature but the reality is that most people shouldn't do it and wouldn't need to for the hassle it has.
That "separate mechanism" could be as simple as a plug that tells Mix to recompile and reload. Example (designed for - and part of - the Sugar framework, but should theoretically work for any Plug-based app, including Phoenix-based ones): https://github.com/sugar-framework/plugs/blob/master/lib/sug...
Hot upgrades like this are not foolproof (which is likely the reason why the above example is gated to :dev environments); there are other concerns like database migrations and other internal and external variances that make this inappropriate for most production situations. That said, these same concerns often exist for other high-availability situations as well, so if you know that you want zero-downtime code upgrades, figuring out a way to do it cleanly within the application is likely valuable as a way to avoid the hell on Earth that is trying to do this with, say, a bunch of load-balanced Docker comtainers.
Just the one being newly packaged into Elixir 1.9+ by default does not yet support hot-loading...
That would be nice if it were true. However, for better or worse, Distillery was Not Invented Here, so what Elixir shipped with today is a reimplementation of the simple half of Distillery.
Although we should probably embrace this aspect of the ecosystem, (like with clustering of servers) I bet it's even easier than I can imagine.
If I'm writing an application that I'll only deploy myself I can of course match the environments exactly. But what about if I wanted to distribute an Elixir application to end users that might install it on all kinds of different operating systems and distributions? Do I have to build a release for OS/architecture combinations like Linux/64bit, Windows/32bit and similar? Or do I have to match each Linux distribution and windows version exactly? That would make it rather impractical to use Elixir to write software you give to other people, and don't deploy yourself.
Of course when I looked at this Distillery was the standard way to deploy, but it doesn't look like this part is any different with Elixir Releases.
The other concern is packages with NIFs (native code) and they would need to be changed if they don't support cross-compilation yet.
I believe Nerves, which is an Elixir framework for embedded, does a good amount of cross compilation too but they have a more controlled environment.
Can anyone provide a good place to start on where to get started with Elixir?
I tend to learn by working on stuff and not just reading etc, maybe a step by step in elixir? I am going into the literature now as well
Thanks in advance for any help!
I especially recommend this approach because it gives you more or less the most complete cross-section of some basic data structures, some web stuff, and some database stuff via their db adapter of choice, Ecto, which is excellent.
Each part can be a pretty steep (but fairly quick) adjustment depending on your background.
Appreciate the input, thank you!
Here's a stupid example I whipped up:
https://gist.github.com/amorphid/3dec7028b05bd10f6ff3180d199...
^^^ you wouldn't ever code it that way, but you should (in my opinion) know what each line of code is trying to do.
[1]: https://pragprog.com/book/elixir16/programming-elixir-1-6
[2]: https://codestool.coding-gnome.com/courses/elixir-for-progra...
For understanding genservers there's The Little Elixir and OTP Guidebook, as well.
In my case I experimented with it for at least a year before I decided to jump in, my "experiments" are here: https://github.com/pmarreck/elixir-snippets (I tend to use single-file dev for exploring simple ideas; this is not a general pattern used in the community or anything, it's just something I discovered I could get by doing)
Thank you!
> From experience, we could deploy to a 70-node cluster in something like under 5 seconds by doing it in parallel. If you want to rotate your infrastructure... your deploy could be taking from 5 minutes to an hour depending on how fast the connection draining can be done.
https://soundcloud.com/elixirtalk/episode-145-feat-fred-hebe...
Even without the compilation and configuration stuff, it's easier to put the release bundle in something basic like an alpine image, rather than keep docker image versions and app in sync.
Also, releases can be very small, after all the superfluous parts/symbols are stripped. Combine that with a fresh alpine image and you have quick-to-deploy containers.
Notably, Elixir's release implementation does not support hot code upgrades. I use upgrades all the time, and won't be trying out Elixir's releases until this shortcoming is addressed.
- too much magic
- slow and painful to scale
- too much metaprogramming
- no compilation, makes it easy to hide syntax errors
- concurrency is absent
- frameworks like rails are too bloated
All these are addressed on the elixir platform, and there are more pros:
- immutability
- mostly purely functional
- well defined modules with good documentation
interested to know, how the releases feture going to affect the way we deploy elixir/phonenix apps in production ?
It can handle stateful things and distributed systems far nicer, with a programming model that is really adapted to it.