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?

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

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