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?
CodePudding user response:
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.
CodePudding user response:
No nice/easy way, no. You could do it by creating the SQL and running a UNION
as a subquery but that's pretty ugly.