覆盖Postgres数组类型移位运算符

时间:2016-05-10 21:28:34

标签: ruby-on-rails arrays ruby postgresql ruby-on-rails-4

是否可以覆盖由ActiveRecord创建的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创建的关联,我可以在其中添加块来重载方法。

2 个答案:

答案 0 :(得分:1)

该方法在Array类中定义,因此您无法在模型中执行此操作。

你可以通过mixin

实现这一目标
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

答案 1 :(得分:1)

在@ ismael的答案的基础上,在ruby =中是setter方法名称的一部分。

此代码 def hours= arr end 创建一个名为hours=的方法,而<<是一个运算符,并且不允许作为方法名称的一部分。 可以定义自定义运算符,@ ismael包含了如何执行此操作的示例。