LoginSignup
16
1

hexdocs.pmのEctoをざっくり読んだメモ

Posted at

hexdocs.pmのEctoをざっくり読んだメモ
※私の読書メモなので、hexdocsをみんな読もう!

Ectoは4つの主要コンポーネントに分かれている

要約すると

  • Ecto.Repo
    • where the data is
  • Ecto.Schema
    • what the data is
  • Ecto.Query
    • how to read the data
  • Ecto.Changeset
    • how to change the data

Ecto.Repo

リポジトリ(repositories)はデータストアのラッパー。
リポジトリ(repository)を通して、既存のエントリーを作成、更新、破棄、問い合わせることができる。
リポジトリは、データベースと通信するためのアダプタと認証情報を必要とする。

リポジトリは次のように定義できる。(Phoenixだと自動生成される)

lib/sample/repo.ex
defmodule Sample.Repo do
  use Ecto.Repo,
    otp_app: :sample,
    adapter: Ecto.Adapters.Postgres
end

リポジトリの構成はアプリケーション環境内に存在する必要があり、通常はアプリケーション環境で定義される。

config/config.exs
config :sample,
  ecto_repos: [Sample.Repo]
config/dev.exs
config :sample, Sample.Repo,
  username: "postgres",
  password: "postgres",
  hostname: "localhost",
  database: "sample_dev",
  stacktrace: true,
  show_sensitive_data_on_connection_error: true,
  pool_size: 10

Ecto.Schema

スキーマは、外部データをElixir構造体にマッピングするために使用する。
データベースのテーブルをElixirのデータにマッピングするためによく使うが、他にもいろいろな使い道がある。

スキーマによって、開発者はデータの形を定義することができる。

defmodule Basic.Accounts.User do
  use Ecto.Schema
  import Ecto.Changeset

  schema "users" do
    field :name, :string
    field :age, :integer

    timestamps()
  end
end
iex(1)> alias SampleP.Accounts.User
iex(2)> user = %User{name: "taro", age: 13}
%SampleP.Accounts.User{
  __meta__: #Ecto.Schema.Metadata<:built, "users">,
  id: nil,
  name: "taro",
  age: 13,
  inserted_at: nil,
  updated_at: nil
}
iex(3)> user.name
"taro"
iex(4)> user2 = %User{name: "jiro", age: 11}
%SampleP.Accounts.User{
  __meta__: #Ecto.Schema.Metadata<:built, "users">,
  id: nil,
  name: "jiro",
  age: 11,
  inserted_at: nil,
  updated_at: nil
}
iex(5)> alias SampleP.Repo
iex(6)> Repo.insert!(user2)
[debug] QUERY OK db=3.7ms queue=1.0ms idle=1386.8ms
INSERT INTO "users" ("name","age","inserted_at","updated_at") VALUES ($1,$2,$3,$4) RETURNING "id" ["jiro", 11, ~N[2023-11-12 05:13:08], ~N[2023-11-12 05:13:08]]
 :erl_eval.do_apply/7, at: erl_eval.erl:746
%SampleP.Accounts.User{
  __meta__: #Ecto.Schema.Metadata<:loaded, "users">,
  id: 2,
  name: "jiro",
  age: 11,
  inserted_at: ~N[2023-11-12 05:13:08],
  updated_at: ~N[2023-11-12 05:13:08]
}

Ecto.Changeset

Changesetは、変更がデータに適用される前に、その変更を追跡し検証する方法を提供する。
Changesetにより、開発者は変更をデータに適用する前に、フィルター、キャスト、検証を行うことができる。

defmodule Sample.Accounts.User do
  use Ecto.Schema
  import Ecto.Changeset

  schema "users" do
    field :name, :string
    field :age, :integer

    timestamps()
  end

  @doc false
  def changeset(user, attrs) do
    user
    |> cast(attrs, [:name, :age])
    |> validate_required([:name, :age])
  end
end

changeset/2 関数は、まず構造体、パラメータ、許可されたフィールドのリストを指定して Ecto.Changeset.cast/4 を呼び出します。
フィールドリストに明示的にリストされていないパラメータは無視されます。

castの後、Changesetは変更されたフィールドのみを検証する多くのEcto.Changeset.validate_* 関数に渡されます。言い換えると、フィールドがパラメータとして与えられなかった場合、そのフィールドはまったく検証されません。

defmodule Sample.Accounts do
  〜略〜

  def create_user(attrs \\ %{}) do
    %User{}
    |> User.changeset(attrs)
    |> Repo.insert()
  end
end

Ecto.Query

Elixir構文で記述されたクエリは、指定されたリポジトリから情報を取得するために使用される。
Ectoクエリはセキュアでコンポーザブルです。

※コンポーザブル
「構成可能な」という意味がある。
複数の要素や部品などを結合して、構成や組み立てが可能な、といった意味がある。

iex(8)> import Ecto.Query, only: [from: 2]
iex(10)> query = from u in User,
...(10)>           where: u.age > 12,
...(10)>           select: u
#Ecto.Query<from u0 in SampleP.Accounts.User, where: u0.age > 12, select: u0>
iex(11)> Repo.all(query)
[debug] QUERY OK source="users" db=5.7ms queue=3.4ms idle=1290.3ms
SELECT u0."id", u0."name", u0."age", u0."inserted_at", u0."updated_at" FROM "users" AS u0 WHERE (u0."age" > 12) []
 :erl_eval.do_apply/7, at: erl_eval.erl:746
[
  %SampleP.Accounts.User{
    __meta__: #Ecto.Schema.Metadata<:loaded, "users">,
    id: 1,
    name: "mamiko",
    age: 15,
    inserted_at: ~N[2023-11-12 05:07:28],
    updated_at: ~N[2023-11-12 05:07:28]
  }
]

最後に

Ectoの4要素をざっくり読んでいきました。
実装に落とし込むには、さらに下記ドキュメントを読むとよさそうです。

16
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
1