【问题标题】:Moving method logic with SQL to model in rails project使用 SQL 将方法逻辑移动到 Rails 项目中的模型
【发布时间】:2016-04-11 15:28:44
【问题描述】:

将我的控制器 (Invoices) 中的方法移动到相应的模型中,但我遗漏了一些东西。我试过关注thisthis 甚至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

我正试图把它变成这个。

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

这里有我模型中的逻辑。

  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

当前错误信息

nil:NilClass 的未定义方法 `array_of_disbursable_invoices'

【问题讨论】:

    标签: ruby-on-rails ruby model controller refactoring


    【解决方案1】:

    你打败了我(基本上,我选择了第二个选项)。但是,无论如何我都会发布这个。

    当你这样做时:

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

    您在实例上调用 array_of_disbursable_invoices。但是,您没有实例化 Report - 因此,undefined method 'array_of_disbursable_invoices' for nil:NilClass 错误。

    所以,我认为你有两个选择:

    (1) 您可以在实例上调用该方法,例如:

    report = Invoice.new.array_of_disbursable_invoices
    

    (2) 你可以将方法设为类方法,例如:

    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
    

    我想我会推荐 (1)。此外,就个人而言,我会使用 ActiveRecord 查询接口而不是 SQL(假设您在模型中设置了所有关联)。但是,这是个人喜好。

    【讨论】:

    • 我可能会选择这个答案。你解释得比我好,它可能对后代更有帮助。至于 SQL 与 ActiveRecord,我认为我的团队领导只是希望我通过强迫我首先构建 SQL 来更好地了解 ActiveRecord 为我做了什么。也可以重构它。比起后者更喜欢前者,还有什么其他原因?
    • 当我第一次读到你的帖子时,我在想你使用report.array_of_disbursable_invoices 方法可能是有原因的(比如,也许有一个Report 对象潜伏在这里)。我看起来不是这样,所以我认为类方法是干净的。当您进行重构时(如果您决定这样做),您可能最终想要使用范围而不是类方法。有优缺点的好帖子。
    【解决方案2】:

    让它在我的控制器中使用以下代码。

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

    这个在模型中。

      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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-25
      • 2021-03-28
      • 1970-01-01
      相关资源
      最近更新 更多