Fritz Meissner Fritz Meissner - 6 months ago 14
Ruby Question

override Postgres array type shift operator

Is it possible to override the

<<
operator for a postgres array type attribute created by ActiveRecord?

Column definition:

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


This seems to work:

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


This doesn't:

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


Note that this is not an association created by
has_many
where I can add a block to overload methods.

Answer

That method is defined in the Array class, so you can't do that in your model.

One way you can achieve that is through a mixin

module WithShift
  def << arg
    # do something 
  end
end


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

This is slower. But it shouldn't be a show stopper. Here is some basic benchmark.

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