Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ectoの全体感をまとめてみる

shozo koga
February 24, 2022

 Ectoの全体感をまとめてみる

2022/02/24 fukuoka.ex#51:Elixirお茶会 での登壇資料です

shozo koga

February 24, 2022
Tweet

More Decks by shozo koga

Other Decks in Programming

Transcript

  1. About Me @koga1020_ @koga1020 koga1020.com 👨‍💻 自己紹介 古賀 祥造(koga1020) 福岡在住のバックエンドエンジニア(最近はマネジメント寄り)

    fukuoka.ex 管理人 💡 最近の興味関心 Elixir・Phoenixを使ったWebアプリケーション開発 マイクロサービスの実現。実装パターンの学習 美味しいご飯・美味しいお酒 🍶 マイホームで快適に過ごすこと 🏠
  2. Ectoとは This guide is an introduction to Ecto, the database

    wrapper and query generator for Elixir. Ecto provides a standardized API and a set of abstractions for talking to all the different kinds of databases, so that Elixir developers can query whatever database they’re using by employing similar constructs. データベースラッパー クエリジェネレーター 標準化されたAPIと、あらゆる種類のデータベースと対話するための抽象化されたセットを提供 使用しているデータベースに対して同様の構造を用いて問い合わせを行うことができる [1] 1. https://hexdocs.pm/ecto/getting-started.html#content
  3. Ecto.Repo data storeとの接続を抽象化 data storeとどうやりとりするか: Adapterを定義 Repo.insert/2 としたときの挙動はAdapterが決めている Point: data

    storeは必ずしもMySQLやPostgreSQLなどのデータベースである必要はない CSVを操作したりする例も ecto3_mnesia なんかもそう ※ ecto_mnesia が2系で止まって、別で ecto3_mnesia が作られている 🤔 ? 大多数の人が使うであろうPostgreSQL, MySQL, SQLServerでは公式がアダプターを提供してくれている これが ecto_sql プロジェクトに分離されている ` ` [1] ` ` [2] ` ` ` ` ` ` [3] 1. https://qiita.com/ndac_todoroki/items/48c44dd1a2e9c7a824d3 2. https://hexdocs.pm/ecto3_mnesia/Ecto.Adapters.Mnesia.html 3. https://github.com/elixir-ecto/ecto_sql
  4. Ecto.Schema schemaを定義 DBクエリ結果をマッピング defmodule User do use Ecto.Schema schema "users"

    do field :name, :string field :age, :integer, default: 0 end end iex> Sample.Repo.all(Sample.Accounts.User) [debug] QUERY OK source="users" db=0.1ms queue=0.1ms idle=1088.3m SELECT u0."id", u0."age", u0."name", u0."inserted_at", u0."updated_at" FR [ %Sample.Accounts.User{ __meta__: #Ecto.Schema.Metadata<:loaded, "users">, age: 20, id: 1, inserted_at: ~N[2022-02-08 14:18:05], name: "山田太郎", updated_at: ~N[2022-02-08 14:18:05] }, %Sample.Accounts.User{ __meta__: #Ecto.Schema.Metadata<:loaded, "users">, age: 30, id: 2, inserted_at: ~N[2022-02-08 14:18:11], name: "山田花子", updated_at: ~N[2022-02-08 14:18:11] } ]
  5. Ecto.Changeset Changesets allow filtering, casting, validation and definition of constraints

    when manipulating structs. Changesetでデータのフィルタリング、キャスト(変換)、バリデーション、制約の定義が行える a set of change:一連の変更 をまとめたもの と捉えるといいかも 個人的には: Ectoを使った実装をする上で超重要 [1] [2] 1. https://hexdocs.pm/ecto/Ecto.Changeset.html 2. https://stackoverflow.com/a/33186341
  6. Ecto.Changeset データに対する変更内容が1つの構造体にまとまっている action: 変更の種類( :insert | :update | :delete |

    :replace | :ignore ) data: 変更を加える元データ errors: 変更を加えようとした際に発生したエラー changes: 加えた変更 valid?: 有効な変更かどうか ` ` iex(1)> User.changeset(%User{}, %{name: "koga", age: "invalid"}) #Ecto.Changeset< action: nil, changes: %{name: "koga"}, errors: [age: {"is invalid", [type: :integer, validation: :cast]}], data: #Sample.Accounts.User<>, valid?: false >
  7. Ecto.Changeset tips: 登録時と更新時でバリデーションの要件が違う場合は関数を分けるなんてこともできる data |> changeset化 |> バリデーション |> Repoに投げ込み

    という流れをイメージできると良さそう def changeset_for_insert(some_data, attrs) do # insert時のcast, validationを記述 end def changeset_for_update(some_data, attrs) do # update時のcast, validationを記述 end
  8. Ecto.Query QueryのDSLを提供するもの Elixirコードでクエリを書くためのマクロ集と捉えるとよい 例. Elixirコード: 生成されるクエリ: Comment |> join(:inner, [c],

    p in Post, on: c.post_id == p.id) |> select([c, p], {p.title, c.text}) SELECT p1."title", c0."text" FROM "comments" AS c0 INNER JOIN "posts" AS p1 ON c0."post_id" = p1."id" []
  9. まとめ Ecto: "the database wrapper and query generator for Elixir"

    Ecto.Repo, Ecto.Schema, Ecto.Changeset, Ecto.Queryの4つが主な構成要素 Ecto.Repo: data storeへの接続、やりとりの定義(Adapter) Ecto.Schema: データをElixirの構造体にマップ Ecto.Changeset: データの一連の変換・バリデーション Ecto.Query: クエリのDSLを提供 Changesetを自由自在に書けると多種多様な要件の実装が可能になる なんらか特殊なバリデーションを組んだり has_manyの構造を同一トランザクションで保存したり cf. cast_assoc/3 , put_assoc/4 DBなしでEctoを使うなどの応用もあり おまけ: @the_haigo さんにLTいただく Ecto.Multi の話も非常に重要 ` ` ` ` ` `