Simplified schema of my tables -
Users Table:
operatorid: integer, pk
gropuid: integer
...
Events Table:
operatorid: integer, pk
colid: integer, pk
contextid: integer, pk
hash: varchar
partition: date
...
Data Table:
hash: varchar, pk
partition: date, pk
data: blob
...
I am trying to pull information for a report using an existing
Postgres DB. I have users, events and data tables. Users are
associated with Data via Events. Enter the first problem.
The relations between Users and Events. The User relation with the
Events table is only via the operatorid. However, the PK for the
Events table include colid and contextid. (Don't ask my why, I just
work here). I setup the Events model with "set_primary_keys" on all
three of the existing PK's in Events because thats what the DB schema
says. I then created the 1:N relation in Events with
"belongs_to :user, :foreign_key => :operatorid". The Users model has a
has_many :events, :foreign_key => :operatorid.
Problem 1: When using irb I tried to grab event User.events but I get
the following error: Incorrect number of primary keys for Events:
[:operatorid, :colid, :contextid]. It looks like the composite key is
trying to enforce the key. (Which I would say is the right thing to
do, but not the most compatible thing to do). Why doesn't is just use
the belongs_to foreign_key assignment? Should I be using :through?
My Solution/Hack 1: I am still very new to Ruby and RoR so I am not
sure if this is the right way, but it did work. I added the following
def to my User model:
<code>
def skip_pk_check_events
Events.find( :all, :conditions => { :operatorid =>
self.opeartorid } )
end
</code>
Now I can access my events from irb with user.skip_pk_check_events[]
I'd rather still have user.events[] work. Is that possible? Or is my
hack the best way?
Now that I have my Event I want to start accessing its data. Enter
Problem 2
Problem 2: The Events table has an attribute called hash. This breaks
AR because hash is a reserved word.
Solution 2: I added the following code to my Event model:
<code>
def my_hash
self['hash']
end
def my_hash=(value)
self['hash'] = value
end
class << self
alias :all_columns :columns
def columns
all_columns.reject {|c|
c.name == 'hash'}
end
end
</code>
This stopped AR from dieing with a DangerousAttributeError. It also
allows me to access my table.hash value via my_has (Event.my_hash will
return the orig value)
Now that I have a handle on event, and can access its attributes, I
want to get at the real data in Data.
I added a has_many :data, :foreign_key[:my_hash, :parition] to my
Events model (Note, I tried both my_hash and hash, both give me the
same problems coming up). I created my Datum model with
set_primary_keys :my_hash, :partition #Note I tried both hash and
my_hash. I also added belongs_to :event, :foreign_key =>
[:hash, :partition]. Since Data also has an attribute called hash I
added the same "hack" I used for the Events model.
Problem 1) When I load an event, and try to access data (event.data) I
get the following error:
IndexError: element size differs (3 should be 2)
from /usr/lib/ruby/gems/1.8/gems/composite_primary_keys-0.9.91/
lib/composite_primary_keys/associations.rb:267:in `transpose'
from /usr/lib/ruby/gems/1.8/gems/composite_primary_keys-0.9.91/
lib/composite_primary_keys/associations.rb:267:in
`full_columns_equals'
from /usr/lib/ruby/gems/1.8/gems/composite_primary_keys-0.9.91/
lib/composite_primary_keys/associations.rb:285:in `construct_sql'
from /usr/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/
active_record/associations/has_many_association.rb:6:in `initialize'
Problem 2) When I load the a datum, and try to access the event
(datum.event) I get the following error:
RuntimeError: [nil, Wed, 20 Feb 2008]: Incorrect number of primary
keys for Event: [:operatorid, :colid, :collectioncontextindex]
from /usr/lib/ruby/gems/1.8/gems/composite_primary_keys-0.9.91/
lib/composite_primary_keys/base.rb:250:in `find_from_ids'
from /usr/lib/ruby/gems/1.8/gems/composite_primary_keys-0.9.91/
lib/composite_primary_keys/base.rb:245:in `each'
from /usr/lib/ruby/gems/1.8/gems/composite_primary_keys-0.9.91/
lib/composite_primary_keys/base.rb:245:in `find_from_ids'
from /usr/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/
active_record/base.rb:504:in `find'
from /usr/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/
active_record/associations/belongs_to_association.rb:44:in
`find_target'
It looks like these errors are again the result of composite keys
trying to enforce the PK. So.. should I solve this problem like I did
with User::Events? (Create my own def to handle the query)