belaustegui

belaustegui

Adding typespect to an Ecto Schema

I have an Ecto schema and I am wondering about how to represent it in typespecs.

Suppose that my schema is like this:

defmodule User do
  use MyApp.Model
  
  schema "users" do
    field :name, :string
    field :email, :string
    timestamps
  end
end

Which would be the best way to refer to this struct in my specs? Currently I am doing something like:

@spec my_function(String.t) :: %User{}

But I’m thinking that I could add a @type t :: %__MODULE__{user: String.t, email: String.t} declaration to my User struct and change the specs to something like:

@spec my_function(String.t) :: User.t

Which alternative would be the best? And why?

First Post!

PragTob

PragTob

I believe @type t ... is the convention to define the type of module and hence should be preferred - it’s the first thing I’d try in an application. Also if you define the required keys like you showed, then you don’t have to repeat that knowledge everywhere and the source of truth lives in Schema.t

Most Liked

mgwidmann

mgwidmann

I’d say if Ecto does not already setup a typespec for your schema when it defines the struct, then I’d consider that a bug. This should happen automatically IMO.

ggerico

ggerico

Could someone check if the LOC below are flawless, especially:

  • the virtual field
  • the associations

teacher_id: integer() or should it be teacher: Teacher.t()
user_id: integer() or should it be user: User.t()

# user.ex

@type t :: %__MODULE__{
  id: integer,
  email: String.t(),
  name:  String.t(),
  phone: String.t(),

  credential: Credential.t(),
  teacher_id: integer,
  student_id: integer,

  inserted_at: NaiveDateTime.t(),
  updated_at: NaiveDateTime.t()
  }

schema "users" do
  field(:email, :string)
  field(:name, :string)
  field(:phone, :string)

   has_one(:credential, Credential)
   belongs_to(:teacher, Teacher)
   belongs_to(:student, Student)

   timestamps()
end

# credential.ex

@type t :: %__MODULE__{
 password: String.t(),
 password_hash: String.t(),
 
  user_id: integer,

  inserted_at: NaiveDateTime.t(),
  updated_at: NaiveDateTime.t()
}

schema "credentials" do
  field(:password_hash, :string)
  # Virtual Fields
  field(:password, :string, virtual: true)

  belongs_to(:user, User)

  timestamps()
end

# teacher.ex

@type t :: %__MODULE__{
  id: integer,
  experience: String.t(),
  
  user: User.t(),
  students: [ Student.t() ],
  subjects: [ Subject.t() ],

  inserted_at: NaiveDateTime.t(),
  updated_at: NaiveDateTime.t()
}

schema "teachers" do

  field(:experience, :integer, default: 1)

  has_one(:user, User)
  has_many(:student, Student)
  has_many(:subject, Subject)

  timestamps()
  end
toraritte

toraritte

Custom types should be implemented using Ecto.Type behaviour, so maybe it would be possible to bake this into any new custom type?

There is also a relevant issue in the ejpcmac/typed_struct repo.

Where Next?

Popular in Questions Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New

Other popular topics Top

rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 31586 112
New
sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New

We're in Beta

About us Mission Statement