In the explanation of the Belongs To/Has One association at https://elixirschool.com/en/lessons/ecto/associations/#belongs-tohas-one the author writes:
Let’s say that a movie has one distributor, for example Netflix is the distributor of their original film “Bright”.
...
...the Distributor schema should use the belongs_to/3 macro to allow us to call distributor.movie and look up a distributor’s associated movie using this foreign key.
...
The has_one/3 macro functions just like the has_many/3 macro. It uses the associated schema’s foreign key to look up and expose the movie’s distributor. This will allow us to call movie.distributor.
Here are the schemas for their example:
defmodule Example.Distributor do
use Ecto.Schema
schema "distributors" do
field :name, :string
belongs_to :movie, Example.Movie
end
end
defmodule Example.Movie do
use Ecto.Schema
schema "movies" do
field :title, :string
field :tagline, :string
has_many :characters, Example.Character
has_one :distributor, Example.Distributor # I'm new!
end
end
José Valim writes in http://blog.plataformatec.com.br/2015/08/working-with-ecto-associations-and-embeds/:
The difference between has_one/3 and belongs_to/3 is that the foreign key is always defined in the schema that invokes belongs_to/3.
So by using belongs_to/3 in the Distributor schema, a foreign key is defined in that schema, limiting a single distributor in this example to a single movie. (This is confirmed by the example writer's "...to allow us to call distributor.movie and look up a distributor’s associated movie using this foreign key.")
How would I define the schema if I want a movie to have one distributor, but a single distributor to have one or more movies?
You reverse it.
If a movie has only one distributor, you put the foreign key in its schema.
And then when you need to find movies for one specific distributor, you just find all the movies which have distributor_id
foreign key referencing the distributor's id.
defmodule Example.Movie do
use Ecto.Schema
schema "movies" do
field :title, :string
field :tagline, :string
has_many :characters, Example.Character
belongs_to :distributor, Example.Distributor
end
end
defmodule Example.Distributor do
use Ecto.Schema
schema "distributors" do
field :name, :string
has_many :movies, Example.Movie
end
end