Is there a replacement for ActiveRecord `source` in ecto?

45 Views Asked by At

Please help me in finding the elixir/ecto option for :source option of has_one/has_many :through association of ActiveRecord.

Here is my problem, I have the following schemas: User, Event, AttendingEvents. A User has many events, and an Event belongs to a user. Then there is AttendedEvents which belongs to both user and group. So, in rails I would do this:

class User < ApplicationRecord
  has_many :attending_events, dependent: :destroy
  has_many :attended_events, through: :attending_events, source: :event, foreign_key: :attendee_id
end

class Event < ApplicationRecord
  has_many :attending_events
  has_many :attendees, through: :attending_events, source: :user
end

Since ecto has no source, how can I rewrite this so that I am able to do this instead of a query?

event = MyApp.Repo.get(MyApp.Event, id) |> MyApp.Repo.preload(:attendees)
event.attendees
1

There are 1 best solutions below

1
ema On

If I understand your schema and requests you can do like this.

defmodule MyApp.User do
  use Ecto.Schema
  import Ecto.Changeset

  schema "users" do
    # User schema fields

    has_many :attending_events, MyApp.AttendingEvent
    has_many :attended_events, through: [:attending_events, :event]
  end
end

defmodule MyApp.Event do
  use Ecto.Schema
  import Ecto.Changeset

  schema "events" do
    # Event schema fields

    has_many :attending_events, MyApp.AttendingEvent
    has_many :attendees, through: [:attending_events, :user]
  end
end

defmodule MyApp.AttendingEvent do
  use Ecto.Schema
  import Ecto.Changeset

  schema "attending_events" do
    belongs_to :user, MyApp.User
    belongs_to :event, MyApp.Event
  end
end

With these schemas and mapping your query became:

event = 
  MyApp.Repo.get(MyApp.Event, id)
  |> MyApp.Repo.preload(attendees: MyApp.User)

Does it make sense?