I have the following context:
defmodule Foo.Companies.Company do
use Foo.Schema
schema "companies" do
field :name, :string
belongs_to :organization, Foo.Organizations.Organization
timestamps()
end
end
Somewhere else I have a function like this:
@spec do_foo(%Company{}) :: :ok
def do_foo(%Company{} = company) do
...
end
This seems to work fine, but when I run mix credo
I get the following warning:
┃ [W] → Struct %Company{} found in @spec
Upon expanding the warning with mix credo explain ...
it says that I should be using something like Company.t()
in the type spec instead of the struct directly.
My question is: What is the preferred way of adding such a type to a struct generated by an Ecto schema? I could add something like:
@type t :: %__MODULE__{
name: String.t(),
organization_id: non_neg_integer()
}
but it seems a bit strange to have to do that manually. Is there a better way? Besides having to do it manually, I see the following problems with the type I just defined:
- It doesn’t capture the fact that a Company can sometimes also have a
organization
associated with it. Some functions that take a %Company{} might require this organization to be preloaded, while others might not. - It doesn’t capture the fact that there are timestamps in the struct.
- If I change the schema I also have to change this type manually.
What are best practices for combining credo dialyzer and ecto like this?