Marituma Marituma - 6 days ago 6
Ruby Question

Trying to implement bidirectional self-referential association

(I'm translating the code as I write, so I apologize for any mistakes!)

I'm trying to implement a bidirectional self referential relation involving the

Associates
table and a join table
Property
. I tried following this post but something is still wrong.

The way it's supposed to work is, an
associate
can be the proprietor of zero or more
associates
, and consequently an
associate
may have zero or more
proprietors
(makes more sense in the context of the application).

So I created the
Property
model:

class CreateProperties < ActiveRecord::Migration
def change
create_table :properties do |t|
t.integer :proprietor_id
t.integer :property_id

t.timestamps null: false
end
end
end


So the table contains only the ids of one
proprietor
and one
property
, both
associate
s, per entry.

Following the tutorial linked above, I came to this configuration:

Associate.rb
:

...
has_many :properties
has_many :related_properties, :through => :properties
has_many :proprietors, :class_name => "Property", :foreign_key => "proprietor_id"
has_many :related_proprietors :through => :proprietors, :source => :associate
...


Property.rb
:

belongs_to :associate
belongs_to :related_properties, :class_name => "Associate"


However when I try to use these relations (
<% @associate.related_properties.each do |property| %>
), I get this error:

PG::UndefinedColumn: ERROR: column properties.related_properties_id does not exist
LINE 1: ... INNER JOIN "propriedades" ON "associados"."id" = "proprieda...
^
: SELECT "associates".* FROM "associates" INNER JOIN "properties" ON "associates"."id" = "properties"."related_properties_id" WHERE "properties"."associate_id" = $1


Basically, the column names are wrong in the generated SQL:
properties.related_properties_id
should be
properties.proprietor_id
, and
properties.associate_id
should be
properties.proprietor_id
as well.

What have I done wrong, and how can I fix this code to get the correct relations?

max max
Answer

You need to setup two seperate associations since the foreign key on Property depends on what the Associates role is.

class Associate
  # defines relations where Associate is the "owning" party
  has_many :properties_as_proprietor, 
    class_name: 'Property',
    foreign_key: 'proprietor_id'
  has_many :properties, 
    through: :properties_as_property,
    source: :property # what to select on Property

  # defines relations where Associate is the "owned" party
  has_many :properties_as_property, 
    class_name: 'Property',
    foreign_key: 'property_id'
  has_many :proprietors, 
    through: :properties_as_proprietor,
    source: :proprietor # what to select on Property
end

class Property
  belongs_to :proprietor, class_name: 'Associate'
  belongs_to :property, class_name: 'Associate'
end