Do you want to pick up from where you left of?
Take me there

Basics

Το Ecto είναι ένα επίσημο Elixir project το οποίο παρέχει μια επικάλυψη της βάσης δεδομένων και μια ενσωματωμένη γλώσσα ερωτημάτων. Με το Ecto είμαστε σε θέση να δημιουργούμε μετατροπές, να ορίζουμε σχήματα, να εισάγουμε και επεξεργαζόμαστε εγγραφές και να δημιουργούμε ερωτήματα προς αυτές.

Προσαρμογείς

Το Ecto υποστηρίζει διαφορετικές βάσεις δεδομένων μέσα από τη χρήση προσαρμογέων. Μερικά παραδείγματα προσαρμογέων είναι:

Για αυτό το μάθημα θα ρυθμίσουμε το Ecto να χρησιμοποιήσει τον προσαρμογέα PostgreSQL.

Ξεκινώντας

Στα πλαίσια αυτού του μαθήματος θα καλύψουμε τρία μέρη του Ecto:

Για να ξεκινήσουμε θα δημιουργήσουμε ένα νέο project με δέντρο επιτήρησης.

mix new friends --sup
cd friends

Προσθέστε τα πακέτα εξαρτήσεων ecto_sql και postgrex στο mix.exs αρχείο μας:

defp deps do
  [
    {:ecto_sql, "~> 3.2"},
    {:postgrex, "~> 0.15"}
  ]
end

Κατεβάστε τις εξαρτήσεις με τη χρήση:

mix deps.get

Δημιουργία ενός Αποθετηρίου

Ένα αποθετήριο στο Ecto δείχνει σε μια πηγή δεδομένων όπως είναι μια βάση δεδομένων Postgres. Όλες οι επικοινωνίες με τη βάση δεδομένων θα πραγματοποιούνται με τη χρήση αυτού του αποθετηρίου.

Ορίστε ένα αποθετήριο τρέχοντας την εντολή:

mix ecto.gen.repo -r Friends.Repo

Αυτή η εντολή θα δημιουργήσει τις απαραίτητες ρυθμίσεις στο αρχείο config/config.exs για τη σύνδεση στη βάση δεδομένων, συμπεριλαμβανομένου του προσαρμογέα που θα χρησιμοποιηθεί. Αυτές είναι οι ρυθμίσεις για την εφαρμογή μας Friends:

config :friends, Friends.Repo,
  database: "friends_repo",
  username: "postgres",
  password: "",
  hostname: "localhost"

Οι παραπάνω γραμμές ορίζουν πως το Ecto θα συνδεθεί στη βάση δεδομένων. Μπορεί να χρειαστεί να ρυθμίσετε τη βάση δεδομένων σας με τα αντίστοιχα διακριτικά. Επίσης, δημιουργεί μια ενότητα Friends.Repo στο αρχείο lib/friends/repo.ex.

defmodule Friends.Repo do
  use Ecto.Repo, 
    otp_app: :friends,
    adapter: Ecto.Adapters.Postgres
end

Θα χρησιμοποιήσουμε την ενότητα Friends.Repo για να στέλνουμε ερωτήματα στη βάση δεδομένων. Επίσης λέμε σε αυτή την ενότητα να βρει τις πληροφορίες ρύθμισης στην εφαρμογή Elixir :friends και ότι επιλέγουμε τον προσαρμογέα Ecto.Adapters.Postgres.

Στη συνέχεια, θα ρυθμίσουμε την Friends.Repo σαν επιτηρητή μέσα στο δέντρο επιτήρησης της εφαρμογής μας στο lib/friends/application.ex. Αυτό θα ξεκινήσει τη διεργασία Ecto όταν ξεκινάει η εφαρμογή μας.

  def start(_type, _args) do
    # List all child processes to be supervised
    children = [
      Friends.Repo,
    ]
  ...

Μετά από αυτό θα χρειαστούμε την παρακάτω γραμμή στο αρχείο config/config.exs:

config :friends, ecto_repos: [Friends.Repo]

Αυτό θα επιτρέψει στην εφαρμογή μας να τρέξει εντολές ecto από τη γραμμή εντολών.

Μόλις τελειώσαμε τη ρύθμιση του αποθετηρίου μας! Τώρα μπορούμε να δημιουργήσουμε τη βάση δεδομένων μέσα στην Postgres με αυτή την εντολή:

mix ecto.create

Το Ecto θα χρησιμοποιήσει τις πληροφορίες στο αρχείο config/config.exs για να προσδιορίσει πως να συνδεθεί στην Postgres και τι όνομα να δώσει στη βάση δεδομένων.

Αν δείτε σφάλματα, βεβαιωθείτε ότι οι πληροφορίες ρύθμισης είναι σωστές και ότι η postgres διεργασία στο σύστημά σας τρέχει.

Μετατροπές

Για να δημιουργήσετε και να αλλάξετε πίνακες στη βάση δεδομένων, το Ecto μας παρέχει τις μετατροπές. Κάθε μετατροπή περιγράφει ένα σύνολο δράσεων που θα γίνουν στη βάση δεδομένων μας, όπως ποιον πίνακα να δημιουργήσει ή να αλλάξει.

Από τη στιγμή που η βάση δεδομένων μας δεν έχει πίνακες ακόμα, θα χρειαστούμε μια μετατροπή για να προσθέσουμε έναν. Η συνθήκη στο Ecto είναι να ονοματίζουμε τους πίνακές μας στον πλυθηντικό. Για την εφαρμογή μας, αν θέλουμε να εκφράσουμε μια οντότητα person στη βάση δεδομένων, θα χρειαστούμε ένα πίνακα people.

Ο καλύτερος τρόπος να δημιουργήσουμε μετατροπές είναι η εργασία mix ecto.gen.migration <όνομα μετατροπής>, έτσι στην περίπτωσή μας θα χρησιμοποιήσουμε:

mix ecto.gen.migration create_people

Αυτή η εντολή θα δημιουργήσει ένα νέο αρχείο στο φάκελο priv/repo/migrations που θα περιέχει την χρονική σήμανση στο όνομα του. Αν περιηγηθούμε στο φάκελο και ανοίξουμε τη μετατροπή θα πρέπει να δούμε κάτι σαν αυτό:

defmodule Friends.Repo.Migrations.CreatePeople do
  use Ecto.Migration

  def change do

  end
end

Ας ξεκινήσουμε αλλάζοντας τη συνάρτηση change/0 για να δημιουργήσουμε ένα νέο πίνακα people με τα πεδία name και age:

defmodule Friends.Repo.Migrations.CreatePeople do
  use Ecto.Migration

  def change do
    create table(:people) do
      add :name, :string, null: false
      add :age, :integer, default: 0
    end
  end
end

Όπως μπορείτε να δείτε ορίσαμε επίσης τους τύπους δεδομένων των πεδίων. Επιπρόσθετα, συμπεριλάβαμε τις επιλογές null: false και default: 0.

Μεταβείτε στο τερματικό και τρέξτε τη μετατροπή:

mix ecto.migrate

Σχήματα

Τώρα που δημιουργήσαμε τον αρχικό πίνακα μας πρέπει να πούμε στο Ecto περισσότερα για αυτόν, μέρος του οποίου γίνεται μέσα από τα σχήματα. Ένα σχήμα είναι μια ενότητα που ορίζει αντιστοιχίσεις στα πεδία του υποκείμενου πίνακα στη βάση δεδομένων.

Παρόλο που το Ecto προτιμά τον πλυθηντικό στα ονόματα πινάκων, το σχήμα τυπικά είναι στον ενικό, έτσι θα δημιουργήσουμε ένα σχήμα Person το οποίο θα συντροφεύει τον πίνακά μας.

Ας δημιουργήσουμε το σχήμα μας στο lib/friends/person.ex:

defmodule Friends.Person do
  use Ecto.Schema

  schema "people" do
    field :name, :string
    field :age, :integer, default: 0
  end
end

Εδώ μπορούμε να δούμε ότι η ενότητα Friends.Person λέει στο Ecto ότι αυτό το σχήμα αναφέρεται στον πίνακα people και ότι έχει δύο στήλες: name, το οποίο είναι αλφαριθμητικό και age, το οποίο είναι ακέραιος με προκαθορισμένη τιμή το 0.

Ας ρίξουμε μια ματιά στο σχήμα μας ανοίγοντας το στο iex -S mix και δημιουργώντας ένα νέο άτομο:

iex> %Friends.Person{}
%Friends.Person{age: 0, name: nil}

Όπως θα περιμέναμε παίρνουμε μια δομή Person με την προκαθορισμένη τιμή εφαρμοσμένη στο πεδίο age. Τώρα ας δημιουργήσουμε ένα “πραγματικό” άτομο:

iex> person = %Friends.Person{name: "Tom", age: 11}
%Friends.Person{age: 11, name: "Tom"}

Από τη στιγμή που τα σχήματα είναι απλά δομές, μπορούμε να αλληλεπιδράσουμε με τα δεδομένα μας όπως έχουμε συνηθίσει:

iex> person.name
"Tom"
iex> Map.get(person, :name)
"Tom"
iex> %{name: name} = person
%Friends.Person{age: 11, name: "Tom"}
iex> name
"Tom"

Όμοια, μπορούμε να αναβαθμίσουμε τα σχήματά μας όπως θα κάναμε με οποιοδήποτε άλλο χάρτη ή δομή στην Elixir:

iex> %{person | age: 18}
%Friends.Person{age: 18, name: "Tom"}
iex> Map.put(person, :name, "Jerry")
%Friends.Person{age: 18, name: "Jerry"}

Στο επόμενο μάθημά μας για τα Σετ Αλλαγών, θα δούμε πως να επιβεβαιώσουμε τις αλλαγές δεδομένων μας και τελικά πως να τις οριστικοποιήσουμε στη βάση δεδομένων μας.

Έπιασες λάθος ή θέλεις να συνεισφέρεις στο μάθημα; Επεξεργαστείτε αυτό το μάθημα στο GitHub!