I’ve been bringing up a good basica framework for applications at work.
To give decent security I’ve been implementing the Rails Recipie for
Authorization of function calls modeled on the book’s implementation.
(Changes for our environment were added…but are minor.)
Since I initially let Rails create the join table between two data
tables with a HABTM relationship…I assumed it would know HOW to do it
correctly. Oh well…maybe not. My tables looked like this:
Rights
ID
name
Roles
ID
rolename
Rights_Roles
ID
right_id
role_id
The ID field is basically unneeded since this table is only for the many
to many relationship. I was getting a problem when trying to add a
second record to the table. It turns out the HABTM relationship was
adding one of the foreign keys as the ID field as well as it’s true
field…causing a key constraint conflict.
My solution was to use a migration to alter the table and drop the ID
field. My rights_roles relationship now seems to be working just fine.
Oh yeah…I had been running on the stable version of Rails 1.1. I
thought that I might have a bug and decided to upgrade to Edge Rails.
(Since I’ve heard Rails 1.2 isn’t far off…it should be fairly close
and I might get a fix for this.) Nope…no dice. Just FYI.
Oh yeah…I had been running on the stable version of Rails 1.1. I
thought that I might have a bug and decided to upgrade to Edge Rails.
(Since I’ve heard Rails 1.2 isn’t far off…it should be fairly close
and I might get a fix for this.) Nope…no dice. Just FYI.
Hope this helps somebody else in this situation.
although it doesn’t specify it in the docs, you are NOT suppose to have
an ID field in the join table.
i’ve had this same problem recently. if you use migrations, the ID
field is created automatically. there is a way to bypass the ID
primary key creation in the migration but I don’t remember where I
read about it - anyone?
i’ve had this same problem recently. if you use migrations, the ID
field is created automatically. there is a way to bypass the ID
primary key creation in the migration but I don’t remember where I
read about it - anyone?
Yeah…I just didn’t find anything quickly and figured somebody would
find this as annoying as I did. It’s trivial to fix, but figuring out
what’s going on, researching to see if I was delusional, and then just
trying it without the ID field…took more time than I want to admit.
This is a my #1 most hated rails bug. The framework should not make
you choose between good db design and simple code. Further this is as
about as far from the principle of least surprise as you can get.
The workaround is to add :select => ‘table.*’ to your habtm
declaration.
Also FWIW, I highly recommend you always add primary keys to all your
tables. This will make it much easier (as opposed to horribly
painful) later when they do (and they often do) become first class
model objects and costs you basically nothing.
The ID field is basically unneeded since this table is only for the many
to many relationship. I was getting a problem when trying to add a
second record to the table. It turns out the HABTM relationship was
adding one of the foreign keys as the ID field as well as it’s true
field…causing a key constraint conflict.
My solution was to use a migration to alter the table and drop the ID
field. My rights_roles relationship now seems to be working just fine.
It’s not a bug, habtm join tables are working as intended. If a join
model is what you want, use has_many :through.
You say Tomato…
Adding a surrogate key to a pure join table certainly isn’t good db
design. You’ll probably want a composite primary key from the two
columns to avoid duplicates.
Obviously it’s not the best design. And I’d rather NOT add complexity
by
either using the surrogate key…or adding the composite key’s
gem…when I really should need it to make this work.
So far just removing the ID field has allowed my code to work. Keeping
it simple because I’m not that bright.
When you start adding fields or gems to make a simple concept work then
you are NOT following the simplest idea behind RoR…to work AS
EXPECTED. When you do it the ‘right’ way you start sounding like a
java guru.
It’s not a bug, habtm join tables are working as intended. If a join
model is what you want, use has_many :through.
This is a bug. Features can be turned off.
Regardless, this ‘feature’ has surprised, confused, and flustered many
a developer. In this regard it minimally violates the spirit of the
framework. Saying “it’s supposed to work that way” misses the point.
The goal is to take the pain out of web development and this is
painful.
Adding a surrogate key to a pure join table certainly isn’t good db
design. You’ll probably want a composite primary key from the two
columns to avoid duplicates.
I beg to differ. I (and many others) would argue tables should always
have a primary key that has no other use (i.e. don’t use composite
keys or keys like SSNs which you think won’t change but sometimes
do, are harder to index, etc). If you don’t you will almost certainly
have messy data problems later.
It’s not a bug, habtm join tables are working as intended. If a join
model is what you want, use has_many :through.
Adding a surrogate key to a pure join table certainly isn’t good db
design. You’ll probably want a composite primary key from the two
columns to avoid duplicates.
This is a my #1 most hated rails bug. The framework should not make
you choose between good db design and simple code. Further this is as
about as far from the principle of least surprise as you can get.
The workaround is to add :select => ‘table.*’ to your habtm
declaration.
Do you literally mean add :select => ‘table.*’ to the declaration or
does “table” represent something?
How does this help and why does it fix the inserts into the join table?
This is a my #1 most hated rails bug. The framework should not make
you choose between good db design and simple code. Further this is as
about as far from the principle of least surprise as you can get.
The workaround is to add :select => ‘table.*’ to your habtm
declaration.
Do you literally mean add :select => ‘table.*’ to the declaration or
does “table” represent something?
How does this help and why does it fix the inserts into the join table?
Thanks,
Wes
OK, I’m a dummy - of course you meant to put actual table names.
However, this does not change the behavior that Steve describes.
Wes
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.