Modeling a collection of integers in active record

Hey,

I’m a newbie to Rails, so forgive me if my question is stupid and I’m
spamming the group. I couldn’t find any info on the Web.

I’d like to model an entity that contains a collection of integers. In
SQL, I could achieve that by creating two tables, like that:

CREATE TABLE Entity (
id INTEGER,
title VARCHAR,
other_stuff BLOB
);

CREATE TABLE EntityIntegerCollection (
entity_id INTEGER,
value INTEGER
);

And now I can SELECT value FROM EntityIntegerCollection WHERE
entity_id = 1234 to retrieve the collection for entity 1234. My
question is: How do I model this in ActiveRecord? Can I keep this
simple table schema or do I have to change something to get what I
want?

Well, you start with creating a model for every table, which can be done
like when you create controllers.

ruby script/generate model entity
ruby script/generate model entityintegercollection

and in your migration you can add columns :smiley:

db/migrate/ (HERE)

Uhm, I think I’m not following you…

What I want is to create a SQL table structure, so that later in Rails
I can write something like entity.integer_collection[3]. I’m looking
for a way to express this association using has_many, belongs_to or
something like that… I don’t want to stick to the table schema
mentioned, but I want to have Entity class that has attribute
integer_collection. Do you mean I can achieve this with migrations?

Mike

On Sep 3, 8:25 pm, Jamal S. [email protected]

Let me first answer your question directly and then suggest an
alternative.

First of all, let’s follow rails convention here and create two
tables: entities and entity_integers. We’ll also create the models
that rails will use to interface them. We’ll do both at once with:

ruby script/generate model Entity
ruby script/generate model EntityInteger

You will find two new migrations in db/migrate:

001_create_entities.rb
002_create_entity_integers.rb

In those add your columns:

class CreateEntities < ActiveRecord::Migration
def self.up
create_table :entities do |t|
t.column :title, :string
end
end

def self.down
drop_table :entities
end
end

Similarly in your 002_create_entity_integers.rb migration add:

t.column :value, :integer
t.column :entity_id, :integer

in your Entity model (app/models/entity.rb) add:

has_many :entity_integers

and in your EntityInteger model add:

belongs_to :entity

Run rake db:migrate and that’s it. open up script/console and play
around.

@entity = Entity.new :title => “foo”
@entity.save
@entity.entity_integers.create :value => 1
@entity.entity_integers.create :value => 2

@entity.entity_integers.map {|integer| integer.value} #=> [1, 2]

Now here’s an alternative. Create the same Entity model as before but
in the migration do:

t.column :title, :string
t.column :integrers, :string, :default => [].to_yaml # will work in
MySQL but not Postgres, last time I checked.

and in the Entity model:

seialize :integers, :class_name => Array

and try this out:

@entity = Entity.new :title => “foo”
@entity.integers += [1,2,3]
@entity.save
@entity.integers #=> [1,2,3]
@entity.integers += [5,6,7]
@entity.save
@entity.integers #=> [1,2,3,5,6,7]

Now @entity.integers is transparently serialized into the database as
an array.

Just another option.

Rein

Thats fantastic Rein,

I wanted something similar to Mike above, at the moment i manually
unload and load (with YAML) a whole bunch of floats from a binary
field.
Your second solution can make my code much cleaner.

I presume the string size can be enlargened with something
like :limit => 1.megabyte in the migration file?

cheers,
J