ActiveRecord - How are Associations stored/generated? Need to import XML to Postgres database in Sinatra App

StackOverflow https://stackoverflow.com/questions/23679340

Question

I have an XML dataset I am trying to import into a Postgresql database to be used by a Sinatra app.

The data consists, essentially, of:

ArchiveObjects
Tags

I would like to define these relationships in my DB Migration:

ArchiveObject - has_many Tags
ArchiveObject - has_many_and_belongs_to ArchiveObjects
Tag - belongs_to ArchiveObject

We can manipulate the XML and were thinking it is best to treat this relationship as an array of ID's, for example:

ArchiveObject.tags = [Array, of, Tags]

However, I'm unsure how we should format the XML, am I correct in assuming that the migration has_many :Tags creates a column to hold an array? Or does ActiveRecord do something completely different? (eg: Create a junction table)

Was it helpful?

Solution

has_many :tags will imply that the database schema will look as follows

create table archive_object(
   id int not null
);

create table tag(
   id int not null,
   archive_object_id int not null
);

i.e. each tag record will contain the id of the archive object that it belongs to.

So there is a column involved, but it doesn't contain an array struct, it contains a reference to another table, and it is the Owned object that contains a reference to its parent.

Edit: An attempt to further explain this.

Given the structures:

A1 : ArchiveObject, A1.tags => [T1, T2, T3]
A2 : ArchiveObject, A2.tags => [T4, T5]

You would have the SQL tables:

archive_objects
id | name
-------------
 1 | A1
 2 | A2

tags
id | archive_object_id | name
-----------------------------
 1 |                 1 | T1
 2 |                 1 | T2
 3 |                 1 | T3
 4 |                 2 | T4
 5 |                 2 | T5

This is the whole point behind a relational database model - the logical list of [T1,T2,T3] belonging to A1 is mapped as a table with 3 rows, linked in a SQL join:

A1.tags # would run the query SELECT * FROM tags WHERE archive_object_id = 1;
A2.tags # would run the query SELECT * FROM tags WHERE archive_object_id = 2;

and is part of the heavy lifting that ActiveRecord endeavours to do for you.

Edit 2: demonstration of how to create and save an ArchiveObject

class ArchiveObject < ActiveRecord::Base
    has_many :tags
end

class Tag < ActiveRecord::Base
    belongs_to :archive_object
end

# create a structure
ao = ArchiveObject.new({
        :name=>'A1',
        :p1=>'some param',
        :p2=>'some other param'})

t1 = Tag.new({
         :name=>'T1',
         :somevalue=>'S1',
         :someothervalue=>'S2'})
t2 = Tag.new({
         :name=>'T2',
         :somevalue=>'S3',
         :someothervalue=>'S4'})

ao.tags = [t1, t2]
ao.save

# at this point you have a record in archive_objects and two records in tags

Any fields you want present in either ArchiveObject or Tags you would generate through a migration.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top