Phoenix 1.3.0 Released
phoenixframework.org
phoenixframework.org
- Programming Phoenix by Chris McCord, Bruce Tate, and José Valim [1]
- The Little Elixir & OTP Guidebook by Benjamin Tan Wei Hao [2]
- Elixir in Action by Saša Jurić [3]
Phoenix initially attracted me to Elixir, I've stuck around for that and the OTP platform: pattern matching, process based concurrency (actor model), supervision, immutability, macros, and more.
"Elixir took the Erlang virtual machine, BEAM, and put a sensible face on it. It gives you all the power of Erlang plus a powerful macro system." – Dave Thomas
[1] https://startlearningelixir.com/r/programming-phoenix
[2] https://startlearningelixir.com/r/the-little-elixir-and-otp-...
You build you a simple HTTP server using Elixir and learn a lot of the core language and architecture choices when writing Elixir code. It doesn't pester you with this is an int, this is a string. You just start building this HTTP server out and learn about Elixir along the way.
Some of the elixir bits are now out of date. (eg. it still has a section on Records)
But it touched on a lot of OTP topics that were missing from other places.
(this was before Benjamin Tan's book was finished)
At the time I remember Elixir in Action really made me finally understand the OTP concepts.
For comparison, though, Dave Thomas' "Programming Elixir" doesn't even mention them.
I just got it a few days ago and I'm about 30% into the first book. What I can say so far is that the author's approach resonates really well with me. Going through the book feels like sitting next to a colleague, who is introducing you to Phoenix and is really knowledgeable in the topic. The book is full of interesting tidbits and explanations about Phoenix internals without getting in the way. I also appreciate the TDD approach including both acceptance and unit testing. The most important thing for me though, is how Shankar condensed teaching Elixir into a single chapter. I have previously tried to study Elixir a few times with the intention of eventually getting into Phoenix but I always got overwhelmed by the OTP material. I didn't want to make the mistake of trying to learn Rails before being comfortable with Ruby again so I put off on learning Phoenix altogether. What Shankar has done is to dedicate one chapter to teach just enough Elixir for you to get started. This was perfect for what I needed and it was reassuring knowing exactly how much (or little) Elixir you need to know before diving into Phoenix.
If you have previous experience in another MVC framework and are interested in Phoenix I highly recommend this series (at least based on what I've read so far).
I should note that the current version of the book is targeting Phoenix v1.3.0-rc.2. Although Shankar has already made an announcement with the intention to update the book soon after the officially 1.3.0 release.
Do you need Elixir experiences too?
I've done MVC and have some functional experiences.
I've seen this book but wasn't sure if it was for me and decided to do exercism's elixir exercises before buying this book.
thanks
It's a strange way to sell a book, when neither the web site selling the book nor googling seem to enlighten me.
Garuda, I'm sure after googling you found the Wikipedia entry for it. It is just a play on words since Garuda, like Phoenix, is a type of mythical bird.
I agree with you, I could have explained the book's content and its title a bit more clearer on my website. I will do it sometime soon.
[1] https://www.amazon.com/Programming-Phoenix-1-3-Productive-Re...
Coming from Rails, the ecosystem isn’t quite there yet, but it is far more mature than rails’ was this early on.
The hardest thing for us has been deployment, but we’ve solved that internally, including giving back by building exrm_deb (it works with distillery too!) to compile the entire project into a Debian package.
If you haven’t already looked at Phoenix (and Ecto!) give it a try :)
Summary: It's amazingly productive, pleasant to work with and simple.
Coming from a background spanning Python/Django, C#/.net and Node/Express I really believe it blows them out of the water.
Thank you for all the hardwork of the Phoenix team and the amazing community you've made.
The Concurrency Model is simple to the point where creating a whole pubsub system to handle events, push out notifications, and handles backpressure can be done in < 100 lines with no additional datastores or frameworks.
Finally the pipe operator is like C#'s LINQ statements but with so much more power and flexibility, hard to explain but I highly recommend cracking open that book on your nightstand!
Erlang's concurrency model is amazing. It's like having micro-microservices running inside your virtual machine. And you can distribute across nodes. Nothing else really has this kind of thing.
Pattern matching is beautiful and it's easy to use. Other languages have this too, so it's not like this is unique. This is one of my favorite things though; you can destructure things, you can pattern match inside a function using case, and you can pattern match on functions themselves like:
def say("Hi"), do: IO.puts("Hello")
def say("Bye"), do: IO.puts("Goodbye")
def say(_msg), do: IO.puts("Where am I?")
That's basically the equivalent of having a single say() function that then does a switch/case on the input.And a more recent addition to the language is "with". This is fantastic, it's one of my favorite things now. Usually you might have code that sets a variable from something, checks to make sure it's valid, sets another variable, checks to make sure it's valid, etc, etc... until finally you're function is ready to actually perform its purpose. Any of those checks might cause it to exit early or to switch paths. So Elixir has this "with" feature that looks sort of like this:
def create(conn, %{"id" => group_id, "friend_id" => friend_id}) do
with {:ok, user} <- current_user(conn, groups: [memberships: [:user, :group]]),
{:ok, group} <- Groups.fetch_for_user(user, group_id),
{:ok, friend} <- Friendship.fetch_friend(user, friend_id),
{:ok, member} <- Groups.add_member(group, friend)
do
render(conn, "success.json", msg: msg)
else
{:error, msg} ->
conn
|> put_status(:unprocessable_entity)
|> render("failure.json", msg: msg)
end
end
I love this feature. It makes code so much more readable and maintainable in my opinion.Here's a similar construct in Scala:
(for {
user <- currentUser(...)
group <- groups.fetchForUser(...)
friend <- friendships.fetchFriend(...)
member <- groups.addMember(...)
} yield {
render(...)
}).recover {
case e: Exception -> ...
}To expand a bit more, it's not like Scala's `Either[T, U]` where we're limited to a pair of types, I think you can return other atom values (but use :ok and :error) as a convention.
Also, there is an Elixir library I'm using that's a closer in spirit to Scala's for-comprehension called `monadex`. Example below:
result = success(comment_params)
~>> fn p -> link_reply_to_id(p) end
~>> fn p -> create_changeset(p) end
~>> fn cs -> assert_changeset(cs) end
~>> fn cs -> insert_changeset(cs) endI recently ported my app from 1.2->1.3 and moving away from Models to Contexts/Data was a simple transition that makes a lot of sense.
The `data` files (aka your new models) are basically where the schema for your model lives and the `context` (your models API) is the interface for your data.
For example when building a blog:
Instead of having User, Session, Post, and Comment models which contains your DB schema, business logic, and interfaces for getting/setting data all models directory ala Rails:
blog/app/models/comment.rb
blog/app/models/post.rb
blog/app/models/session.rb
blog/app/models/user.rb
blog/app/controllers/...
blog/app/views/...
you instead create a namespace for each group of data: lib/blog_app/accounts/accounts.ex
lib/blog_app/accounts/session.ex
lib/blog_app/accounts/user.ex
lib/blog_app/blog/blog.ex
lib/blog_app/blog/comment.ex
lib/blog_app/blog/post.ex
lib/blog_app/web/controllers/...
lib/blog_app/web/views/...
And in your data file `lib/blog_app/blog/post.ex` for example, you'd keep just your schema defining the fields like "title, permalink, body, etc" and code to handle validations and virtual attributes.Then in your context file `lib/blog_app/blog/blog.ex` you define the API that access your data. So from your controller instead of calling:
Post.all
Comment.all
Comment.find(1)
User.new({..})
You now call: Blog.list_posts
Blog.list_comments
Blog.get_comment(1)
Accounts.create_user({..})
It makes for a very logical structure for your MVC code.It would be great if there was one official way to make it easier to implement app security with the framework. I feel that this is the only missing part in phoenix - but it is a very important one.
BTW: does anybody know some tool that generates a phoenix api from a json-schema? Thanks!
You want the whole enchilada? Use Guardian.
Need oauth? Use ueberauth.
Just want email and password? Use comeonin to hash your password.
It's liberating to know exactly how your system works and that it's not hidden behind some magical blackbox like Devise.
With a cookie?
With a server-side session?
With a database session?
With an authentication token GET params?
With an authentication token in the header?
You make the choices for your specific use case and implement them using laser-focused, great packages. One system I built authenticates with an `authenticationToken` GET params, I look for that in a Plug, then assign the current_user to the conn object.
For non-api requests, I use plain old sessions.
Am I reading that right or is it just comparing an unencrypted string to the encrypted version?
As of now there are no libraries available to implement above functionality easily for Phoenix framework. For me also this is one of the main reason to go ahead with Elixir + Phoenix
However, I was recently in need of implementing authentication for more than two models (Buyer, Seller) and that's where I hit a roadblock with these Devise-like libraries. Just by chance I found a really good, well designed library which I use in production as of now. The author is also the author of many other famous libraries in Phoenix-verse (Comeonin, for example). The library is called Phauxth. Check it out:
What would a transition to phoenix + elixir look like for me?
I'd suggest:
https://pragprog.com/book/phoenix/programming-phoenix
In structure it reminds me a lot of the very first Rails book co-authored by DHH. It's a good way to get into the language/framework.
It is worth stating that the way Erlang/Elixir manage processes is completely different than most other languages and that has to be grokked at some point. Thankfully the framework abstracts a lot of that.
The Elixir and Phoenix docs are also pretty good. They're not Django-level (what is), but they're good.
Or sets of things which only work if given in a particular order. Or unrelated functionalities which interfere with each other due to implementation details. And so on.
In other words, leaky abstractions where thinking in terms of the concept has so many edge cases that it's easier to think in terms of the implementation instead. Or conventions which can only be used via memorisation, trial and error, stack overflow and reading the source (often this is due to shoehorning things into language models which aren't amenable; e.g. all of the things aspect oriented programming tries to do)
Or are you making a stronger claim that language X is better than Y, at least when it comes to web dev?
The thing I really miss from Django is the admin scaffolding. Phoenix just isn't there. In practice, you could continue to use Django as a front-end.
I moved away from Django when the recurring question of "this is neat, but how do I make it keep going no matter what?"
The problem is that I was/still am a rookie of a programmer. I could not wrap my head around async in Python. I just wasn't getting it. I had a nagging sense that it was going to fail in the middle of the night and there was nothing I could do about it.
So, enter Elixir, which actually has a syntax that is kind of close to Python. It made immediate sense. If you want to do something that can cause the program to fail, do it in a process and send a message back with the result. If the program spawning the process fails, the supervisor will restart it!
Sorry - back to your question - and this will probably disatisfy you, but the answer is that everything was neat. It was just simple CRUD stuff, but doing it in Python didn't feel "robust" enough.
I'm fully aware that my reasons are superficial, but the way Elixir works has made me way more confident as a programmer.
I came to Ruby from Java, I wrote Ruby code like Java code at the start, it runs, but it is bad, once I really learned to write Ruby code it became a billion times better.
Same thing happened to Elixir, my first few lines of Elixir were very similar to Ruby, similar syntax makes this possible, but I missed the real gains from Elixir this way.
There are quite a few functional programming concepts to learn, but once I finally clicked what pattern matching was all about Elixir programming went from enjoyable to amazing, if you can work functional programming concepts your way you can do a lot.
That said, don't worry about it unless it is critical for your job, do your code, once all the concepts click in it gets way better, spend some time with pure Elixir, it pays off just as much as it pays to a Rails developer to understand what Ruby is all about.
If you really want to learn a functional programming language I'd strongly suggest looking at Haskell, Ocaml or F#. Functional programming only really starts to shine with a good static type system and dialyzer simply doesn't cut it.
In a distributed system where machines register on a cluster and messages are passed constantly across isolated heaps, processes and entire machines transparently all of the assumed protections of a static type system break down. You can't enforce static types across a cluster anymore than you can across a JSON requests to somebody else's API without a lot of extra overhead.
Static types are essentially contracts and in order to enforce a contract like that on a cluster of different machines that would mean you'd have to exchange contracts everytime a new machine joined the cluster...for all modules and functions...with every machine on the cluster. And then you have to determine how to handle contract violations.
Clustered message passing operates more like request routing in that regard. Send to this machine, to this module, to a function named this, with this arity, that matches this pattern.
The Elixir gradual typing approach balances this reality extremely well in my opinion. You get type checking if you want it and can specify it in more detail...but it won't promise something that it can't guarantee across the cluster, across deploys and across changes.
I'm surprised that it's used in production at all. It's based on a new language that is years behind all the others in terms of available third-party libraries and modules.
I'm a fan of Contexts myself as that is typically how I architect apps on mobile as well. I like having everything separated more explicitly and testable individually and Contexts seem to promote that in a really nice way.
In the past few weeks:
- Erlang/OTP 20 released,
- Elixir 1.5 released
And Cowboy 2.0 is in Release Candidate phase.
Exciting times.
I'm just a bystander reading about erlang and elixir for awhile. Did web dev in php and a little bit of nodejs.
But I think what you guys doing are great. I'm glad Elixir and Phoenix came about it really helps drive the language into a field (web dev) and get people to notice.
And that one implementation of figuring out how people is log off or not that is in Phoenix was really sweet when you presented it.
Highly recommended, but as always ignore the hype/recommendations and do your own research.
I have been bit so many times with trying to figure out where to put things like authentication/registration in a traditional MVC rails like app.
We're using it at a client as a kind of nexus of all our legacy systems, in fact.
When I started with Phoenix I was anxious that the experience was going to be just like when I first tried out Play/Scala, but no. To my surprise, my experience was fantastic. Truly, this framework allows you to focus on your business problems rather than fighting with configurations/conventions.
One of the best decisions the team has made is introducing the concept of contexts from DDD[2]. Initially, I was pretty confused, but now, I simply cannot imagine myself going back once that I've understood it. It's basically breaking down your business into smaller tiny modules, like I've done in [1]. The other thing I love about Phoenix is the concept of umbrella applications. I'm not sure if Rails has an equivalent, but I think this alone is worth exploring Phoenix for.
I don't even have micro-services in my architecture yet, but because of these patterns, I'll be able to break out and scale my application if I require to, in the future.
Phoenix has proven to me that it can not only scale performance-wise, but also architecture-wise. Last time I tried developing [1], it was in PHP and I had to hire 5 devs to get it done..6 months later and we still weren't done. However, in just a matter of weeks, I was able to finish a complete working prototype of this mammoth application, with UI and frontend. As for my production setup, I use Docker + AppEngine (using a custom VM) and it has served me really well. The performance is top notch and everything works so flawless.
As for the language itself, I really love Elixir. I simply cannot imagine going back. It really forces you to think differently about your code. Last time I tried to learn a functional language, it was Scala - also a beautiful language on top of the JVM. But, the problem is, it's so academic in the sense that even a good book on scala had 400+ pages. Some of them had 700+ pages. But Elixir isn't like that, you can pick up the language in a matter of weeks (YMMV, it took me 2) AND build a project in no time.
For Elixir, if you're coming from a Ruby background, you'll be able to pick it up fairly easy. However, you will find it challenging when you hit a situation where you would have used a traditional for loop, but in Elixir, you would be forced to re-architect your code. And that's a good thing.
1) Functions have different forms and even nomenclature based on how many parameters they accept, how they are represented, etc.
2) Scala still has OO, which means it needs to carry a lot of baggage. The breadth of Scala's nomenclature combined with OO will take you a long way to learn the language.
3) Scala still runs on JVM which means you need to learn some of the JVM concepts if you'll be using it in prod. If you're from a Rails background, this is completely a new arena, because this is usually the Java guys' arena.
4) I wanted to be able to simply open up the source code and be able to understand what's happening. This was possible in Ruby/Rails, and ultra easy to do in Phoenix/Elixir, but painful in Play/Scala. IF you open up the source code of a Play! framework project, there's code so succinct that you would need to be strong with the language's understanding to get the full picture. Case class, implicit, etc., just to cite a few. In Elixir/Phoenix, it's just modules and it's just simple, yet elegant.
5) That being said, it's still good to learn Scala because there are tons of libraries out there with special use cases which you can use Scala for - It's still a good strongly typed language to build a robust project on. IF I remember correctly, David Pollak mentioned in his book that he'd written an app in Scala that ran for years without any problems.
As for Haskell, I read this somewhere - "Haskell is nice and all, but it's no Erlang." Since Erlang also has a bit of a learning curve, the next best alternative is Elixir.
P.S, - languages should be chosen based on one's own philosophy and in this case, Elixir strongly resonates with my own philosophy and all this is just my own opinion on why I chose it :)
Cheers.
While it is possible to look at source code in Ruby/Rails, in practice for me (even after a few years of production ruby experience) it was extremely painful to look at any number of libraries due to the amount of redirection and implicit state, and monkey patching. But Elixir has (almost always) been VERY easy to follow, sometimes the code is just so simple.
I wouldn't be surprised to see one elixir server replacing 5x - 10x servers.
http://www.techworld.com/apps-wearables/how-elixir-helped-bl...
Which is why I tried Gigalixir[1] and never looked back. It's sort of like Heroku for Phoenix/Elixir, but without the daily restarts and with hot upgrades and the ability to run a BEAM cluster. Jes (owner) has been super responsive and deploys are trivial... just like I like it.
Also got Postgres running in google cloud (a new offering!) and that's worked great as well.
Sparkpost for an email API and Timber.io for cloud logs have also been stellar. Sweet dashboards.
You get a lot at the free tier on these.
I also want to try gigalixir which has a free tier: https://gigalixir.com/
1) Daily restarts, which kill any app-side state such as a cache or ETS table
2) Can't take advantage of any clustering
3) Can't do hot upgrades
I also work on a number of side projects with coworkers and we host those in Heroku. Can't really speak to how well that'd work if they were more than just side projects, but it works for us.
https://github.com/hexpm/hexpm
Firestorm is another:
I'll prefix my comment by saying I'm someone who is more on the sysadmin side of the scale of things. My code isn't pretty, but it generally works well enough to get the job done. I'm learning (probably the most important thing, I guess).
Contexts are one of things that I felt the same about. Until I tried really using them, rather than stressing over whether or not I was using them properly.
I made the mistake of trying to think of them as microservices, which bogged me down and for my purposes was complete overkill. I've now reached a kind of happy medium, which I've realised that I really should have already been using. I've kinda realised I suck at api design. And for that I'm very thankful to the phoenix team, because it feels like I'm learning.
I have built an app[0], the app allow user to submit links, either using our web ui or via a bot.
When using web ui, they have to login, hence we associate the links with that user. The bot is different, everyone submit via the post share the same `Bot` account.
In other words, the process of inserting a link from web ui or via bot is a bit different. Without context, I would use different module or some branch code to distinct between them. I think context solves that nicely for me.
---
[0] https://one.betterdev.link which is an extra version of https://betterdev.link/
But if you don't, that's cool too. There are mix tasks for using the older style generators and mix tasks for the newer context style generators. Use whichever you prefer.
*Yes, I'm aware of Mono, but I've been completely unhappy with my experience using it.