ActiveRecord vs. Ecto Teil Zwei

Dies ist der zweite Teil der Reihe „ActiveRecord vs. Ecto“, in der Batman und Batgirl um die Abfrage von Datenbanken streiten und wir Äpfel und Orangen vergleichen.

Nachdem Sie sich mit den Datenbankschemata und Migrationen in ActiveRecord vs. Ecto, Teil 1, befasst haben, wird in diesem Beitrag erläutert, wie sowohl ActiveRecord als auch Ecto es Entwicklern ermöglichen, die Datenbank abzufragen, und wie sich ActiveRecord und Ecto vergleichen, wenn sie dieselben Anforderungen erfüllen. Unterwegs werden wir auch die Identität von Batgirl von 1989 bis 2011 herausfinden.

Seed-Daten

Lass uns anfangen! Nehmen Sie an, dass die Benutzer und die Rechnungstabellen auf der Grundlage der im ersten Beitrag dieser Reihe definierten Datenbankstruktur die folgenden Daten gespeichert haben:

Benutzer

* Das Feld created_at von ActiveRecord trägt standardmäßig den Namen insert_at in Ecto.

Rechnungen

* Das Feld created_at von ActiveRecord trägt standardmäßig den Namen insert_at in Ecto.

In diesem Beitrag durchgeführte Abfragen setzen voraus, dass die oben genannten Daten in der Datenbank gespeichert sind. Denken Sie also beim Lesen dieser Informationen daran.

Suchen Sie das Objekt mit seinem Primärschlüssel

Beginnen wir mit dem Abrufen eines Datensatzes aus der Datenbank mithilfe seines Primärschlüssels.

Aktiver Rekord

irb (main): 001: 0> User.find (1) User Load (0,4 ms) SELECT "users". * FROM "users" WHERE "users". "id" = $ 1 LIMIT $ 2 [[["id", 1 ], ["LIMIT", 1]] => # 

Ecto

iex (3)> Repo.get (Benutzer, 1)
[debug] QUERY OK source = "users" db = 5.2ms decode = 2.5ms queue = 0.1ms
SELECT u0. "Id", u0. "Full_name", u0. "Email", u0. "Inserted_at", u0. "Updated_at" FROM "users" AS u0 WHERE (u0. "Id" = $ 1) [1]
% Financex.Accounts.User {
  __meta__: # Ecto.Schema.Metadata <: loaded, "users">,
  E-Mail: "[email protected]",
  vollständiger_name: "Bette Kane",
  id: 1,
  inserted_at: ~ N [2018-01-01 10: 01: 00.000000],
  Rechnungen: # Ecto.Association.NotLoaded ,
  updated_at: ~ N [2018-01-01 10: 01: 00.000000]
}

Vergleich

Beide Fälle sind sehr ähnlich. ActiveRecord verwendet die Methode find class der Benutzermodellklasse. Dies bedeutet, dass jede untergeordnete ActiveRecord-Klasse eine eigene Find-Methode enthält.

Ecto verfolgt einen anderen Ansatz und stützt sich auf das Repository-Konzept als Vermittler zwischen der Zuordnungsebene und der Domäne. Wenn Sie Ecto verwenden, hat das Benutzermodul keine Kenntnisse darüber, wie Sie sich selbst finden können. Diese Verantwortung liegt im Repo-Modul vor, das sie dem darunter liegenden Datenspeicher zuordnen kann, in unserem Fall Postgres.

Beim Vergleich der SQL-Abfrage selbst können wir einige Unterschiede feststellen:

  • ActiveRecord lädt alle Felder (Benutzer. *), Während Ecto nur die in der Schemadefinition aufgelisteten Felder lädt.
  • ActiveRecord enthält ein LIMIT 1 für die Abfrage, Ecto dagegen nicht.

Abrufen aller Elemente

Gehen wir noch einen Schritt weiter und laden Sie alle Benutzer aus der Datenbank.

Aktiver Rekord

irb (main): 001: 0> User.all User Load (0,5 ms) SELECT "users". * FROM "users" LIMIT $ 1 [["LIMIT", 11]] => # , # , # , # ]>

Ecto

iex (4)> Repo.all (Benutzer)
[debug] QUERY OK source = "users" db = 2,8 ms decodieren = 0,2 ms queue = 0,2 ms
SELECT u0. "Id", u0. "Full_name", u0. "Email", u0. "Inserted_at", u0. "Updated_at" FROM "users" AS u0 []
[
  % Financex.Accounts.User {
    __meta__: # Ecto.Schema.Metadata <: loaded, "users">,
    E-Mail: "[email protected]",
    vollständiger_name: "Bette Kane",
    id: 1,
    inserted_at: ~ N [2018-01-01 10: 01: 00.000000],
    Rechnungen: # Ecto.Association.NotLoaded ,
    updated_at: ~ N [2018-01-01 10: 01: 00.000000]
  },
  % Financex.Accounts.User {
    __meta__: # Ecto.Schema.Metadata <: loaded, "users">,
    email: "[email protected]",
    vollständiger_name: "Barbara Gordon",
    id: 2,
    inserted_at: ~ N [2018-01-02 10: 02: 00.000000],
    Rechnungen: # Ecto.Association.NotLoaded ,
    updated_at: ~ N [2018-01-02 10: 02: 00.000000]
  },
  % Financex.Accounts.User {
    __meta__: # Ecto.Schema.Metadata <: loaded, "users">,
    E-Mail: "[email protected]",
    vollständiger_name: "Cassandra Cain",
    id: 3,
    inserted_at: ~ N [2018-01-03 10: 03: 00.000000],
    Rechnungen: # Ecto.Association.NotLoaded ,
    updated_at: ~ N [2018-01-03 10: 03: 00.000000]
  },
  % Financex.Accounts.User {
    __meta__: # Ecto.Schema.Metadata <: loaded, "users">,
    email: "[email protected]",
    vollständiger_name: "Stephanie Brown",
    id: 4,
    inserted_at: ~ N [2018-01-04 10: 04: 00.000000],
    Rechnungen: # Ecto.Association.NotLoaded ,
    updated_at: ~ N [2018-01-04 10: 04: 00.000000]
  }
]

Vergleich

Es folgt genau dem gleichen Muster wie im vorherigen Abschnitt. ActiveRecord verwendet die Methode all class und Ecto verwendet das Repository-Muster, um die Datensätze zu laden.

Es gibt wieder einige Unterschiede bei den SQL-Abfragen:

Abfrage mit Bedingungen

Es ist sehr unwahrscheinlich, dass wir alle Datensätze aus einer Tabelle abrufen müssen. Eine häufige Anforderung ist die Verwendung von Bedingungen, um die zurückgegebenen Daten herauszufiltern.

Verwenden wir dieses Beispiel, um alle Rechnungen aufzulisten, die noch zu bezahlen sind (WHERE paid_at IS NULL).

Aktiver Rekord

irb (main): 024: 0> Invoice.where (paid_at: nil) Rechnungslast (18,2 ms) SELECT "Rechnungen". * FROM "Rechnungen" WHERE "Rechnungen". "paid_at" IS NULL LIMIT $ 1 [["LIMIT" , 11]] => # , # ]>

Ecto

iex (19)> where (Invoice, [i], is_nil (i.paid_at)) |> Repo.all ()
[debug] QUERY OK source = "Rechnungen" db = 20.2ms
SELECT i0. "Id", i0. "Payment_method", i0. "Paid_at", i0. "User_id", i0. "Inserted_at", i0. "Updated_at" FROM "invoices" AS i0 WHERE (i0. "Paid_at" IS NULL) []
[
  % Financex.Accounts.Invoice {
    __meta__: # Ecto.Schema.Metadata <: loaded, "invoices">,
    id: 3,
    inserted_at: ~ N [2018-01-04 08: 00: 00.000000],
    paid_at: nil,
    zahlungsmethode: nil,
    updated_at: ~ N [2018-01-04 08: 00: 00.000000],
    Benutzer: # Ecto.Association.NotLoaded ,
    user_id: 3
  },
  % Financex.Accounts.Invoice {
    __meta__: # Ecto.Schema.Metadata <: loaded, "invoices">,
    id: 4,
    inserted_at: ~ N [2018-01-04 08: 00: 00.000000],
    paid_at: nil,
    zahlungsmethode: nil,
    updated_at: ~ N [2018-01-04 08: 00: 00.000000],
    Benutzer: # Ecto.Association.NotLoaded ,
    user_id: 4
  }
]

Vergleich

In beiden Beispielen wird das Schlüsselwort where verwendet, das eine Verbindung zur SQL-WHERE-Klausel darstellt. Obwohl die generierten SQL-Abfragen sehr ähnlich sind, gibt es einige wichtige Unterschiede in der Art und Weise, wie beide Tools dorthin gelangen.

ActiveRecord wandelt das Argument paid_at: nil automatisch in die SQL-Anweisung paid_at IS NULL um. Um mit Ecto zur gleichen Ausgabe zu gelangen, müssen Entwickler ihre Absichten genauer erläutern, indem sie is_nil () aufrufen.

Ein weiterer hervorzuhebender Unterschied ist das "reine" Verhalten der Funktion in Ecto. Wenn Sie die where-Funktion alleine aufrufen, interagiert sie nicht mit der Datenbank. Die Rückgabe der where-Funktion ist eine Ecto.Query-Struktur:

iex (20)> where (Invoice, [i], is_nil (i.paid_at))
# Ecto.Query 

Die Datenbank wird nur berührt, wenn die Funktion Repo.all () aufgerufen wird und die Struktur Ecto.Query als Argument übergeben wird. Dieser Ansatz ermöglicht das Erstellen von Abfragen in Ecto, das im nächsten Abschnitt behandelt wird.

Abfragestruktur

Einer der mächtigsten Aspekte von Datenbankabfragen ist die Zusammensetzung. Es beschreibt eine Abfrage auf eine Weise, die mehr als eine einzelne Bedingung enthält.

Wenn Sie unformatierte SQL-Abfragen erstellen, bedeutet dies wahrscheinlich, dass Sie eine Art Verkettung verwenden. Stellen Sie sich vor, Sie haben zwei Bedingungen:

  1. not_paid = 'paid_at IST NICHT NULL'
  2. paid_with_paypal = 'payment_method = "Paypal"'

Um diese beiden Bedingungen mit Raw-SQL zu kombinieren, müssen Sie sie mit etwas ähnlichem verketten:

SELECT * FROM Rechnungen WHERE # {not_paid} AND # {paid_with_paypal}

Zum Glück haben ActiveRecord und Ecto eine Lösung dafür.

Aktiver Rekord

irb (main): 003: 0> Invoice.where.not (paid_at: nil) .where (payment_method: "Paypal") Laden der Rechnung (8.0ms) SELECT "invoices". * FROM "invoices" WHERE "invoices". " paid_at "IS NOT NULL AND" invoices "." payment_method "= $ 1 LIMIT $ 2 [[" payment_method "," Paypal "], [" LIMIT ", 11]] => # ]>

Ecto

iex (6)> Invoice |> where ([i], not is_nil (i.paid_at)) |> where ([i], i.payment_method == "Paypal") |> Repo.all ()
[debug] QUERY OK source = "Rechnungen" db = 30.0ms decode = 0.6ms queue = 0.2ms
SELECT i0. "Id", i0. "Payment_method", i0. "Paid_at", i0. "User_id", i0. "Inserted_at", i0. "Updated_at" FROM "invoices" AS i0 WHERE (NOT (i0. "Paid_at "IS NULL)) AND (i0." Payment_method "= 'Paypal') []
[
  % Financex.Accounts.Invoice {
    __meta__: # Ecto.Schema.Metadata <: loaded, "invoices">,
    id: 2,
    inserted_at: ~ N [2018-01-03 08: 00: 00.000000],
    paid_at: #DateTime <2018-02-01 08: 00: 00.000000Z>,
    zahlungsmethode: "Paypal",
    updated_at: ~ N [2018-01-03 08: 00: 00.000000],
    Benutzer: # Ecto.Association.NotLoaded ,
    user_id: 2
  }
]

Vergleich

Beide Fragen beantworten die gleiche Frage: "Welche Rechnungen wurden bezahlt und mit Paypal bezahlt?".

Wie bereits erwartet, bietet ActiveRecord eine präzisere Methode zum Erstellen der Abfrage (für dieses Beispiel), während Ecto von den Entwicklern einen höheren Aufwand für das Schreiben der Abfrage verlangt. Wie üblich ist Batgirl (das verwaiste, stumme Mädchen mit der Cassandra Cain-Identität) oder Activerecord nicht so wortreich.

Lassen Sie sich nicht von der Ausführlichkeit und offensichtlichen Komplexität der oben gezeigten Ecto-Abfrage täuschen. In einer realen Umgebung würde diese Abfrage so umgeschrieben, dass sie wie folgt aussieht:

Rechnung
|> where ([i], nicht is_nil (i.paid_at))
|> where ([i], i.payment_method == "Paypal")
|> Repo.all ()

Unter diesem Gesichtspunkt macht die Kombination der "reinen" Aspekte der Funktion, bei der Datenbankoperationen nicht von selbst ausgeführt werden, mit dem Pipe-Operator die Abfragekomposition in Ecto wirklich sauber.

Bestellung

Die Bestellung ist ein wichtiger Aspekt einer Anfrage. Entwickler können damit sicherstellen, dass ein bestimmtes Abfrageergebnis einer bestimmten Reihenfolge entspricht.

Aktiver Rekord

irb (main): 002: 0> Invoice.order (created_at:: desc) Rechnungslast (1,5 ms) SELECT "Rechnungen". * FROM "Rechnungen" ORDER BY "Rechnungen". "created_at" DESC LIMIT $ 1 [["LIMIT ", 11]] => # , # , # , # ]>

Ecto

iex (6)> order_by (Rechnung, desc:: inserted_at) |> Repo.all ()
[debug] QUERY OK source = "Rechnungen" db = 19.8ms
SELECT i0. "Id", i0. "Payment_method", i0. "Paid_at", i0. "User_id", i0. "Inserted_at", i0. "Updated_at" FROM "invoices" AS i0 ORDER BY i0. "Inserted_at" DESC []
[
  % Financex.Accounts.Invoice {
    __meta__: # Ecto.Schema.Metadata <: loaded, "invoices">,
    id: 3,
    inserted_at: ~ N [2018-01-04 08: 00: 00.000000],
    paid_at: nil,
    zahlungsmethode: nil,
    updated_at: ~ N [2018-01-04 08: 00: 00.000000],
    Benutzer: # Ecto.Association.NotLoaded ,
    user_id: 3
  },
  % Financex.Accounts.Invoice {
    __meta__: # Ecto.Schema.Metadata <: loaded, "invoices">,
    id: 4,
    inserted_at: ~ N [2018-01-04 08: 00: 00.000000],
    paid_at: nil,
    zahlungsmethode: nil,
    updated_at: ~ N [2018-01-04 08: 00: 00.000000],
    Benutzer: # Ecto.Association.NotLoaded ,
    user_id: 4
  },
  % Financex.Accounts.Invoice {
    __meta__: # Ecto.Schema.Metadata <: loaded, "invoices">,
    id: 2,
    inserted_at: ~ N [2018-01-03 08: 00: 00.000000],
    paid_at: #DateTime <2018-02-01 08: 00: 00.000000Z>,
    zahlungsmethode: "Paypal",
    updated_at: ~ N [2018-01-03 08: 00: 00.000000],
    Benutzer: # Ecto.Association.NotLoaded ,
    user_id: 2
  },
  % Financex.Accounts.Invoice {
    __meta__: # Ecto.Schema.Metadata <: loaded, "invoices">,
    id: 1,
    inserted_at: ~ N [2018-01-02 08: 00: 00.000000],
    paid_at: #DateTime <2018-02-01 08: 00: 00.000000Z>,
    payment_method: "Kreditkarte",
    updated_at: ~ N [2018-01-02 08: 00: 00.000000],
    Benutzer: # Ecto.Association.NotLoaded ,
    user_id: 1
  }
]

Vergleich

Das Hinzufügen der Reihenfolge zu einer Abfrage ist in beiden Tools unkompliziert.

Obwohl im Ecto-Beispiel eine Rechnung als erster Parameter verwendet wird, akzeptiert die order_by-Funktion auch Ecto.Query-Strukturen, wodurch die order_by-Funktion in Kompositionen verwendet werden kann, z.

Rechnung
|> where ([i], nicht is_nil (i.paid_at))
|> where ([i], i.payment_method == "Paypal")
|> order_by (desc:: inserted_at)
|> Repo.all ()

Begrenzen

Was wäre eine Datenbank ohne Limit? Ein Disaster. Zum Glück helfen ActiveRecord und Ecto dabei, die Anzahl der zurückgegebenen Datensätze zu begrenzen.

Aktiver Rekord

irb (main): 004: 0> Invoice.limit (2)
Rechnungslast (0,2 ms) SELECT "Rechnungen". * FROM "Rechnungen" LIMIT $ 1 [["LIMIT", 2]]
=> # , # ]>

Ecto

iex (22)> limit (Invoice, 2) |> Repo.all ()
[debug] QUERY OK source = "Rechnungen" db = 3.6ms
SELECT i0. "Id", i0. "Payment_method", i0. "Paid_at", i0. "User_id", i0. "Inserted_at", i0. "Updated_at" FROM "invoices" AS i0 LIMIT 2 []
[
  % Financex.Accounts.Invoice {
    __meta__: # Ecto.Schema.Metadata <: loaded, "invoices">,
    id: 1,
    inserted_at: ~ N [2018-01-02 08: 00: 00.000000],
    paid_at: #DateTime <2018-02-01 08: 00: 00.000000Z>,
    payment_method: "Kreditkarte",
    updated_at: ~ N [2018-01-02 08: 00: 00.000000],
    Benutzer: # Ecto.Association.NotLoaded ,
    user_id: 1
  },
  % Financex.Accounts.Invoice {
    __meta__: # Ecto.Schema.Metadata <: loaded, "invoices">,
    id: 2,
    inserted_at: ~ N [2018-01-03 08: 00: 00.000000],
    paid_at: #DateTime <2018-02-01 08: 00: 00.000000Z>,
    zahlungsmethode: "Paypal",
    updated_at: ~ N [2018-01-03 08: 00: 00.000000],
    Benutzer: # Ecto.Association.NotLoaded ,
    user_id: 2
  }
]

Vergleich

Sowohl ActiveRecord als auch Ecto können die Anzahl der von einer Abfrage zurückgegebenen Datensätze begrenzen.

Das Limit von Ecto funktioniert ähnlich wie order_by und eignet sich für Abfragezusammenstellungen.

Verbände

ActiveRecord und Ecto verfolgen unterschiedliche Ansätze im Umgang mit Assoziationen.

Aktiver Rekord

In ActiveRecord können Sie jede in einem Modell definierte Assoziation verwenden, ohne etwas Besonderes tun zu müssen, zum Beispiel:

irb (main): 012: 0> user = User.find (2) User Load (0,3 ms) SELECT "users". * FROM "users" WHERE "users". "id" = $ 1 LIMIT $ 2 [["id" , 2], ["LIMIT", 1]] => #  irb (main): 013: 0> user.invoices Invoice Load (0,4 ms) SELECT" Rechnungen ". * FROM" Rechnungen "WHERE" Rechnungen " . "user_id" = $ 1 LIMIT $ 2 [["user_id", 2], ["LIMIT", 11]] => # ] >

Das obige Beispiel zeigt, dass wir beim Aufruf von user.invoices eine Liste der Benutzerrechnungen erhalten können. Dabei hat ActiveRecord automatisch die Datenbank abgefragt und die Rechnungen geladen, die dem Benutzer zugeordnet sind. Während dieser Ansatz die Dinge einfacher macht, da weniger Code geschrieben werden muss oder zusätzliche Schritte erforderlich sind, kann dies ein Problem sein, wenn Sie mehrere Benutzer durchlaufen und die Rechnungen für jeden Benutzer abrufen. Dieses Problem wird als "N + 1-Problem" bezeichnet.

In ActiveRecord besteht die vorgeschlagene Lösung für das „N + 1-Problem“ darin, die Includes-Methode zu verwenden:

irb (main): 022: 0> user = User.includes (: invoices) .find (2) User Load (0,3 ms) SELECT "users". * FROM "users" WHERE "users". "id" = $ 1 LIMIT $ 2 [["id", 2], ["LIMIT", 1]] Laden der Rechnung (0,6 ms) SELECT "invoices". * FROM "invoices" WHERE "invoices". "User_id" = $ 1 [["user_id", 2]] => #  irb (main): 023: 0> user.invoices => # ]>

In diesem Fall lädt ActiveRecord beim Abrufen des Benutzers eifrig die Rechnungszuordnung (wie in den beiden gezeigten SQL-Abfragen gezeigt).

Ecto

Wie Sie vielleicht schon bemerkt haben, mag Ecto Magie oder implizite Dinge nicht. Es erfordert, dass Entwickler ihre Absichten explizit angeben.

Versuchen wir den gleichen Ansatz wie bei der Verwendung von user.invoices mit Ecto:

iex (7)> ​​user = Repo.get (User, 2)
[debug] QUERY OK source = "users" db = 18.3ms decode = 0.6ms
SELECT u0. "Id", u0. "Full_name", u0. "Email", u0. "Inserted_at", u0. "Updated_at" FROM "users" AS u0 WHERE (u0. "Id" = $ 1) [2]
% Financex.Accounts.User {
  __meta__: # Ecto.Schema.Metadata <: loaded, "users">,
  email: "[email protected]",
  vollständiger_name: "Barbara Gordon",
  id: 2,
  inserted_at: ~ N [2018-01-02 10: 02: 00.000000],
  Rechnungen: # Ecto.Association.NotLoaded ,
  updated_at: ~ N [2018-01-02 10: 02: 00.000000]
}
iex (8)> user.invoices
# Ecto.Association.NotLoaded 

Das Ergebnis ist eine Ecto.Association.NotLoaded. Nicht so nützlich.

Um auf die Rechnungen zugreifen zu können, muss ein Entwickler Ecto dies mithilfe der Funktion zum Vorladen mitteilen:

iex (12)> user = preload (Benutzer,: Rechnungen) |> Repo.get (2)
[debug] QUERY OK source = "users" db = 11.8ms
SELECT u0. "Id", u0. "Full_name", u0. "Email", u0. "Inserted_at", u0. "Updated_at" FROM "users" AS u0 WHERE (u0. "Id" = $ 1) [2]
[debug] QUERY OK source = "Rechnungen" db = 4.2ms
SELECT i0. "Id", i0. "Payment_method", i0. "Paid_at", i0. "User_id", i0. "Inserted_at", i0. "Updated_at", i0. "User_id" FROM "invoices" AS i0 WHERE ( i0. "user_id" = $ 1) ORDER BY i0. "user_id" [2]
% Financex.Accounts.User {
  __meta__: # Ecto.Schema.Metadata <: loaded, "users">,
  email: "[email protected]",
  vollständiger_name: "Barbara Gordon",
  id: 2,
  inserted_at: ~ N [2018-01-02 10: 02: 00.000000],
  Rechnungen: [
    % Financex.Accounts.Invoice {
      __meta__: # Ecto.Schema.Metadata <: loaded, "invoices">,
      id: 2,
      inserted_at: ~ N [2018-01-03 08: 00: 00.000000],
      paid_at: #DateTime <2018-02-01 08: 00: 00.000000Z>,
      zahlungsmethode: "Paypal",
      updated_at: ~ N [2018-01-03 08: 00: 00.000000],
      Benutzer: # Ecto.Association.NotLoaded ,
      user_id: 2
    }
  ],
  updated_at: ~ N [2018-01-02 10: 02: 00.000000]
}

iex (15)> user.invoices
[
  % Financex.Accounts.Invoice {
    __meta__: # Ecto.Schema.Metadata <: loaded, "invoices">,
    id: 2,
    inserted_at: ~ N [2018-01-03 08: 00: 00.000000],
    paid_at: #DateTime <2018-02-01 08: 00: 00.000000Z>,
    zahlungsmethode: "Paypal",
    updated_at: ~ N [2018-01-03 08: 00: 00.000000],
    Benutzer: # Ecto.Association.NotLoaded ,
    user_id: 2
  }
]

Ähnlich wie bei ActiveRecord beinhaltet das Vorabladen das Abrufen der zugehörigen Rechnungen, wodurch diese beim Aufruf von user.invoices verfügbar werden.

Vergleich

Wieder einmal endet der Kampf zwischen ActiveRecord und Ecto mit einem bekannten Punkt: der expliziten Aussage. Mit beiden Tools können Entwickler problemlos auf Verknüpfungen zugreifen. ActiveRecord ist zwar weniger ausführlich, kann jedoch zu unerwartetem Verhalten führen. Ecto folgt dem WYSIWYG-Ansatz, der nur das tut, was in der vom Entwickler definierten Abfrage angezeigt wird.

Rails ist bekannt für die Verwendung und Förderung von Caching-Strategien für alle verschiedenen Ebenen der Anwendung. Ein Beispiel ist die Verwendung des Caching-Ansatzes "Russische Puppe", bei dem der Caching-Mechanismus zur Ausführung seiner Magie vollständig auf dem "N + 1-Problem" beruht.

Validierungen

Die meisten in ActiveRecord vorhandenen Überprüfungen sind auch in Ecto verfügbar. Hier ist eine Liste der gängigen Überprüfungen und deren Definition durch ActiveRecord und Ecto:

Einpacken

Da haben Sie es: Der Vergleich zwischen essentiellen Äpfeln und Orangen.

ActiveRecord konzentriert sich auf die einfache Ausführung von Datenbankabfragen. Die überwiegende Mehrheit der Funktionen konzentriert sich auf die Modellklassen selbst. Entwickler müssen weder ein tiefes Verständnis der Datenbank noch der Auswirkungen solcher Operationen haben. ActiveRecord führt viele Dinge standardmäßig implizit aus. Das erleichtert zwar den Einstieg, erschwert jedoch das Verstehen der Vorgänge hinter den Kulissen und funktioniert nur, wenn Sie dem „ActiveRecord-Weg“ folgen.

Ecto hingegen erfordert explizite Aussagen, was zu einem ausführlicheren Code führt. Als Vorteil steht alles im Rampenlicht, nichts hinter den Kulissen, und Sie können Ihren eigenen Weg angeben.

Beide haben ihre Vorteile, abhängig von Ihrer Perspektive und Ihren Vorlieben. Nachdem wir also Äpfel und Orangen verglichen haben, kommen wir zum Ende dieses BAT-Tle. Ich habe fast vergessen, dir zu sagen, dass BatGirls Codename (1989–2001)… war. Orakel. Aber darauf gehen wir nicht ein.

Dieser Beitrag wurde vom Gastautor Elvio Vicosa verfasst. Elvio ist der Autor des Buches Phoenix for Rails Developers.

Ursprünglich veröffentlicht auf blog.appsignal.com am 9. Oktober 2018.