jpw
jpw

Reputation: 19247

rails activerecord: how to specify the inverse relationship to "belongs_to ... :class_name ..."

I have the belongs_to ... :class_name association working fine, but cannot see how to create the reciprocal association.

Here's what I have now:

class Contact < ActiveRecord::Base
  # has fields email_id and phone_id
  belongs_to :email, :class_name => 'Rolodex' # this works fine
  belongs_to :phone, :class_name => 'Rolodex' # this works fine
end

class Rolodex < ActiveRecord::Base
  # entry:string  holds a phone#, email address, etc
  has_many :contacts    # does NOT WORK, since no Contact.rolodex_id field
end

And the association works fine in the Contact -> Rolodex direction (via the names :phone and :email)

john = Contact.first
john.phone.entry
# correctly returns the person's rolodex.entry for their phone, if any
john.email.entry
# correctly returns the person's rolodex.entry for their email, if any

However, if I want to lookup all the contacts who share a rolodex entry I cannot use:

r = Rolodex.first
r.contacts
# column contacts.rolodex_id does not exist

Of course, I can bypass the association and do a lookup directly:

Contacts.where("(email_id = ?) OR (phone_id = ?)", r.id. r.id)

but I assume there is some (better) way, eg, a way to specify the reciprocal of the belongs_to ... :class_name association ?

Upvotes: 0

Views: 986

Answers (1)

sevenseacat
sevenseacat

Reputation: 25029

Something like the following would work:

class Rolodex < ActiveRecord::Base
  has_many :email_contacts, class_name: 'Contact', foreign_key: 'email_id'
  has_many :phone_contacts, class_name: 'Contact', foreign_key: 'phone_id'

  def contacts
    email_contacts + phone_contacts
  end
end

Upvotes: 2

Related Questions