如何为一个Model重写ActiveRecord方法

时间:2016-01-22 08:26:43

标签: ruby-on-rails activerecord

我想为我的班级last覆盖Calculations方法。

# app/models/calculations.rb
class Calculations < ActiveRecord::Base
  def self.last
    console.info "Run my custom Calculations.last"
    order(:custom_field).limit(1).last
  end
end

1.9.3-p194 :001 > Calculations.last
custom last
Calculations Load (0.1ms)  SELECT `calculations`.* FROM `calculations` ORDER BY calculations.created_at DESC LIMIT 1
=> #<Calculations date: "2016-01-13", direction: "order", ...>

1.9.3-p194 :003 > Calculations.where(nil).last
Calculations Load (45.1ms)  SELECT `calculations`.* FROM `calculations` ORDER BY `calculations`.`` DESC LIMIT 1
Mysql2::Error: Unknown column 'calculations.' in 'order clause': SELECT  `calculations`.* FROM `calculations`  ORDER BY `calculations`.`` DESC LIMIT 1
ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'calculations.' in 'order clause': SELECT  `calculations`.* FROM `calculations`  ORDER BY `calculations`.`` DESC LIMIT 1

第一个示例称为自定义方法。 第二个称为AR原始方法。 我做错了什么?

2 个答案:

答案 0 :(得分:0)

问题是您已为.last类重写Calculations,但在第二行中,您在.last上调用Calculations::ActiveRecord_Relation(由where子句返回) ,这不是你定义的那个。我不确定这是多么干净,但它应该有效(不需要在你的课程中覆盖.last):

class Calculations < ActiveRecord::Base
  class ActiveRecord_Relation
    def self.last
      console.info "Run my custom Calculations.last"
      order(:custom_field).limit(1).last
    end
  end
end

补充一点。如果您没有特殊原因为模型使用复数名称,请考虑将其更改为单数,这是rails惯例。

答案 1 :(得分:0)

要覆盖:: last for Calculations,你可以这样做:

class Calculations < ActiveRecord::Base

  def self.last
    puts "OVERRIDING"
    super
  end
end

虽然我不推荐它。

对于你正在做的事情,看起来范围可能有效

scope :last_record, -> { order(created_at: :desc).limit(1) }