Ruby on Rails ActiveRecord - has_many with Custom Join on Aliased Table

47 views Asked by At

Context:

  • I have three models: User, ProjectUser, and Message .

  • Messages have a polymorphic join via item_id and item_type and can belong to either a User or a ProjectUser

  • Users have many ProjectUsers


Goal: In the ProjectUser model, I want to define a has_many relationship called general_messages to get all Messages that are related to either the ProjectUser OR ProjectUser.user . The join would look like this:

ProjectUser.joins(:user).joins('JOIN messages AS general_messages ON general_messages.item_id IN (project_users.id, users.id)') 

Note: I want to be able to join and filter using regular ActiveRecord methods. I.e. ProjectUser.joins(:general_messages).where(general_messages: { ...WHERE CLAUSE }), so it's important that this is achieved by defining a has_many relationship

1

There are 1 answers

0
Ruby Racer On

Well, this is all to be tailored for your needs, but there are different things to be done.

Using plain ActiveRecord, I would go for a lambda as a scope argument, to define what is that the relation would do.

The line below has not been tested, but you could use it to play around it and see where you get.

Source: https://api.rubyonrails.org/v7.0.6/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many

has_many :general_messages, ->(project_user) {
    where(type: 'User', id: project_user.user_id).
    or(type: 'ProjectUser', id: project_user.id)
}, class_name: "Message"