Ecto#
naive_datetimeでなく、utc_datetime_usecを使用したほうが良いという話 https://elixirforum.com/t/why-use-utc-datetime-over-naive-datetime-for-ecto/32532
preload#
交差テーブルでpreloadする方法は、
例えば、
def get_user_by_role(role_name) when is_binary(role_name) do
from(u in User,
join: ur in UserRole,
on: ur.user_id == u.id,
join: r in Role,
on: r.id == ur.role_id,
where: r.name == ^role_name,
select: u
)
|> Repo.all() # ここでselect1回走る
|> Repo.preload(:roles) # ここでselect2回走る
end
あるいはこう、
def get_user_by_role(role_name) when is_binary(role_name) do
from(u in User,
join: ur in UserRole,
on: ur.user_id == u.id,
join: r in Role,
on: r.id == ur.role_id,
where: r.name == ^role_name,
preload: :roles,
select: u
)
|> Repo.all() # ここでselect3回走る
end
selectを1回で済ましたい場合は、明示的に書く。 see. https://hexdocs.pm/ecto/Ecto.Query.html#preload/3
def get_user_by_role(role_name) when is_binary(role_name) do
from(u in User,
join: ur in UserRole,
on: ur.user_id == u.id,
join: r in Role,
on: r.id == ur.role_id,
where: r.name == ^role_name,
preload: [roles: r]
select: u
)
|> Repo.all() # ここでselect1回走る
end
You don’t have to use :put_assoc or :cast_assoc#
https://medium.com/@lauraannwilliams/you-dont-have-to-use-put-assoc-or-cast-assoc-48b8575be3ce
assoc_constraint の 嬉しさが分からない。ドキュメントに
This is similar to foreign_key_constraint/3 except that the field is inferred from the association definition.
とあるが、以下のようにcastで :post_id を書いている時点で :post_id の存在を知っているので意味がないと感じる。
comment
|> Ecto.Changeset.cast(params, [:post_id])
|> Ecto.Changeset.assoc_constraint(:post)
|> Repo.insert
暗に使うくらいなら、 foreign_key_constraint で明にした方がいい気がする。
put_assocでなくbuild_assocを使うケース#
def create_user_property(%User{} = user, attrs) do
Ecto.build_assoc(user, :property)
|> UserProperty.changeset(attrs)
|> Repo.insert()
end
# changesetの後にput_assocするとuser_idにvalidationをかけたい場合にかけられない。
def create_user_property(%User{} = user, attrs) do
%UserProperty{}
|> UserProperty.changeset(attrs)
|> Ecto.Changeset.put_assoc(:user, user)
|> Repo.insert()
end