I think this is an Ecto issue with the newest minor version of Elixir, but in Elixir 1.10.1, I can't use the schema types in my typespecs. This is not an issue on previous versions of Elixir.
Using this code (note the spec on what would be line 12):
defmodule MyApp.User do
use Ecto.Schema
import Ecto.Changeset
alias __MODULE__
schema "users" do
field :email, :string
field :password, :string
timestamps()
end
@spec changeset(User.t(), map()) :: Ecto.Changeset.t()
def changeset(%User{} = user \\ %User{}, attrs) do
user
|> cast(attrs, [:email, :password])
end
end
Paste in an iex session with Elixir 1.10.1 (erlang 22.2.6, Ecto 3.3.3), and you'll get this error:
** (CompileError) iex:12: type t/0 undefined (no such type in MyApp.User)
(elixir 1.10.1) lib/kernel/typespec.ex:898: Kernel.Typespec.compile_error/2
(stdlib 3.11.2) lists.erl:1354: :lists.mapfoldl/3
(elixir 1.10.1) lib/kernel/typespec.ex:950: Kernel.Typespec.fn_args/5
(elixir 1.10.1) lib/kernel/typespec.ex:936: Kernel.Typespec.fn_args/6
(elixir 1.10.1) lib/kernel/typespec.ex:377: Kernel.Typespec.translate_spec/8
(stdlib 3.11.2) lists.erl:1354: :lists.mapfoldl/3
(elixir 1.10.1) lib/kernel/typespec.ex:229: Kernel.Typespec.translate_typespecs_for_module/2
(elixir 1.10.1) src/elixir_erl_compiler.erl:12: anonymous fn/3 in :elixir_erl_compiler.spawn/2
Paste that same code in an iex session with Elixir 1.9.1 (erlang 22.1.3, Ecto 3.1.7), and it compiles:
{:module, MyApp.User,
<<70, 79, 82, 49, 0, 0, 15, 84, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 1, 248,
0, 0, 0, 51, 17, 69, 108, 105, 120, 105, 114, 46, 77, 121, 65, 112, 112, 46,
85, 115, 101, 114, 8, 95, 95, 105, 110, ...>>, {:changeset, 2}}
I expect to be able to use schemas in Elixir 1.10 like I used them in 1.9. Again, this may be an issue with how Elixir changes something in Kernel, but since I do define types in the schema definition, I do not expect to have to define them again (i.e. @type t :: %__MODULE__{...).
Hi @davelively14!
Ecto does not define typespecs for you (and it never has). So the code above did not ever work, it is just that Elixir v1.10 started to error if you point to a typespec in the same module that does not exist. You have to define @type t :: %User{} yourself, preferably with proper typespecs inside. :)
Most helpful comment
Hi @davelively14!
Ecto does not define typespecs for you (and it never has). So the code above did not ever work, it is just that Elixir v1.10 started to error if you point to a typespec in the same module that does not exist. You have to define
@type t :: %User{}yourself, preferably with proper typespecs inside. :)