ruby-on-railsrubyactiverecordrails-activerecordarel

How to get active record relation of polymorphic parents from child object?


I have below structure:

class Transaction < ApplicationRecord
  belongs_to :transactionable, polymorphic: true
end

class TransactionSale < ApplicationRecord
  has_many :transactions, as: :transactionable
end

class TransactionRental < ApplicationRecord
  has_many :transactions, as: :transactionable
end

I want to get all the linked transactions (sale & rental) by querying the Transaction table only. For example:

Transaction.includes(:transactionable).where(project_id: project_id).map { |txn| txn.transactionable }

The above query returns both TransactionSale and TransactionRental objects combined and that is the exact result I wanna achieve. The only problem here is it returns a ruby array instead of ActiveRecord::Relation so I can't sort the transactions further in a single query or use other active record methods.

I have read all other answers that suggest plucking the ids and then apply where which is not possible here coz I don't know whether the table is rental or sale.

Is there any way to achieve the same result without losing the ActiveRecord relation?


Solution

  • Apparantly i solved it myself,

    # Get id and classes of all transaction types
    locks = Transaction.where(project_id: self.id).pluck(:transactionable_id, :transactionable_type)
        
    # Init empty active record relation
    final = Transaction.none
    
    # convert id and classes array to hash to group on polymorphic classes
    locks.group_by { |s| s[1] }.each_pair do |k,v| 
          # extracts ids to make query
          ids = v.map { |d| d[0] }
          
          # make query from respective model
          data = eval(k).where(id: ids)
    
          # merge the array returned above with empty relation and rewrite 
          final = final.or(data)
    end
    

    The final contains the active record relation of all polymorphic records.