Search code examples
elixirphoenix-frameworkecto

Inverse polymorphic with ecto


the current Ecto documentation http://hexdocs.pm/ecto/Ecto.Schema.html only explains how to build a belongs_to type of polymorphic association, when the polymorphic Comment can belong to both Task and Post. But what about opposite direction?

For example there is a Listing which can have a one of the four types of properties: Room, Apartment, Vila or Office.

Considering a one-to-one relationship, given the example above it would mean that there should be rooms_listings, apartments_listings, vila_listings and office_listings, which is impossible, because that will lead to the duplication of all of the other tables associated with listings.

The question is how to model this kind of relationship?


Solution

  • I think the simplest way to model this is by flipping around the sides of the association and then just adding the room_id, etc. fields to the listings table:

    defmodule Listing do
      use Ecto.Model
      schema "listings" do
        belongs_to :room, Room
        belongs_to :apartment, Apartment
        belongs_to :villa, Villa
        belongs_to :office, Office
      end
    end
    

    Then you can define a has_one :listing relationship on every one of the other tables:

    defmodule Room do
      use Ecto.Model
      schema "rooms" do
        has_one :listing, Listing
      end
    end
    
    defmodule Apartment do
      use Ecto.Model
      schema "apartments" do
        has_one :listing, Listing
      end
    end
    
    defmodule Villa do
      use Ecto.Model
      schema "villas" do
        has_one :listing, Listing
      end
    end
    
    defmodule Office do
      use Ecto.Model
      schema "offices" do
        has_one :listing, Listing
      end
    end