Ruby on Rails
HowtoHaveArraysInRubyAndDB (Version #16)

Note: This applies to ActiveRecord 1.14.4 / Rails 1.1.6 and Postgres 8.0.1

For storing Ruby arrays in a database with ActiveRecord, the normal way is to use

:serialize column
and store the yamled object as text. But doesn’t that just feel wrong? Some DBMS support arrays of various datatypes. And maybe you also want to access the data via SQL, be it for performance reasons or because other (non-Ruby) programs need to access.

So here is one possibly crude solution:

In my example, I have a class called Atom. For each atom, i like to store an array of shifts, which are Floats.

In the atom table i have one column shifts_array of type double precision[].

This is the code:



class ActiveRecord::ConnectionAdapters::Column; def make_text; @type=:text; end; end

class Atom < ActiveRecord::Base

  def shifts
    make_text("shifts_array")
    str2arr(self.shifts_array)
  end

  def add_shift(s)
    self.shifts = (self.shifts << s)
  end

  def shifts=(s)
    if s.class != Array then s = [s] end
    make_text("shifts_array")
    self.shifts_array = arr2str(s)
  end

  def arr2str(arr)
    return "{#{arr.join(',')}}" 
  end

  def str2arr(str)
    if str == nil then return nil end
    return str[1..-2].split(',').collect do |e| e.to_f end
  end
  def make_text(col)
    column_for_attribute(col).make_text
  end
end

If you have ideas on how to make this sleeker or more general, please let me know.

Note: This applies to ActiveRecord 1.14.4 / Rails 1.1.6 and Postgres 8.0.1

For storing Ruby arrays in a database with ActiveRecord, the normal way is to use

:serialize column
and store the yamled object as text. But doesn’t that just feel wrong? Some DBMS support arrays of various datatypes. And maybe you also want to access the data via SQL, be it for performance reasons or because other (non-Ruby) programs need to access.

So here is one possibly crude solution:

In my example, I have a class called Atom. For each atom, i like to store an array of shifts, which are Floats.

In the atom table i have one column shifts_array of type double precision[].

This is the code:



class ActiveRecord::ConnectionAdapters::Column; def make_text; @type=:text; end; end

class Atom < ActiveRecord::Base

  def shifts
    make_text("shifts_array")
    str2arr(self.shifts_array)
  end

  def add_shift(s)
    self.shifts = (self.shifts << s)
  end

  def shifts=(s)
    if s.class != Array then s = [s] end
    make_text("shifts_array")
    self.shifts_array = arr2str(s)
  end

  def arr2str(arr)
    return "{#{arr.join(',')}}" 
  end

  def str2arr(str)
    if str == nil then return nil end
    return str[1..-2].split(',').collect do |e| e.to_f end
  end
  def make_text(col)
    column_for_attribute(col).make_text
  end
end

If you have ideas on how to make this sleeker or more general, please let me know.