timestamps()
end
- def get_by_name(name) do
- Repo.get_by(Hashtag, name: name)
+ def normalize_name(name) do
+ name
+ |> String.downcase()
+ |> String.trim()
end
- def get_or_create_by_name(name) when is_bitstring(name) do
- with %Hashtag{} = hashtag <- get_by_name(name) do
- {:ok, hashtag}
- else
- _ ->
- %Hashtag{}
- |> changeset(%{name: name})
- |> Repo.insert()
- end
+ def get_or_create_by_name(name) do
+ changeset = changeset(%Hashtag{}, %{name: name})
+
+ Repo.insert(
+ changeset,
+ on_conflict: [set: [name: get_field(changeset, :name)]],
+ conflict_target: :name,
+ returning: true
+ )
end
def get_or_create_by_names(names) when is_list(names) do
+ names = Enum.map(names, &normalize_name/1)
timestamp = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
structs =
|> Map.merge(%{inserted_at: timestamp, updated_at: timestamp})
end)
- with {:ok, %{query_op: hashtags}} <-
- Multi.new()
- |> Multi.insert_all(:insert_all_op, Hashtag, structs, on_conflict: :nothing)
- |> Multi.run(:query_op, fn _repo, _changes ->
- {:ok, Repo.all(from(ht in Hashtag, where: ht.name in ^names))}
- end)
- |> Repo.transaction() do
- {:ok, hashtags}
- else
- {:error, _name, value, _changes_so_far} -> {:error, value}
+ try do
+ with {:ok, %{query_op: hashtags}} <-
+ Multi.new()
+ |> Multi.insert_all(:insert_all_op, Hashtag, structs,
+ on_conflict: :nothing,
+ conflict_target: :name
+ )
+ |> Multi.run(:query_op, fn _repo, _changes ->
+ {:ok, Repo.all(from(ht in Hashtag, where: ht.name in ^names))}
+ end)
+ |> Repo.transaction() do
+ {:ok, hashtags}
+ else
+ {:error, _name, value, _changes_so_far} -> {:error, value}
+ end
+ rescue
+ e -> {:error, e}
end
end
def changeset(%Hashtag{} = struct, params) do
struct
|> cast(params, [:name])
- |> update_change(:name, &String.downcase/1)
+ |> update_change(:name, &normalize_name/1)
|> validate_required([:name])
|> unique_constraint(:name)
end
where: hto.object_id == ^object_id,
select: hto.hashtag_id
)
- |> Repo.delete_all() do
- delete_unreferenced(hashtag_ids)
+ |> Repo.delete_all(),
+ {:ok, unreferenced_count} <- delete_unreferenced(hashtag_ids) do
+ {:ok, length(hashtag_ids), unreferenced_count}
end
end