Hugo
Hugo

Reputation: 2204

Active Record get associated model with polymorphic relation

I have a polymorphic address model like so:

class Address < ApplicationRecord
  belongs_to :addressable, polymorphic: true
end

As well as two possible associations, users and friends:

class User < ApplicationRecord
  has_many :friends, dependent: :destroy
  has_one :address, :as => :addressable, dependent: :destroy
end

class Friend < ApplicationRecord
  belongs_to :user
  has_many :addresses, :as => :addressable, dependent: :destroy
end

I would like to be able to get the friends or the user from the address. Both are related to the Address model.

How could I have the following:

Address.last.user

Or

Address.last.friends.first

Thank you

Upvotes: 0

Views: 1287

Answers (2)

TheVinspro
TheVinspro

Reputation: 370

As you defined a polymorphic model.

class Address < ApplicationRecord
  belongs_to :addressable, polymorphic: true
end

One address will be associated with One instance of either User or Friend.

see http://guides.rubyonrails.org/association_basics.html#polymorphic-associations

With polymorphic associations, a model can belong to more than one other model, on a single association.

Address.last.user or Address.first.friend

Here you defined a relation between address and friend.

class Friend < ApplicationRecord
  belongs_to :user
  has_many :addresses, :as => :addressable, dependent: :destroy
end

so each instance of Friend can have multiple instances of Address like:

Friend.last.addresses # office address, home address

Upvotes: 1

Nermin
Nermin

Reputation: 6100

Address.new.addressable # will give the addressed object
# Depending what was addressed it will return User or Friend

But to achieve this what you ask, you would need to create a method, and it would not be treated as a relation (could not be used in the join)

class Address < ApplicationRecord
  belongs_to :addressable, polymorphic: true

  def user
    addressable if addressable_type == User.name
  end

  def friend
    addressable if addressable_type == Friend.name
  end
end

You can not call relations in class, you have to call them on an object. Address.user # will throw an error

Also Address has a relation type belongs_to so you do not have a list of friends for address, you have a list of addresses for a friend.

Upvotes: 1

Related Questions