2016-05-10 27 views
0

是否有可能覆蓋由ActiveRecord創建的postgres數組類型屬性的<<運算符?覆蓋Postgres數組類型移位運算符

列定義:

t.time "hours", default: [], array: true 

這似乎工作:

def hours=(arr) 
    super(arr.map {|h| # do some stuff with each element}) 
end 

這不:

def hours<<(val) 
    super(# do some stuff before pushing) 
end 

注意,這不是has_many創建一個協會,我可以爲重載方法添加一個塊。

回答

1

該方法在Array類中定義,因此您無法在模型中執行此操作。你可以做到這一點

一種方式是通過一個混合

module WithShift 
    def << arg 
    # do something 
    end 
end 


def hours 
    read_attribute("hours").extend(WithShift) 
end 

這會慢一些。但它不應該是一個表演塞。這是一些基本的基準。

require 'benchmark/ips' 
module WithShift 
    def << arg 
    end 
end 
def with_extend; [1,2,3].extend(WithShift); end 

def base; [1,2,3]; end 

Benchmark.ips do |x| 
    x.report("base") { base } 
    x.report("with extend") { with_extend } 
    x.compare! 
end 


Calculating ------------------------------------- 
       base  5.506M (± 9.1%) i/s -  27.415M in 5.022561s 
     with extend 349.984k (± 7.6%) i/s -  1.769M in 5.081799s 

Comparison: 
       base: 5505897.2 i/s 
     with extend: 349984.1 i/s - 15.73x slower 
+0

每次使用小時屬性時,是否存在包含模塊的性能/內存成本? – iftheshoefritz

+0

是的,它慢了大約15倍。但除非你把這種方法稱爲很多次,否則可以忽略不計。還要注意'include'不起作用。你實際上想要做的是使用'extend'。我編輯了我的答案並添加了一個基準 –

1

大廈@伊斯梅爾的回答,在紅寶石=是二傳手的方法名稱的一部分。

此代碼 def hours= arr end 創建一個名爲hours=<<是一個操作符,並且不允許作爲方法名稱的一部分的方法。它可能定義自定義運算符,並@ismael包括如何做到這一點的例子。