Improve migration and model. Debugging and console.

The current state of migration and model:

Migration:

defmodule WorthIt.Repo.Migrations.CreateUser do
  use Ecto.Migration

  def change do
    create table(:users) do
      add :email, :string, null: false
      add :encrypted_password, :string, null: false

      timestamps()
    end

    create unique_index(:users, [:email])
  end
end

I changed migration instead of adding new migrate because of it just first migration and there are no data inside the database. We can easy use:

mix ecto.drop
mix ecto.create
mix ecto.migrate

Modified model:

defmodule WorthIt.User do
  use WorthIt.Web, :model

  schema "users" do
    field :email, :string
    field :encrypted_password, :string
    field :password, :string, virtual: true

    timestamps()
  end

  @required_fields ~w(email password)

  @doc """
  Builds a changeset based on the `struct` and `params`.
  """
  def changeset(struct, params \\ %{}) do
    struct
    |> cast(params, @required_fields)
    |> validate_required([:email, :password])
    |> validate_format(:email, ~r/@/)
    |> validate_length(:password, min: 5)
    |> unique_constraint(:email, message: "Email already taken")
    |> generate_encrypted_password
  end

  defp generate_encrypted_password(current_changeset) do
    case current_changeset do
      %Ecto.Changeset{valid?: true, changes: %{password: password}} ->
        put_change(current_changeset, :encrypted_password, Comeonin.Bcrypt.hashpwsalt(password))
      _ ->
        current_changeset
    end
  end
end

As we can see here, I changed validation and added ability to create an encrypted password.
So we need fill email and password and password will be encrypted. I used here comeonein library.

Debugging:

For debugging we can simply use:

require IEx
IEx.pry

So when we want to check what is going on in the generate_encrypted_password method we need to do something like:

defp generate_encrypted_password(current_changeset) do
    require IEx
    IEx.pry
    case current_changeset do
      %Ecto.Changeset{valid?: true, changes: %{password: password}} ->
        put_change(current_changeset, :encrypted_password, Comeonin.Bcrypt.hashpwsalt(password))
      _ ->
        current_changeset
    end
  end

Console:

I like to play with console – that makes me sure I understand the code.

To run console:

iex -S mix phoenix.server

For trying to create a new user changeset.

WorthIt.User.changeset(%WorthIt.User{}, %{})

It will cause response errors because we have a required validation:

#Ecto.Changeset<action: nil, changes: %{},
errors: [email: {"can't be blank", [validation: :required]},
password: {"can't be blank", [validation: :required]}], data: #WorthIt.User<>,
valid?: false>

We can use here also alias

alias WorthIt.User
User.changeset(%User{}, %{})

That give us the same errors

If we want create record we need valid params, so for example it will be:

changeset = User.changeset(%User{}, %{email: "email@email.com", password: "mypassword"})

It will give us valid changeset with encrypted password:

#Ecto.Changeset<action: nil,
changes: %{email: "email@email.com",
encrypted_password: "$2b$12$hJUmnZQO5c/2YAhpA2pnDeUXeKmK/TU38L689SehuKg2mWtOnuJVa",
password: "mypassword"}, errors: [], data: #WorthIt.User<>, valid?: true>

Now we try to push it to the database with Ecto Repo.

WorthIt.Repo.insert(changeset)

We will get this:

[debug] QUERY OK db=3.9ms
INSERT INTO "users" ("email","encrypted_password","inserted_at","updated_at") VALUES ($1,$2,$3,$4) RETURNING "id" ["email@email.com", "$2b$12$hJUmnZQO5c/2YAhpA2pnDeUXeKmK/TU38L689SehuKg2mWtOnuJVa", {{2017, 3, 26}, {21, 24, 55, 378315}}, {{2017, 3, 26}, {21, 24, 55, 381994}}]
{:ok,
 %WorthIt.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
 email: "email@email.com",
 encrypted_password: "$2b$12$hJUmnZQO5c/2YAhpA2pnDeUXeKmK/TU38L689SehuKg2mWtOnuJVa",
 id: 4, inserted_at: ~N[2017-03-26 21:24:55.378315], password: "mypassword",
 updated_at: ~N[2017-03-26 21:24:55.381994]}}

To be sure we have it in database we will use Enum count method and Ecto Repo.

Enum.count(WorthIt.Repo.all(User))

That will give us:

[debug] QUERY OK source="users" db=1.1ms
SELECT u0."id", u0."email", u0."encrypted_password", u0."inserted_at", u0."updated_at" FROM "users" AS u0 []
1

And in PostgreSQL database:

psql worth_it_dev
SELECT * FROM users;

There is a record with email and encrypted password.

Advertisements

Migration and Ecto model

Simple user migration:

defmodule WorthIt.Repo.Migrations.CreateUser do
 use Ecto.Migration

 def change do
 create table(:users) do
 add :email, :string
 add :crypted_password, :string
 add :password, :string, virtual: true

 timestamps()
 end

 end
end

I added here three columns (one virtual)

Simple user model:

defmodule WorthIt.User do
 use WorthIt.Web, :model

 schema "users" do
 field :email, :string
 field :password, :string

 timestamps()
 end

 @doc """
 Builds a changeset based on the `struct` and `params`.
 """
 def changeset(struct, params \\ %{}) do
 struct
 |> cast(params, [:email, :password])
 |> validate_required([:email, :password])
 |> validate_length(:password, min: 5)
 |> validate_format(:email, ~r/@/)
 |> unique_constraint(:email)
 end
end

There are some validations:
– email and password are require
– password must have minimum 5 characters
– email must have ‘@’ and be unique

In the future, I will add here the code to crypt the password (currently is not safe).

commit source

Create repository with database configuration

To generate Phoenix App, we need to use mix phoenix.new worth_it

After that, I wanted to create secrets related to the database.
I created /config/dev.secret.exs and included secret and imported it inside /config/dev.exs.

Also added information in README that we need to create this file and configure it with edited .gitignore file. All changes we can see in worth-it-backend

When someone needs to create an environmental variable, there is a library called figaro-elixir.

Configure environment

I am using Mac OS X El Capitan.

My workflow is setting virtual machine with all necessary libraries per project.
In my virtual machine, I am using Ubuntu (currently 16.04).

I can easy manage my projects this way and communicate by using SSH and VIM.

Configuration for Worth IT:

– Elixir 1.3.2
– Erlang 19
– PostgreSQL 9.5.4

Useful links:
http://www.phoenixframework.org/docs/installation
https://www.erlang-solutions.com/resources/download.html

Preparing to work

The main thing in creating an application is to have a general plan and split it into smaller parts.

So the general plan is:

  1. Landing page (FE)
  2. Registration (BE, FE)
  3. Login (BE, FE)
  4. Main page (FE)
  5. Ability to create category inside main page (BE, FE)
  6. Ability to create items (BE, FE)
  7. Ability to display items and filter it inside main page (BE, FE)

With general technologies:

Backend(BE):

  • Elixir (Phoenix)

Frontend(FE):

  • JavaScript (Angular 2)

While to work on the project I will write more about each backend part.

Initial post

Initial post

Hello everyone,

This blog was created for polish programming competition called “Daj Się Poznać 2017!” – in short DSP2017.

I will public here information about backend application that I want to build called “Worth IT”. It is related to frontend application which will be built by another programmer in https://worthitfrontend.wordpress.com/.

My goal is to build simple backend application in Elixir & Phoenix.