result =
case MyRepo.get(Post, id) do
nil -> %Post{id: id}
post -> post
end
|> Post.changeset(changes)
|> MyRepo.insert_or_update
# {:ok, struct} or {:error, changeset}
Race condition immune
Method 1:
*note a unique index must be on daily_recording_id
case get_chat_channel(attrs) do
%ChatChannel{} = cc -> cc
nil ->
case create_chat_channel(attrs) do
{:ok, cc} -> cc
{:error,
%Ecto.Changeset{
errors: [
unique_constraint:
{"has already been taken",
[constraint: :unique, constraint_name: "chat_channels_unique_index"]}
]
}} ->
%ChatChannel{} = cc = get_chat_channel(attrs)
end
Composing queries
# Create a query
query = from u in User, where: u.age > 18
# Extend the query
query = from u in query, select: u.name
Fragments
Allow you to define raw SQL
from p in Post,
where: is_nil(p.published_at) and
fragment("lower(?)", p.title) == ^title
Custom Macros
defmodule ReactPhoenix.Helpers.QueryMacros do
defmacro filter(agg, condition) do
quote do
fragment("? FILTER(WHERE ?)", unquote(agg), unquote(condition))
end
end
defmacro type_count(id, condition) do
quote do
filter(count(unquote(id)), unquote(condition))
end
end
end