Hi I got Dialyzer from is_session_creator
function until I added %App.Account.User{id: integer}
to typespec of second argument. Is there way to make type spec match any struct or map with id
key? Or is there something wrong with my typespecs?
If you remove %App.Account.User{id: integer}
from is_session_creator
typespec you get this warning
The call 'Elixir.App.Workshop':'is_session_creator?'(_session@1::any(),#{'__meta__':=_, '__struct__':='Elixir.App.Account.User', 'disabled':=boolean(), 'email':=binary(), 'id':=integer(), 'inserted_at':=_, 'role':=binary(), 'updated_at':=_, 'verified':=boolean()}) breaks the contract ('nil' | #{'creator_id':=integer()},#{'id':=integer()} | integer()) -> boolean()
Code
@spec is_session_creator?(
nil | %{creator_id: integer},
%App.Account.User{id: integer} | %{id: integer} | integer
) :: boolean
def is_session_creator?(nil, _), do: false
def is_session_creator?(session, %{id: user_id}) when is_integer(user_id) do
is_session_creator?(session, user_id)
end
def is_session_creator?(%{creator_id: creator_id}, user_id)
when is_integer(creator_id) and is_integer(user_id) do
creator_id == user_id
end
Here is User’s Ecto schema
defmodule App.Account.User do
use Ecto.Schema
import Ecto.Changeset
schema "users" do
field :email, :string, null: false
field :role, :string, null: false
field :disabled, :boolean, null: false, default: false
field :verified, :boolean, null: false, default: false
timestamps()
end
@doc false
def changeset(user, attrs) do
user
|> cast(attrs, [:email, :role, :disabled, :verified])
|> validate_required([:email, :role, :disabled, :verified])
|> unique_constraint(:email)
end
end
This is the function that returned that User struct.
@spec get_current_user(Plug.Conn.t()) :: App.Account.User.t()
def get_current_user(conn), do: conn.assigns[:user]