nachoab
nachoab

Reputation: 1978

Accesing attributes in the joining table with has_many through

I have a many2many relationship with a has_many through association:

class User < ActiveRecord::Base
  has_many :trips_users
  has_many :trips, through: :trips_users
end

class Trip < ActiveRecord::Base
  has_many :trips_users
  has_many :users, through: :trips_users
end

class TripsUser < ActiveRecord::Base
  belongs_to :user
  belongs_to :trip
end

The joining table trips_user contains a column named 'pending' which id like get when I ask for a list of trips of a user.

So in my controller I need to get all trips a user has, but also adding the 'pending' column.

I was trying

current_user.trips.includes(:trips_users)

that will be done by this select statement:

SELECT trips.* FROM trips INNER JOIN trips_users ON trips.id = trips_users.trip_id WHERE trips_users.user_id = 3

which is missing the information in the trips_users table that I want.

The desired sql would be:

SELECT trips.*, trips_users.* FROM trips INNER JOIN trips_usersON trips.id = trips_users.trip_id WHERE trips_users.user_id = 3

Upvotes: 0

Views: 1586

Answers (3)

gduq
gduq

Reputation: 1454

You could also try:

trips_users = current_user.trips_users.includes(:trip)
trips_users.first.pending?
trips_users.first.trip

Which should give you the trips_users records for that user but also eager loading the trips so that accessing them wouldn't hit the database again.

Upvotes: 0

nachoab
nachoab

Reputation: 1978

This finally worked:

current_user.trips.select('trips_users.*, trips.*')

Overriding the select part of the SQL.

Not very pretty in my opinion thou, I shouldn't be messing with tables and queries but models, specially in such a common case of a m2m association with extra data in the middle.

Upvotes: 1

Helios de Guerra
Helios de Guerra

Reputation: 3475

You'll want to use joins rather than includes for this... See the following Rails Guide:

http://guides.rubyonrails.org/active_record_querying.html#joining-tables

Essentially you'd do something like this:

current_user.trips.joins(:trips_users)

The includes method is used for eager loading, while joins actually performs the table join.

Upvotes: 0

Related Questions