Reputation: 34013
I have a many-to-many relation between User
and "Link".
The join model is called LinkAddress
and besides for saving the IDs of the other two models, it has an attribute called address
- information it collects at creation.
How can I access the address attribute for a certain link in a request scenario like the following: User.first.links.first.address
?
Models:
class User < ActiveRecord::Base
has_many :link_addresses, dependent: :destroy
has_many :links, through: :link_addresses
accepts_nested_attributes_for :link_addresses, allow_destroy: true
end
class LinkAddress < ActiveRecord::Base
belongs_to :user
belongs_to :link
end
class Link < ActiveRecord::Base
has_many :link_addresses, dependent: :destroy
has_many :users, through: :link_addresses
end
Upvotes: 0
Views: 1464
Reputation: 76774
SQL Aliases
I had this exact question: Rails Scoping For has_many :through To Access Extra Data
Here's the answer I got:
#Images
has_many :image_messages, :class_name => 'ImageMessage'
has_many :images, -> { select("#{Image.table_name}.*, #{ImageMessage.table_name}.caption AS caption") }, :class_name => 'Image', :through => :image_messages, dependent: :destroy
This uses SQL Aliases which I found at this RailsCast (at around 6:40 in). It allows us to call @user.image.caption
(even though .caption
is in the join model)
Your Code
For your query, I'd use this:
class User < ActiveRecord::Base
has_many :link_addresses, dependent: :destroy
has_many :links, -> { select("#{Link.table_name}.*, #{LinkAddress.table_name}.address AS address") }, through: :link_addresses
accepts_nested_attributes_for :link_addresses, allow_destroy: true
end
This will allow you to write @user.links.first.address
, and gracefully handles an absence of the address
record
Upvotes: 0
Reputation: 38645
You could access it through User
since it's a has_many ... :through
relation:
User.first.link_addresses.first.address
Or, if you'd like to go through links
then:
User.first.links.first.link_addresses.first.address
Upvotes: 2