DEV Community

Anton
Anton

Posted on

Elixir and Elm learning log. Reading "Elixir and Elm tutorial" book.

I think, in November last year, I was browsing leanpub store and discovered a little book called "Elixir and Elm tutorial". I was hooked immediately. Because I am interested in both of those languages and I heard that the combination of Elixir and Elm is excellent.

The book is quite accessible in terms of price in case you are tight on funds as I am.

I have already finished half of the book, but want to publish the log that I am keeping while reading it.

The log itself is sporadic and chaotic. I logged my mistakes, as well as impressions.

I also had one monumental surprise for me.

The author is really open minded individual with whom I am now in communication. Shout out to Bijan and great respect.

One more thing, I was on Ubuntu so some of the commands I used may not work on your distro or system. A couple of weeks ago I've installed Antergos (arch based distro), and I started from the beginning again so the commands will change in another post.

Here we go. The following is the log:

19th November 2018.

Starting in the evening.

I have already been learning Elm and Elixir. More Elm than Elixir. I have learned more Haskell at this point than Elixir.

I'm familiar with functional programming. But I'm learning it, that means I haven't worked in the industry and I am yet to find a job and go through the interview process.
So this book is my way to learn Elixir and then to create a couple of portfolio projects.

I have already updated Elm to 0.19 on my machine while the book works with the version 0.18.

As it turns out I also have an updated Elixir (1.7.3).

The first question that I had before buying the book "what is the database that is used in the book". It would be nice to say something about postrgeSQL in the table contents on leanpub or in the description to the book.

I know that heroku is like a digital ocean.
Is it free for personal projects? What's the deal here?


mix phx.new platform

Gives an error:

The task "phx.new" could not be found

Probably I don't have phoenix installed.

I have installed it with
mix archive.install hex phx_new 1.4.0

Do I have ecto installed?

It is installed (probably was installed with phoenix).


I first tried changing the password to postgreSQL by entering the command
psql postgres (it didn't ask me for password)

then \password
I set up a new passoword. But it didn't work, then I ran a command I found on stackoverflow and it worked.

https://stackoverflow.com/questions/35785892/ecto-postgres-install-error-password-authentication-failed

sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';"

sudo service postgresql restart


Alight, so the issue has been solved and I have a phoenix app.

mix phx.server

then

localhost:4000

Yahoo, everything's working.


mix phx.gen.html Accounts Player players username:string score:integer

I'm reading about routing. I don't know what routing is yet.


I started working with html templates and ran into the issue with classes.

<div class="container">
    <a class="btn btn-success" href="/players/new">Create Player Account</a>
    <a class="btn btn-info" href="/players">List All Players</a>
</div>

I've read through the release notes on phoenix 1.4. Bootstrap was dropped in favor of Milligram https://milligram.io/

Oh, the milligram version doesn't look as awesome as bootstrap's version.
But no judgement here, because there is probably less friction when it comes to tweaking the look of the website to your needs. So as far as I know the folks at phoenix know better.

I finished the chapter diving in.

It's cool that the book starts with that chapter.

There is IO.inspect which I didn't know about.
And there is nice partial application example.


I messed up my doc test. I remember that there has to be very specific indentation.

I set it up.


Already know about pipe operator. Going through that one quickly.


Interesting thing about arity in Elixir is that you can define the function with the same name but with different arity. It would be interesting to see the examples, but I also feel like it will bring confusion.


Pattern matching.

Here's where Haskell knowledge comes in. Although I already looked at pattern matching in Elixir before approaching Haskell. Haskell makes it so simple.

Guards are interesting.
Shorthand function syntax.
is_ (hit the tab in iex to find different functions)

Okay, I'm wrapping the Elixir introduction.


I think I need to take a break.

Phoenix Testing and Deployment.

I think I need to get better at using git. I just went through some simple tutorials.

I just had an idea to create a dummy repository for people to make pull requests just to train their git skills.

By the way, I feel like the book has an interesting structure.

Git -> So, I went to dev.to found one simple git tutorial, quickly went through the tutorial. I have to take a note, that I often see among programmers things like hard and difficult (well it is often misleading). Or is it me, who has a technical mindset and don't seem to be bothered with these "difficulties"?

https://dev.to/juni/git-and-github---must-know-commands-to-make-your-first-commit-333c

A link from the author https://git-scm.com/

And here is the answer to the question I had earlier:

For those that haven't used Heroku before, it essentially gives us an easy and free way to deploy our application and see it running live.

Just signed up at Heroku. Let's see what's next.

platform-for-elixir
Is gonna be the name of the app on heroku.
I don't know yet if the names are going to cause problems, because they differ with the github name.

sudo snap install --classic heroku
heroku v7.18.9 from Heroku✓ installed

heroku git:remote -a YOURAPPNAME

This one is confusing because it should either YOURAPPNAME_ON_HEROKU or YOURAPPNAME_ON_GITHUB

it should be: heroku git:remote -a YOURAPPNAME_ON_HEROKU

login heroku
uses the browser. It's a cool way to login.

For elixir_buildpack.config
I need to use
erlang_version=21.0
elixir_version=1.7.3

mix phx.gen.secret
5K7hFVl+mPqhxsGG7jFjFL1XI3ICwV/xg/QSgOXISlWYVkQcFL4cWwrhbApbRWUe

Before tweaking prod.exs I made a backup version prod_backup.exs.

Because it looks different from the book, and probably there were some changes.

My deployment to heroku was unsuccessful.
Will be reading this https://hexdocs.pm/phoenix/heroku.html, but first I will google the error message

error: failed to push some refs to 'https://git.heroku.com/platform-for-elixir.git'

Decided to check the log more carefully on Heroku.

What didn't work:
git push -f heroku master
changing the procfile
phoenix_static_buildpack.config
always_rebuild=true

I found that I can use

https://gigalixir.readthedocs.io/en/latest/

1 instance + 1 database could be used for free.

https://github.com/bitwalker/distillery is also a possible solution.

https://alchemist.camp/episodes/deploy-phoenix-heroku

Found these, worth looking at:

https://github.com/dwyl/learn-heroku/blob/master/elixir-phoenix-app-deployment.md
https://github.com/dwyl/phoenix-chat-example


November 20th, 14:15

Yesterday, it took me whole evening trying to deploy the app to heroku. It was unsuccessful.
I will just continue with the book.

This is another place where things get different:

Player Changesets

def changeset(player, attrs) do
    player
    |> cast(attrs, [:username, :score])
  end

20th November 22:37

I decided to start from the beginning.


I've set up the emmet to work with html.eex

Now, I need to take a note of emmet not expanding the lines vertically.

Again trying to deploy:

Tried this:

line 1: brunch: command not found
https://github.com/gjaldon/heroku-buildpack-phoenix-static/issues/24

didn't work


November 21st. 17:39

After I coordinated with the author he linked me to the update in his book.

Now I have deployed the app to heroku.

It's time to continue. I will try to read the updated version.

Reading updated Phoenix Sign Up chapter.

When I was running the migration https://github.com/elixir-elm-tutorial/elixir-elm-tutorial-book/blob/revisions/manuscript/phoenix_sign_up.md#running-the-migration
I hit en error:
** (RuntimeError) could not find migration runner process for #PID<0.91.0>

The solution:
https://github.com/elixir-ecto/ecto/issues/1298
put https://github.com/elixir-ecto/ecto/issues/1298 inside the change function.

Ah, again, I'm stupid enough not to look closely at the code. It should have been inside the change function!

I finished updated Phoenix Sign Up.

I just noticed that previously on my first attempt I actually skipped this chapter!
I need to pay more attention.


Phoenix Authentication

This sentence is a little tricky

Let's also go ahead and update our create_player/1 test case with the following to since we want users to create accounts with valid username and password fields.

The book refers to the documentation a lot.
And that is the right thing. Because you don't really need to repeat yourself and focus on things that is not in official documentation.

Elixir's documentation is great, by the way.

Reading about keyword lists and maps.

Here is a map:
%{:a => 1, 2 => :b}

But this is also a map
%Platform.Accounts.Player{password: "some password", username: "some username"}

Why the hell the difference between the syntax?

Here's the answer:
When all the keys in a map are atoms, you can use the keyword syntax for convenience:

Now after reading the docs on Elixir this makes much more sense

We're going to make a slight change to remove the password field. We'll need to convert the struct into a map to delete the field, and then we'll merge the fields back together to return the player struct.

def player_fixture(attrs \\ %{}) do
  {:ok, player} =
    attrs
    |> Enum.into(@valid_attrs)
    |> Accounts.create_player()

  player_attrs_map =
    player
    |> Map.from_struct()
    |> Map.delete(:password)

  Map.merge(%Player{}, player_attrs_map)
end

The only one thing that look strange and that I don't get is this one
attrs \ %{} in
def player_fixture(attrs \ %{}) do

Authenticate Function

I got an error:
** (KeyError) key :current_user not found in: %{current_player: nil}

By default my page controller looked like this:

def index(conn, _params) do
render(conn, "index.html")
end

it should be:

def index(conn, _params) do
render conn, "index.html"
end

I'm wondering why no parentheses?
Still no, that doesn't seem to be the problem.

key :current_user not found in: %{current_player: nil}
and localhost:4000
points to

lib/platform_web/controllers/page_controller.ex

  def index(conn, _params) do

    render conn, "index.html"

  end

  defp authenticate(conn, _opts) do

    if conn.assigns.current_user() do

      conn

    else

      conn

      |> put_flash(:error, "You must be signed in to access that page.")

      |> redirect(to: Routes.player_path(conn, :new))

November 22nd, 17:13
Now I decided to retype something of the code. Now, I'm going to start again from the very beginning.

Yesterday, I had an idea, what if I read the phoenix documentation and try to gain the general understanding of the framework.
I'm gonna do that right now.

Just read a bit the overview page
https://hexdocs.pm/phoenix/overview.html


November 23rd 17:57

I have reached the Phoenix Authentication chapter again.

Authentication Plug

If I get a bug and won't be able to fix it. I will just copy the code and try too see if the bug gets fixed. If not I will email the author.

You must be signed in to access that page

Yes, good. Now I don't have the bug I had before.

Signing In
PlayerAuthController.

Session Routing
https://github.com/elixir-elm-tutorial/elixir-elm-tutorial-book/blob/revisions/manuscript/phoenix_authentication.md
I for some reason got a horrible bug without any particular insight why.

So I decided to check my code twice and found that I have a difference between

get "/", PlayerController, :new
resources "/players", PlayerController
resources "/sessions", PlayerSessionController, only: [:new, :create, :delete]

I had
get "/", PlayerController, :index

I changed that to :new
and the error message was even more horrible.
But I changed that to :index again and the mistake went away.

November 24 00:16 Just finished the Phoenix Authentication chapter.


In the book, there is a recommendation to start iex with -S mix
iex -S mix phx.server

I tired to do it without phx.server and it works.
With it the result is the same only you have a phx server running.

def index(conn, _params) do
the conn argument looks like some sort of convention.

What about the @conn
What the does the at sign mean here?

Accounts.get_player!(id)
Why there is an exclamation point?

Phoenix Api and JSON chapter

def render("index.json", %{players: players}) do
    %{data: render_many(players, PlayerApiView, "player.json")}
  end

  def render("show.json", %{player: player}) do
    %{data: render_one(player, PlayerApiView, "player.json")}
  end

why render has the same name? Doesn't that supposed conflict somehow? Or it is just pattern matched?

November 24th 22:24 Just finished the API chapter.


To be honest so far I don't really have the understanding of what I'm doing. Seems like I should get deeper and try to understand.

Seems, like the author really considered the audience to be rubyists familiar with Ruby on Rails. I haven't work with such a framework, so I have no idea what it is.

Gotta learn deeper.


Chapter: Elm Introduction

Then, we'll also use Elm to start building mini games for our platform.

Building games is exciting.

Can't wait for that.

Now, I'm not going to dive into the introduction, I'm skimming this chapter quickly.

main : Html msg
main =
"Hello World"
|> String.toUpper
|> text

This is some nice Elm code.

That's it. I'm done. To the next chapter.


ELM setup.

I just noticed that the book has a nice outline.

November 25th 02:07 Just finished the chapter.


Elm application

Let's update our main function to accept the data from our model, and our application should be back to a fully functioning state. We'll post the full code example here and then follow the data to get a better understanding of how it flows through our functions and how it all fits together (also note that we removed our firstGameMaybe and firstGameTitle functions now that we're mapping through all the titles):

I don't see how the model ends up in the gameListItem function.

Okay, I got it. It's in the main function. There is call to a gamesIndex function with the model as an argument.

Now I see clearly what is what. At first there was a demonstration of the maybe type on calling a first item in the list and then there is mapping of a whole list.

And, now I have a question. Can this code be refactored with piping?

November 25th 23:30 Finishing the Elm application chapter.


Elm Architecture

I see Subscriptions so I immediately set my expectations to see more about Cmd.
This where I lack in understanding.

Looking forward to that part.

November 27th Finished at 00:49

Have been learning some Haskell. Slowly finishing the FP course on edx.org.


And now to the ELM api data chapter.

Decode.field "description" Decode.string
Why do we use Decode.field if we use Decode.string anyway?

02:38 I'm so tired of the computer, and I began wasting time on twitter.
Turning off the computer and going to lie down and just enjoy my being.

November 27th continuing with elm api data chapter.
17:13

Okay I have some problem with Http.
Should I expose Http?
import Http exposing (..)

I cannot find a Http.send variable:

62| |> Http.send FetchGamesList
^^^^^^^^^
The Http module does not expose a send variable. These names seem close
though:

I emailed the author about the issue. I tried to work it out on my own. I couldn't. As it turned out the Http.get was changed. So instead I will go through the elm's official guide. Who knows maybe I will find the solution by myself.


Top comments (0)