4

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?

awsmketchup
  • 112
  • 2
  • 14
lessless
  • 866
  • 10
  • 27

1 Answers1

7

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
Patrick Oscity
  • 53,604
  • 17
  • 144
  • 168
  • Patrick, but what if, just theoretically, there would be 20 realty types? What then? – lessless Oct 17 '15 at 12:45
  • @lessless take a look at this related answer, it covers in detail a design using a concrete supertable that will eliminate the need for an extra column for each realty type, while also ensuring you can use foreign key constraints to ensure referential integrity: https://stackoverflow.com/questions/922184/why-can-you-not-have-a-foreign-key-in-a-polymorphic-association – Patrick Oscity Oct 17 '15 at 14:23
  • 3
    @lessless it is also worth pointing out that using 20 types would still be faster, take less space (because most of them would be nil) and maintain the database integrity, while the polymorphic approach proposed still wouldn't. – José Valim Oct 20 '15 at 10:32
  • @JoséValim what exactly approach are you referring to? The one mentioned in the docs, or the one with supertable? – lessless Oct 20 '15 at 14:21
  • I was answering your questions: "Patrick, but what if, just theoretically, there would be 20 realty types? What then?" :) – José Valim Oct 22 '15 at 09:18
  • @lessless I think he compared the approach using explicit columns to polymorphic designs in general, be it supertable or polymorphic associations as described in the ecto docs. – Patrick Oscity Oct 22 '15 at 11:44
  • thank you folks! I'm really inspired to start project with phoenix not as because it will make me a better developer, but also hope to create some elixir jobs in the nearest future. – lessless Oct 22 '15 at 13:52