#elixirlang 외래 키는 스키마에 정의하고 ecto 연관 함수로 외래 키를 직접 쓰지 말자
2020-01-18
연관(associations) 함수를 사용하면 외래 키(foreign key)를 직접 안 넘겨도 된다. ecto 연관 함수를 쓰면 스키마(schema)에 외래 키를 정의하기에 외래 키를 직접 넘기지 않아도 된다. Programming Phoenix 1.4 책에서 본 온 소스 코드를 간단하게 수정했다.
defmodule User do
use Ecto.Schema
schema "users" do
field(:name, :string)
has_many(:videos, Video)
end
end
defmodule Video do
use Ecto.Schema
schema "videos" do
field(:title, :string)
belongs_to(:user, User)
end
end
테스트를 위해 스키마를 먼저 정의한다. User와 Video에 일대다 관계(one-to-many relationship)를 설정한다. belongs_to/3 매크로로 외래 키를 정의한다. 옵션을 넘기지 않으면 _id
접미사를 붙여서 키를 정의한다. 즉 user_id
키를 정의한다.
iex> {:ok, user} = Repo.insert(%User{name: "ohyecloudy"}) {:ok, %User{ __meta__: #Ecto.Schema.Metadata<:loaded, "users">, id: 1, name: "ohyecloudy", videos: #Ecto.Association.NotLoaded<association :videos is not loaded> }} iex> {:ok, video} = Repo.insert(%Video{title: "video 1", user_id: user.id}) {:ok, %Video{ __meta__: #Ecto.Schema.Metadata<:loaded, "videos">, id: 1, title: "video 1", user: #Ecto.Association.NotLoaded<association :user is not loaded>, user_id: 1 }}
user_id: user.id
키와 값을 넘겨 관계를 만든다. 이렇게 직접 외래 키를 넣는 방법 대신에 스키마에서 가져오게 할 수도 있다.
iex> {:ok, video} = Ecto.build_assoc(user, :videos, %{title: "video 2"}) |> Repo.insert() {:ok, %Video{ __meta__: #Ecto.Schema.Metadata<:loaded, "videos">, id: 2, title: "video 2", user: #Ecto.Association.NotLoaded<association :user is not loaded>, user_id: 1 }}
Ecto.build_assoc/3 함수를 사용하면 외래 키 이름을 스키마에서 가져와서 넣는다. 외래 키 이름이 뭔지 신경 쓸 필요 없이 스키마에 정의한 대로 관계를 만든다.
iex> import Ecto.Query iex> Repo.all(from v in Video, where: v.user_id == ^user.id) [ %Video{ __meta__: #Ecto.Schema.Metadata<:loaded, "videos">, id: 1, title: "video 1", user: #Ecto.Association.NotLoaded<association :user is not loaded>, user_id: 1 }, %Video{ __meta__: #Ecto.Schema.Metadata<:loaded, "videos">, id: 2, title: "video 2", user: #Ecto.Association.NotLoaded<association :user is not loaded>, user_id: 1 } ]
where
절에 user_id
컬럼 값을 검사해서 video를 찾을 수 있다.
ie)> Ecto.assoc(user, :videos) |> Repo.all() [ %Video{ __meta__: #Ecto.Schema.Metadata<:loaded, "videos">, id: 1, title: "video 1", user: #Ecto.Association.NotLoaded<association :user is not loaded>, user_id: 1 }, %Video{ __meta__: #Ecto.Schema.Metadata<:loaded, "videos">, id: 2, title: "video 2", user: #Ecto.Association.NotLoaded<association :user is not loaded>, user_id: 1 } ]
Ecto.assoc/2 함수를 사용하면 더 간단하게 쿼리(query) 문을 만들 수 있다.
ecto 연관 함수를 사용하면 스키마에 정의한 외래 키를 사용해 더 편하게 조회 및 삽입을 할 수 있다.

- tags:
- elixirlang 34
- ecto 3
@ohyecloudy
,ohyecloudy@gmail.com