CheeseFry
CheeseFry

Reputation: 1319

Moving method logic with SQL to model in rails project

Moving a method in my controller (Invoices) into the corresponding model and I'm missing something. I've tried following this and this and even this and there are small issues I'm having that I need extra eyes on.

My working controller method is this.

  def array_of_disbursable_invoices
    sql = "SELECT MIN(departure_date), ch_invoice.invoice_id
    FROM ch_invoice
    INNER JOIN ch_trip
    ON ch_invoice.invoice_id = ch_trip.invoice_id
    WHERE departure_date <= (SELECT SYS_EXTRACT_UTC(SYSTIMESTAMP)FROM DUAL)
    AND service_rendered = 0
    AND paid = 1
    Group By ch_invoice.invoice_id"

    report = ActiveRecord::Base.connection.exec_query(sql)
    render json: report
  end

And I'm trying to turn it into this.

  def array_of_disbursable_invoices
    report = report.array_of_disbursable_invoices
    render json: report
  end

With the logic in my model here.

  def array_of_disbursable_invoices
    sql = "SELECT MIN(departure_date), ch_invoice.invoice_id
    FROM ch_invoice
    INNER JOIN ch_trip
    ON ch_invoice.invoice_id = ch_trip.invoice_id
    WHERE departure_date <= (SELECT SYS_EXTRACT_UTC(SYSTIMESTAMP)FROM DUAL)
    AND service_rendered = 0
    AND paid = 1
    Group By ch_invoice.invoice_id"

    ActiveRecord::Base.connection.exec_query(sql)
  end

Current error message

undefined method `array_of_disbursable_invoices' for nil:NilClass

Upvotes: 0

Views: 73

Answers (2)

jvillian
jvillian

Reputation: 20263

You beat me to it (and went, essentially, with my second option). But, I'll post this anyway.

When you do this:

def array_of_disbursable_invoices
  report = report.array_of_disbursable_invoices
  render json: report
end

You're calling array_of_disbursable_invoices on an instance. But, you don't instantiate Report - thus, the undefined method 'array_of_disbursable_invoices' for nil:NilClass error.

So, I think you have two choices:

(1) You could call the method on an instance, something like:

report = Invoice.new.array_of_disbursable_invoices

(2) You could make the method a class method, something like:

class Invoice < ActiveModel::Base
  class << self
    def array_of_disbursable_invoices
      sql = "SELECT MIN(departure_date), ch_invoice.invoice_id
      FROM ch_invoice
      INNER JOIN ch_trip
      ON ch_invoice.invoice_id = ch_trip.invoice_id
      WHERE departure_date <= (SELECT SYS_EXTRACT_UTC(SYSTIMESTAMP)FROM DUAL)
      AND service_rendered = 0
      AND paid = 1
      Group By ch_invoice.invoice_id"

      connection.exec_query(sql)
    end
  end
end

I think I'd recommend (1). Also, personally, I'd use the ActiveRecord query interface instead of the SQL (assuming you have all the associations set up in your models). But, that's a personal preference.

Upvotes: 1

CheeseFry
CheeseFry

Reputation: 1319

Got it to work with the following code in my controller.

  def array_of_disbursable_invoices
    report = Invoice.array_of_disbursable_invoices
    render json: report
  end

And this in the model.

  def self.array_of_disbursable_invoices
    sql = "SELECT MIN(departure_date), ch_invoice.invoice_id
    FROM ch_invoice
    INNER JOIN ch_trip
    ON ch_invoice.invoice_id = ch_trip.invoice_id
    WHERE departure_date <= (SELECT SYS_EXTRACT_UTC(SYSTIMESTAMP)FROM DUAL)
    AND service_rendered = 0
    AND paid = 1
    Group By ch_invoice.invoice_id"

    ActiveRecord::Base.connection.exec_query(sql)
  end

Upvotes: 0

Related Questions