ActiveRecord срещу Ecto, втора част

Това е втората част от серията „ActiveRecord срещу Ecto“, в която Батман и Батгърл се борят за заявки в бази данни и сравняваме ябълки и портокали.

След като разгледаме схемите на базата данни и миграциите в ActiveRecord спрямо Ecto, първа част, тази публикация обхваща как ActiveRecord и Ecto дават възможност на разработчиците да направят заявки към базата данни и как ActiveRecord и Ecto се сравняват, когато работят с едни и същи изисквания. По пътя ще разберем и самоличността на Batgirl в периода 1989–2011 г.

Данни за семената

Да започваме! Въз основа на структурата на базата данни, дефинирана в първата публикация на тази серия, приемете, че потребителите и таблиците с фактури имат следните данни, съхранявани в тях:

потребители

* Полето създадено_at поле на ActiveRecord е по име по подразбиране вмъкнато_ в Ecto.

фактури

* Полето създадено_at поле на ActiveRecord е по име по подразбиране вмъкнато_ в Ecto.

Въпросите, изпълнени чрез тази публикация, предполагат, че данните по-горе се съхраняват в базата данни, така че имайте предвид тази информация, докато я четете.

Намерете елемент с неговия първичен ключ

Нека започнем с получаването на запис от базата данни с помощта на неговия първичен ключ.

ActiveRecord

irb (main): 001: 0> User.find (1) Потребителско натоварване (0.4ms) ИЗБЕРЕТЕ "потребители". * ОТ "потребители" КЪДЕ "потребители". "id" = $ 1 ОГРАНИЧЕНИЕ $ 2 [["id", 1 ], ["LIMIT", 1]] => # 

екто

iex (3)> Repo.get (Потребител, 1)
[debug] QUERY OK source = "users" db = 5.2ms декодиране = 2.5ms опашка = 0.1ms
ИЗБЕРЕТЕ u0. "Id", u0. "Full_name", u0. "Имейл", u0. "Вмъкна_at", u0. "Актуализира_at" ОТ "потребители" КАК u0 WHERE (u0. "Id" = $ 1) [1]
% Financex.Accounts.User {
  __meta__: # Ecto.Schema.Metadata <: заредени, "потребители">,
  имейл: „[email protected]“,
  пълно име: „Бете Кейн“,
  id: 1,
  вмъкнато_на: ~ N [2018-01-01 10: 01: 00.000000],
  фактури: # Ecto.Association.NotLoaded <асоциация: фактури не са заредени>,
  updated_at: ~ N [2018-01-01 10: 01: 00.000000]
}

сравнение

И двата случая са доста сходни. ActiveRecord разчита на метода find class на класа на потребителски модел. Това означава, че всеки детски клас ActiveRecord има свой собствен метод за намиране в него.

Ecto използва различен подход, разчитайки на концепцията Repository като посредник между картографския слой и домейна. Когато използвате Ecto, потребителският модул няма знания как да се намери. Подобна отговорност присъства в модула Repo, който е в състояние да го пренасочи под хранилището на данни, което в нашия случай е Postgres.

Когато сравняваме самата SQL заявка, можем да забележим няколко разлики:

  • ActiveRecord зарежда всички полета (потребители. *), Докато Ecto зарежда само полетата, посочени в дефиницията на схемата.
  • ActiveRecord включва LIMIT 1 към заявката, докато Ecto не.

Извличане на всички елементи

Нека направим крачка напред и ще заредим всички потребители от базата данни.

ActiveRecord

irb (main): 001: 0> User.all Зареждане на потребителя (0.5ms) ИЗБЕРЕТЕ "потребители". * ОТ "потребители" ОГРАНИЧЕН $ 1 [["LIMIT", 11]] => # , # , # , # ]>

екто

iex (4)> Repo.all (потребител)
[debug] QUERY OK source = "users" db = 2.8ms декодиране = 0.2ms опашка = 0.2ms
SELECT u0. "Id", u0. "Full_name", u0. "Имейл", u0. "Insert_at", u0. "Updated_at" ОТ "потребители" AS u0 []
[
  % Financex.Accounts.User {
    __meta__: # Ecto.Schema.Metadata <: заредени, "потребители">,
    имейл: „[email protected]“,
    пълно име: „Бете Кейн“,
    id: 1,
    вмъкнато_на: ~ N [2018-01-01 10: 01: 00.000000],
    фактури: # Ecto.Association.NotLoaded <асоциация: фактури не са заредени>,
    updated_at: ~ N [2018-01-01 10: 01: 00.000000]
  }
  % Financex.Accounts.User {
    __meta__: # Ecto.Schema.Metadata <: заредени, "потребители">,
    имейл: „[email protected]“,
    пълно име: „Барбара Гордън“,
    id: 2,
    вмъкнато_на: ~ N [2018-01-02 10: 02: 00.000000],
    фактури: # Ecto.Association.NotLoaded <асоциация: фактури не са заредени>,
    updated_at: ~ N [2018-01-02 10: 02: 00.000000]
  }
  % Financex.Accounts.User {
    __meta__: # Ecto.Schema.Metadata <: заредени, "потребители">,
    имейл: „[email protected]“,
    пълно име: „Касандра Каин“,
    id: 3,
    вмъкнато_на: ~ N [2018-01-03 10: 03: 00.000000],
    фактури: # Ecto.Association.NotLoaded <асоциация: фактури не са заредени>,
    updated_at: ~ N [2018-01-03 10: 03: 00.000000]
  }
  % Financex.Accounts.User {
    __meta__: # Ecto.Schema.Metadata <: заредени, "потребители">,
    имейл: „[email protected]“,
    пълно име: „Стефани Браун“,
    id: 4,
    вмъкнато_на: ~ N [2018-01-04 10: 04: 00.000000],
    фактури: # Ecto.Association.NotLoaded <асоциация: фактури не са заредени>,
    updated_at: ~ N [2018-01-04 10: 04: 00.000000]
  }
]

сравнение

Следва абсолютно същия модел като предишния раздел. ActiveRecord използва метода all class и Ecto разчита на модела на хранилището за зареждане на записите.

Отново има някои разлики в SQL заявките:

Въпроси с условия

Малко вероятно е да извлечем всички записи от таблица. Обща необходимост е използването на условия за филтриране на върнатите данни.

Нека използваме този пример, за да изброим всички фактури, които тепърва ще се плащат (КЪДЕ платено_от Е НУЛЛ).

ActiveRecord

irb (main): 024: 0> Invoice.where (paid_at: nil) Зареждане на фактура (18.2ms) ИЗБЕРЕТЕ "фактури". * ОТ "фактури" WHERE "фактури". "paid_at" Е NULL LIMIT $ 1 [["LIMIT" , 11]] => # , # <фактура id: 4, user_id: 4, Payment_method: nil, paid_at: nil, created_at:" 2018-01-05 08:00:00 ", updated_at:" 2018-01-05 08:00:00 ">]>

екто

iex (19)> където (Фактура, [i], is_nil (i.paid_at)) |> Repo.all ()
[debug] QUERY OK source = "фактури" db = 20.2ms
ИЗБЕРЕТ i0. "Id", i0. "Payment_method", i0. "Paid_at", i0. "User_id", i0. "Insert_at", i0. "Updated_at" ОТ "фактури" AS i0 WHERE (i0. "Paid_at" IS НУЛА) []
[
  % Financex.Accounts.Invoice {
    __meta__: # Ecto.Schema.Metadata <: заредени, "фактури">,
    id: 3,
    вмъкнато_на: ~ N [2018-01-04 08: 00: 00.000000],
    paid_at: нула,
    Payment_method: нула,
    updated_at: ~ N [2018-01-04 08: 00: 00.000000],
    потребител: # Ecto.Association.NotLoaded <асоциация: потребителят не е зареден>,
    user_id: 3
  }
  % Financex.Accounts.Invoice {
    __meta__: # Ecto.Schema.Metadata <: заредени, "фактури">,
    id: 4,
    вмъкнато_на: ~ N [2018-01-04 08: 00: 00.000000],
    paid_at: нула,
    Payment_method: нула,
    updated_at: ~ N [2018-01-04 08: 00: 00.000000],
    потребител: # Ecto.Association.NotLoaded <асоциация: потребителят не е зареден>,
    user_id: 4
  }
]

сравнение

И в двата примера се използва ключовата дума където е връзка с клаузата SQL WHERE. Въпреки че генерираните SQL заявки са доста сходни, начинът, по който и двата инструмента стигат до там, има някои важни разлики.

ActiveRecord преобразува аргумента pay_at: nil в оператора pay_at IS NULL SQL автоматично. За да стигнат до същия изход чрез Ecto, разработчиците трябва да бъдат по-категорични относно намеренията си, като извикат is_nil ().

Друга разлика, която трябва да се подчертае, е „чистото“ поведение на функцията, където е в Ecto. Когато се обаждате само където функцията, тя не взаимодейства с базата данни. Връщането на функцията където е структура на Ecto.Query:

iex (20)> където (Фактура, [i], is_nil (i.paid_at))
# Ecto.Query <от i в Financex.Accounts.Invoice, където: is_nil (i.paid_at)>

Базата данни се докосва само когато се извиква функцията Repo.all (), като се предава структурата на Ecto.Query като аргумент. Този подход позволява състава на заявки в Ecto, което е предмет на следващия раздел.

Състав на заявката

Един от най-мощните аспекти на заявките към базата данни е състава. Той описва заявка по начин, който съдържа повече от едно условие.

Ако изграждате сурови SQL заявки, това означава, че вероятно ще използвате някакъв вид конкатенация. Представете си, че имате две условия:

  1. not_paid = 'paid_at НЕ Е НУЛЛ'
  2. paid_with_paypal = 'payment_method = "Paypal"'

За да комбинирате тези две условия, използвайки суров SQL, означава, че ще трябва да ги свържете, като използвате нещо подобно на:

ИЗБЕРЕТЕ * ОТ фактури, КЪДЕ # {not_paid} И # {paid_with_paypal}

За щастие и ActiveRecord и Ecto имат решение за това.

ActiveRecord

irb (main): 003: 0> Invoice.where.not (paid_at: nil) .where (Payment_method: "Paypal") Зареждане на фактура (8.0ms) ИЗБЕРЕТЕ "фактури". * FROM "фактури" WHERE "фактури". " paid_at "НЕ Е НУЛНО И" фактури "." Payment_method "= $ 1 ОГРАНИЧЕНИЕ $ 2 [[" Payment_method "," Paypal "], [" LIMIT ", 11]] => # ]>

екто

iex (6)> Фактура |> където ([i], а не is_nil (i.paid_at)) |> където ([i], i.payment_method == "Paypal") |> Repo.all ()
[debug] QUERY OK source = "фактури" db = 30.0ms декодиране = 0.6ms опашка = 0.2ms
ИЗБЕРЕТ i0. "Id", i0. "Payment_method", i0. "Paid_at", i0. "User_id", i0. "Insert_at", i0. "Updated_at" ОТ "фактури" AS i0 WHERE (НЕ (i0. "Paid_at "IS NULL)) И (i0." Payment_method "= 'Paypal') []
[
  % Financex.Accounts.Invoice {
    __meta__: # Ecto.Schema.Metadata <: заредени, "фактури">,
    id: 2,
    вмъкнато_на: ~ N [2018-01-03 08: 00: 00.000000],
    paid_at: #DateTime <2018-02-01 08: 00: 00.000000Z>,
    Payment_method: "Paypal",
    updated_at: ~ N [2018-01-03 08: 00: 00.000000],
    потребител: # Ecto.Association.NotLoaded <асоциация: потребителят не е зареден>,
    user_id: 2
  }
]

сравнение

И двете запитвания отговарят на един и същ въпрос: „Кои фактури са платени и използвани Paypal?“.

Както вече се очаква, ActiveRecord предлага по-кратък начин за съставяне на заявката (за този пример), докато Ecto изисква от разработчиците да отделят малко повече за писането на заявката. Както обикновено, Batgirl (Сиракът, ням такъв с идентичността на Касандра Каин) или Activerecord не е толкова многословен.

Не се заблуждавайте от многословието и явната сложност на заявката Ecto, показана по-горе. В реална среда тази заявка ще бъде пренаписана, за да изглежда по-скоро като:

фактура
|> където ([i], а не is_nil (i.paid_at))
|> където ([i], i.payment_method == "Paypal")
|> Repo.all ()

Виждайки от този ъгъл, комбинацията от „чисти“ аспекти на функцията, където, която не извършва операции с база данни само с оператора на тръбата, прави състава на заявките в Ecto наистина чиста.

Подреждане

Поръчката е важен аспект на заявката. Тя дава възможност на разработчиците да гарантират, че даден резултат от заявката следва определен ред.

ActiveRecord

irb (main): 002: 0> Invoice.order (created_at:: desc) Зареждане на фактура (1,5ms) ИЗБЕРЕТЕ "фактури". * ОТ "фактури" ПОРЪЧАЙТЕ по "фактури". "created_at" DESC LIMIT $ 1 [["LIMIT ", 11]] => # , # <фактура ID: 3, user_id: 3, Payment_method: nil, paid_at: nil, created_at: "2018-01-04 08:00:00", updated_at: "2018-01-04 08:00:00">, # <фактура идентификатор: 2, потребител_ид: 2, Payment_method: "Paypal", paid_at: "2018-02-01 08:00:00", създадено_at: "2018 -01-03 08:00:00 ", актуализиран_at:" 2018-01-03 08:00:00 ">, # <Идент. Номер на фактура: 1, user_id: 1, Payment_method:" Кредитна карта ", paid_at:" 2018- 02-01 08:00:00 ", created_at:" 2018-01-02 08:00:00 ", актуализира_at:" 2018-01-02 08:00:00 ">]>

екто

iex (6)> order_by (Фактура, desc:: insert_at) |> Repo.all ()
[debug] QUERY OK source = "фактури" db = 19.8ms
ИЗБЕРЕТ i0. "Id", i0. "Payment_method", i0. "Paid_at", i0. "User_id", i0. "Insert_at", i0. "Updated_at" ОТ "фактури" AS i0 ПОРЪЧАЙТЕ i0. "Insert_at" DESC []
[
  % Financex.Accounts.Invoice {
    __meta__: # Ecto.Schema.Metadata <: заредени, "фактури">,
    id: 3,
    вмъкнато_на: ~ N [2018-01-04 08: 00: 00.000000],
    paid_at: нула,
    Payment_method: нула,
    updated_at: ~ N [2018-01-04 08: 00: 00.000000],
    потребител: # Ecto.Association.NotLoaded <асоциация: потребителят не е зареден>,
    user_id: 3
  }
  % Financex.Accounts.Invoice {
    __meta__: # Ecto.Schema.Metadata <: заредени, "фактури">,
    id: 4,
    вмъкнато_на: ~ N [2018-01-04 08: 00: 00.000000],
    paid_at: нула,
    Payment_method: нула,
    updated_at: ~ N [2018-01-04 08: 00: 00.000000],
    потребител: # Ecto.Association.NotLoaded <асоциация: потребителят не е зареден>,
    user_id: 4
  }
  % Financex.Accounts.Invoice {
    __meta__: # Ecto.Schema.Metadata <: заредени, "фактури">,
    id: 2,
    вмъкнато_на: ~ N [2018-01-03 08: 00: 00.000000],
    paid_at: #DateTime <2018-02-01 08: 00: 00.000000Z>,
    Payment_method: "Paypal",
    updated_at: ~ N [2018-01-03 08: 00: 00.000000],
    потребител: # Ecto.Association.NotLoaded <асоциация: потребителят не е зареден>,
    user_id: 2
  }
  % Financex.Accounts.Invoice {
    __meta__: # Ecto.Schema.Metadata <: заредени, "фактури">,
    id: 1,
    вмъкнато_на: ~ N [2018-01-02 08: 00: 00.000000],
    paid_at: #DateTime <2018-02-01 08: 00: 00.000000Z>,
    Payment_method: „Кредитна карта“,
    updated_at: ~ N [2018-01-02 08: 00: 00.000000],
    потребител: # Ecto.Association.NotLoaded <асоциация: потребителят не е зареден>,
    user_id: 1
  }
]

сравнение

Добавянето на поръчка към заявка е направо и в двата инструмента.

Въпреки че примерът Ecto използва фактура като първи параметър, функцията order_by също приема структури Ecto.Query, което позволява функцията order_by да се използва в композиции, като:

фактура
|> където ([i], а не is_nil (i.paid_at))
|> където ([i], i.payment_method == "Paypal")
|> order_by (desc:: insert_at)
|> Repo.all ()

Ограничаването

Какво би била база данни без ограничение? Катастрофа. За щастие, ActiveRecord и Ecto помагат за ограничаване на броя върнати записи.

ActiveRecord

irb (main): 004: 0> Фактура.limit (2)
Зареждане с фактури (0.2ms) ИЗБЕРЕТЕ „фактури“. * ОТ „фактури“ LIMIT $ 1 [[„LIMIT“, 2]]
=> # , # <Идент. Номер на фактура: 2, user_id: 2, Payment_method:" Paypal ", paid_at:" 2018-02-01 08: 00:00 ", създаден_at:" 2018-01-03 08:00:00 ", актуализиран_at:" 2018-01-03 08:00:00 ">]>

екто

iex (22)> лимит (фактура, 2) |> Repo.all ()
[debug] QUERY OK source = "фактури" db = 3.6ms
ИЗБЕРЕТ i0. "Id", i0. "Payment_method", i0. "Paid_at", i0. "User_id", i0. "Insert_at", i0. "Updated_at" ОТ "фактури" AS i0 LIMIT 2 []
[
  % Financex.Accounts.Invoice {
    __meta__: # Ecto.Schema.Metadata <: заредени, "фактури">,
    id: 1,
    вмъкнато_на: ~ N [2018-01-02 08: 00: 00.000000],
    paid_at: #DateTime <2018-02-01 08: 00: 00.000000Z>,
    Payment_method: „Кредитна карта“,
    updated_at: ~ N [2018-01-02 08: 00: 00.000000],
    потребител: # Ecto.Association.NotLoaded <асоциация: потребителят не е зареден>,
    user_id: 1
  }
  % Financex.Accounts.Invoice {
    __meta__: # Ecto.Schema.Metadata <: заредени, "фактури">,
    id: 2,
    вмъкнато_на: ~ N [2018-01-03 08: 00: 00.000000],
    paid_at: #DateTime <2018-02-01 08: 00: 00.000000Z>,
    Payment_method: "Paypal",
    updated_at: ~ N [2018-01-03 08: 00: 00.000000],
    потребител: # Ecto.Association.NotLoaded <асоциация: потребителят не е зареден>,
    user_id: 2
  }
]

сравнение

Както ActiveRecord, така и Ecto имат начин да ограничат броя записи, върнати чрез заявка.

Ограничението на Ecto работи подобно на order_by, като е подходящо за композиции на заявки.

асоциации

ActiveRecord и Ecto имат различни подходи, що се отнася до начина на работа с асоциациите.

ActiveRecord

В ActiveRecord можете да използвате всяка асоциация, дефинирана в даден модел, без да се налага да правите нещо специално за това, например:

irb (main): 012: 0> user = User.find (2) Зареждане на потребителя (0.3ms) ИЗБЕРЕТЕ "потребители". * ОТ "потребители", КЪДЕ "потребители". "id" = $ 1 ОГРАНИЧЕНА $ 2 [["id" , 2], ["LIMIT", 1]] => #  irb (main): 013: 0> user.invoices Зареждане на фактури (0.4ms) ИЗБЕРЕТЕ" фактури ". * FROM" фактури "WHERE" фактури " . "user_id" = $ 1 LIMIT $ 2 [["user_id", 2], ["LIMIT", 11]] => # ] >

Примерът по-горе показва, че можем да получим списък с потребителските фактури при извикване на user.invoices. Когато прави това, ActiveRecord автоматично запитва базата данни и зарежда фактурите, които са свързани с потребителя. Въпреки че този подход прави нещата по-лесни, в смисъл да пишете по-малко код или да се притеснявате за допълнителни стъпки, това може да е проблем, ако правите повторение на няколко потребители и получавате фактури за всеки потребител. Този проблем е известен като "N + 1 проблем".

В ActiveRecord, предложеното коригиране на „проблема с N + 1“ е да се използва методът включва:

irb (main): 022: 0> user = User.includes (: фактури) .find (2) User Load (0.3ms) ИЗБЕРЕТЕ "потребители". * ОТ "users" WHERE "потребители". "id" = $ 1 ОГРАНИЧЕНИЕ $ 2 [["id", 2], ["LIMIT", 1]] Зареждане с фактури (0.6ms) ИЗБЕРЕТЕ "фактури". * FROM "фактури" WHERE "фактури". "User_id" = $ 1 [["user_id", 2]] => #  irb (main): 023: 0> user.invoices => # ]>

В този случай ActiveRecord жадно зарежда асоциацията на фактури при извличане на потребителя (както се вижда от показаните две SQL заявки).

екто

Както може би вече сте забелязали, Ecto наистина не харесва магия или имплицит. Това изисква от разработчиците да са изрично относно своите намерения.

Нека опитаме същия подход с използването на user.invoices с Ecto:

iex (7)> ​​потребител = Repo.get (Потребител, 2)
[debug] QUERY OK source = "users" db = 18.3ms decode = 0.6ms
ИЗБЕРЕТЕ u0. "Id", u0. "Full_name", u0. "Имейл", u0. "Вмъкна_at", u0. "Актуализира_at" ОТ "потребители" КАК u0 WHERE (u0. "Id" = $ 1) [2]
% Financex.Accounts.User {
  __meta__: # Ecto.Schema.Metadata <: заредени, "потребители">,
  имейл: „[email protected]“,
  пълно име: „Барбара Гордън“,
  id: 2,
  вмъкнато_на: ~ N [2018-01-02 10: 02: 00.000000],
  фактури: # Ecto.Association.NotLoaded <асоциация: фактури не са заредени>,
  updated_at: ~ N [2018-01-02 10: 02: 00.000000]
}
iex (8)> user.invoices
# Ecto.Association.NotLoaded <асоциация: фактури не са заредени>

Резултатът е Ecto.Association.NotLoaded. Не е толкова полезно.

За да има достъп до фактурите, разработчикът трябва да уведоми Ecto за това, използвайки функцията за предварително зареждане:

iex (12)> user = preload (Потребител,: фактури) |> Repo.get (2)
[debug] QUERY OK source = "потребители" db = 11,8ms
ИЗБЕРЕТЕ u0. "Id", u0. "Full_name", u0. "Имейл", u0. "Вмъкна_at", u0. "Актуализира_at" ОТ "потребители" КАК u0 WHERE (u0. "Id" = $ 1) [2]
[debug] QUERY OK source = "фактури" db = 4.2ms
ИЗБЕРЕТ i0. "Id", i0. "Payment_method", i0. "Paid_at", i0. "User_id", i0. "Insert_at", i0. "Updated_at", i0. "User_id" FROM "фактури" AS i0 WHERE ( i0. "user_id" = $ 1) ПОРЪЧАЙТЕ i0. "user_id" [2]
% Financex.Accounts.User {
  __meta__: # Ecto.Schema.Metadata <: заредени, "потребители">,
  имейл: „[email protected]“,
  пълно име: „Барбара Гордън“,
  id: 2,
  вмъкнато_на: ~ N [2018-01-02 10: 02: 00.000000],
  фактури: [
    % Financex.Accounts.Invoice {
      __meta__: # Ecto.Schema.Metadata <: заредени, "фактури">,
      id: 2,
      вмъкнато_на: ~ N [2018-01-03 08: 00: 00.000000],
      paid_at: #DateTime <2018-02-01 08: 00: 00.000000Z>,
      Payment_method: "Paypal",
      updated_at: ~ N [2018-01-03 08: 00: 00.000000],
      потребител: # 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 <: заредени, "фактури">,
    id: 2,
    вмъкнато_на: ~ N [2018-01-03 08: 00: 00.000000],
    paid_at: #DateTime <2018-02-01 08: 00: 00.000000Z>,
    Payment_method: "Paypal",
    updated_at: ~ N [2018-01-03 08: 00: 00.000000],
    потребител: # Ecto.Association.NotLoaded <асоциация: потребителят не е зареден>,
    user_id: 2
  }
]

Подобно на ActiveRecord включва, предварителното зареждане с извличане на свързаните фактури, които ще ги направят достъпни при извикване на user.invoices.

сравнение

За пореден път битката между ActiveRecord и Ecto завършва с изрично известна точка: И двата инструмента позволяват на разработчиците да имат лесен достъп до асоциациите, но докато ActiveRecord го прави по-малко многословен, резултатът от него може да има неочаквано поведение. Ecto следва подхода на WYSIWYG, който прави само това, което се вижда в заявката, дефинирана от програмиста.

Rails е добре известна с използването и популяризирането на кеширащите стратегии за всички различни слоеве на приложението. Един пример е за използването на кеширания подход „руска кукла“, който изцяло разчита на „N + 1 проблема“, за да кешира механизма му да изпълнява своята магия.

Проверки

Повечето валидации, присъстващи в ActiveRecord, са налични и в Ecto. Ето списък с общи валидации и как ActiveRecord и Ecto ги определят:

Увийте

Ето го: сравнението между основните ябълки и портокали.

ActiveRecord се фокусира върху лекотата на изпълнение на заявки към база данни. По-голямата част от неговите функции са съсредоточени върху самите класове на модели, като не се изисква от разработчиците да разбират дълбоко базата данни, нито въздействието на подобни операции. ActiveRecord прави много неща по подразбиране неявно. Въпреки че това прави по-лесно да започнете, затруднява разбирането на случващото се зад кулисите и работи само ако следвате „ActiveRecord начина“.

Ecto, от друга страна, изисква изричност, което води до повече многословен код. Като полза всичко е в светлината на прожекторите, нищо зад кулисите и можете да определите свой собствен път.

И двамата са обърнати нагоре в зависимост от вашата перспектива и предпочитания. Така че сравнявайки ябълки и портокали, стигаме до края на тази НДНТ. Почти забравих да ви кажа, че кодовото име на BatGirl (1989–2001) беше…. Oracle. Но нека не навлизаме в това.

Този пост е написан от гост-автора Елвио Викоза. Елвио е автор на книгата Phoenix for Rails Developers.

Първоначално публикуван на blog.appsignal.com на 9 октомври 2018 г.