James
James

Reputation: 1887

Rails sort query by date

I have Payment, Invoice, and Transaction models setup like this:

# transaction.rb
class Transaction < ActiveRecord::Base
  belongs_to :customer
  belongs_to :transactionable, polymorphic: true
end

# payment.rb
class Payment < ActiveRecord::Base
  belongs_to :customer
  has_many :transactions, as: :transactionable
end

# invoice.rb
class Invoice < ActiveRecord::Base
  belongs_to :customer
  has_many :transactions, as: :transactionable
end

In my customers show template, I'm finding all transactions that belong to the requested customer. I want to sort the the transactions by the date of the Invoice or Payment that they belong to. What is the best way to accomplish this?

class CustomersController < ApplicationController
  def show
    @customer = Customer.find(params[:id])

    # I want the transactions sorted by the date of the Invoice or Payment they belong to 
    @transactions = Transaction.where(customer: @customer)
  end
end

Upvotes: 2

Views: 103

Answers (2)

br3nt
br3nt

Reputation: 9586

It may be possible with scopes.

You should be able to do something like the following:

transactions = Transaction.all
transactions = transactions.order_by_payment_date
transactions = transactions.order_by_invoice_date
transactions = transactions.includes_transactionable

transactions.each do |transaction|
  # do what you want with the transaction and transactable
end

Hopefully this code just works:

class Transaction < ActiveRecord::Base
  belongs_to :customer
  belongs_to :transactionable, polymorphic: true

  scope :includes_transactionable, -> { includes(:transactionable) }

  scope :order_by_payment_date, -> {
    # This may or may not work, you may need to specify a has_many 
    # relationship to Payment, or do more to get the join to work
    joins(Payment.arel_table).merge( Payment.descending )
  }

  scope :order_by_invoice_date, -> {
    # This may or may not work, you may need to specify a has_many 
    # relationship to Invoice, or do more to get the join to work
    joins(Invoice.arel_table).merge( Invoice.descending )
  }
end

class Payment < ActiveRecord::Base
  belongs_to :customer
  has_many :transactions, as: :transactionable

  scope :descending, -> { order(arel_table[:payment_date].desc) }
end

class Invoice < ActiveRecord::Base
  belongs_to :customer
  has_many :transactions, as: :transactionable

  scope :descending, -> { order(arel_table[:invoice_date].desc) }
end

Upvotes: 2

Alexa Y
Alexa Y

Reputation: 1854

If a transaction is always created alongside a payment or invoice, you could use the created_at timestamp on the transactions table. If not however, in an effort to keep the transaction model from specifically knowing which models it can belong to, a good option would be to create another datetime column on the transactions table, and have it be updated with whatever datetime is most relevant in the associated object.

Upvotes: 1

Related Questions