has_one through association with condition
Asked Answered
I

1

18

I have 3 relevant tables/models. I would like to retrieve the user which has organized a party, given a Party record, a join table with a boolean organized column, and a users table.

My best attempt so far (this one makes the most sense to me after much fiddling). I've omitted the irrelevant columns.

class Party
  # party_id

  has_many   :parties_users
  has_many   :users, through: :parties_users, source: :user
  has_one    :organizer,
             -> { where organizer: true },
             through: :parties_users,
             source: :user

class PartiesUser
  # party_id
  # user_id
  # organized:bool

  belongs_to :party
  belongs_to :user

class User
  # user_id
  has_many : parties_users

The above setup raises the following error, which I honestly don't fully understand: ActiveRecord::HasOneThroughCantAssociateThroughCollection (Cannot have a has_one :through association 'Party#organizer' where the :through association 'Party#parties_users' is a collection. Specify a has_one or belongs_to association in the :through option instead.)

I know I can do this via an instance method, but given the frequency types of use, my app would massively benefit from having this as an association.

Intestinal answered 19/3, 2018 at 15:20 Comment(2)
I feel like the parties_users should not contain the data related to who organized the party, but the party itself should have belongs_to :organizer, class_name: 'User' (or a separate organizers if you want many-to-many)Fun
This is, in fact, the implementation that I have currently, but it's also resulted in a bunch of messy queries where I have to manually merge users from the join table, and the organizerIntestinal
T
25

As the error message says, you can't have a has_one through a has_many.

You could (instead) do it this way if the organizer flag is on the join record...

has_many :parties_users
has_many :users, through: :parties_users, source: :user
has_one :main_party_user, -> {where organizer: true}, class_name: 'PartiesUser'
has_one :organizer, through: :main_party_user, class_name: 'User'
Toastmaster answered 19/3, 2018 at 15:30 Comment(2)
This works! However, source: :enthusiast must be provided on the last lineIntestinal
I think it should be source: :user instead of class_name: 'User'Noncooperation

© 2022 - 2024 — McMap. All rights reserved.