belaustegui

belaustegui

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?

Showing Posts 1 to 10

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

mrkaspa

mrkaspa

I have this struct but I don’t know how to make the typespec for the associations

%Core.Models.Service{__meta__: #Ecto.Schema.Metadata<:built, "services">,
 charge_to: nil, customer_id: nil, estimated_price: nil,
 estimated_time: nil, id: nil, inserted_at: nil,
 organization_id: nil, payment_type: nil, price: nil,
 scheduled_time: nil,
 service_type: #Ecto.Association.NotLoaded<association :service_type is not loaded>,
 service_type_id: nil, status: nil,
 tasks: #Ecto.Association.NotLoaded<association :tasks is not loaded>,
 total_km: nil, total_time: nil, updated_at: nil,
 user_id: nil, uuid: nil,
 worker_vehicle: #Ecto.Association.NotLoaded<association :worker_vehicle is not loaded>,
 worker_vehicle_id: nil}
ottojimb

ottojimb

I’ve got the same problem. I tried multiple types but dialyzer show me warnings all times.

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.

belaustegui

belaustegui OP

Yes. I completely agree with you.
Typespecs should be provided automatically for Ecto schemas.

michalmuskala

michalmuskala

While it would be rather easy to generate a spec for a schema with built-in types, it’s not as easy to generate one when you start using custom types.

belaustegui

belaustegui OP

Oh, I understand.
So, if the way to go is to manually add the typespecs to our schemas, do you think that it would be a good idea to mention it in the Ecto.Schema docs.

I could submit a PR myself to improve the docs.

mrkaspa

mrkaspa

Do you have an example about how are you doing it?

fertapric

fertapric

Elixir Core Team

Would it be possible to return just term for custom types that does not provide the callback?

I found Ecto.Model typespec · Issue #425 · elixir-ecto/ecto · GitHub and I agree with @whatyouhide

I think even just laying out the struct info is a good starting point. I also think that most people would implement the callback in Ecto.Type if we give good documentation on how to do it; it doesn’t sound like a very complicated task if you have a “template” to look at.

I might be wrong, but my first guess is that it would be something like quote(do: MyCustomType.t)

What do you think?

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

Where Next? Top

Trending in Questions Top

Blokh
Hey guys, I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly Do you guys have any suggestions what is the best prac...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
Onor.io
I have what I’ve heard referred to as a “lookup table” in my database. This is a way of assigning codes to common values. One common lo...
New
jaybe78
Hello, I’m developing a online persistent chat system (what’s app) like using elixir/dynamodb/aws for a mobile app(flutter). The diffic...
New
Trolleger
What approach to take when sending live updates to “random” users Hi! I have a question, I have a little chat app, and when I create a DM...
New
matt-savvy
Anyone here using Honeybadger? My Honeybadger account is being overwhelmed with noise from some bots. Seeing a lot of Bandit.HTTPError...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New

Other Trending Topics Top

garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
wintermeyer
There are three potential reasons for members of this forum to have a look at https://vutuv.de You are tired or annoyed of LinkedIn. Yo...
New
webofbits
Aludel - LLM Evaluation Workbench Aludel is an embeddable Phoenix LiveView dashboard for evaluating and comparing LLM prompts across mult...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews