2016-05-10 15 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

hours属性を使用するたびにモジュールを含めるのにパフォーマンス/メモリコストはありますか? – iftheshoefritz

+0

はい、それは約15倍遅くなります。しかし、あなたがこのメソッドを多くの時間呼び出すまで無視してください。また、 'include'が動作しなかったことに気づくでしょう。あなたが実際にしたいことは、 'extend'を使うことです。私は私の答えを編集し、ベンチマークを追加しました –

1

ルビー=の@イスマエルの答えのビルは、セッターのメソッド名の一部です。

このコード def hours= arr end <<一方hours=という名前のメソッドを作成する演算子であり、そしてメソッド名の一部として許可されていません。 で、カスタム演算子を定義することができます。@ismaelにはカスタム演算子を定義する方法が含まれています。

関連する問題