1
0
mirror of https://github.com/mgerb/classic-wow-forums synced 2026-01-09 00:42:47 +00:00
Files
classic-wow-forums/lib/myapp/data/user.ex

82 lines
2.5 KiB
Elixir

defmodule MyApp.Data.User do
use Ecto.Schema
import Ecto.Query
import Ecto.Changeset
alias MyApp.Repo
alias MyApp.Data
@derive {Poison.Encoder, except: [:__meta__]}
schema "user" do
field :battle_net_id, :integer
field :battletag, :string
timestamps()
end
def changeset(user, params \\ %{}) do
user
|> cast(params, [:battle_net_id, :battletag])
|> validate_required([:battle_net_id, :battletag])
|> unique_constraint(:battle_net_id)
end
@spec get_user(integer) :: nil | map
defp get_user(battle_net_id) do
query = from u in "user",
where: u.battle_net_id == ^battle_net_id,
select: [:id, :battle_net_id, :battletag]
Repo.one(query)
end
# insert user info in database - if not exists - update battletag if it has changed
@spec upsert_user(%{"battle_net_id": integer, "battletag": String.t} | tuple) :: {:ok, map} | {:error, any}
def upsert_user(params) when is_map(params) do
# check for current user in database
case get_user(Map.get(params, "battle_net_id")) do
nil -> insert_user(params)
user ->
# update user if battletag has changed
if Map.get(user, :battletag) != Map.get(params, "battletag") do
update_battletag(user, params)
else
{:ok, user}
end
end
|> add_access_token(Map.get(params, "access_token"))
end
def upsert_user({:ok, params}), do: upsert_user(params)
def upsert_user({:error, error}), do: {:error, error}
# need to add token back to map because we don't store it in the database
defp add_access_token({:error, error}, _), do: {:error, error}
defp add_access_token({:ok, user}, access_token) do
{:ok, Map.merge(user, %{access_token: access_token})}
end
defp insert_user(params) do
cs = changeset(%Data.User{}, params)
cs
|> Repo.insert
|> process_insert_or_update
end
# it's possible for a user's battle tag to change - if so update it
defp update_battletag(user, params) do
cs = Data.User.changeset(Map.merge(%Data.User{}, user), %{battletag: Map.get(params, "battletag")})
cs
|> Repo.update
|> process_insert_or_update
end
defp process_insert_or_update({:error, changeset}), do: {:error, map_changeset(changeset)}
defp process_insert_or_update({:ok, user}) do
{:ok, Map.take(user, [:id, :battle_net_id, :battletag])} # only grab the fields we need
end
defp map_changeset(changeset) do
Enum.map(changeset.errors, fn {key, val} ->
%{key => elem(val, 0)}
end)
end
end