views:

1326

answers:

7

So I've got two models, State and Acquisition. State has_many Acquisitions. I felt like an autoincrementing integer primary key for 51 records was rather silly. So I altered the model for the State to be the PK (State being the two letter abbreviation; I'm not storing the actual state name anywhere:

class State < ActiveRecord::Base  
    self.primary_key = "state"  
    has_many :acquisition_histories  
end

The problem is when I created my Acquisition model, it created the foreign key column state_id as an integer. More specifically, the script/generated migration did:

class CreateAcquisitions < ActiveRecord::Migration  
    def self.up  
        create_table :acquisitions do |t|  
          t.date :date  
          t.string :category  
          t.text :notes  
          t.references :state  
          t.timestamps  
    end
end

I'm assuming that t.references data type sets it to int. The problem is my create method on my Acquisition class is trying to put a state abbreviation into the state_id field on the table acquisitions (and yes, it's called state_id on the database, even though it says :state in the migration script). The method doesn't fail, but it does put a 0 in the state_id field and the records go into the ether.

+7  A: 
John Topley
Well, there's a (probably memory-cached and tiny) database overhead when you have to keep including the state table to get the code. But it's probably over-optimisation. I do that, but I'm old and it used to matter more in VAX 8700 days.
Mike Woodhouse
For that sort of thing I tend to define a constant in the State class i.e. ALL = State.all and then use State::ALL as the source for dropdowns etc. That way, the SQL query only runs at start-up in Production.
John Topley
I'm not worried about performance at all, I just don't like the concept of an extra unique identifier. But I'm going to go back with the convention, assuming I can figure out how to back everything back out. I'm fairly new to Rails.
fr0man
+3  A: 

You want to follow the Rails conventions. The extra primary key is not an issue in any way. Just use it.

August Lilleaas
A: 

I had a bit of experience with string used as primary keys and it's a pain in the ***. Remember that by default if you want to pass an object with the default :controller/:action/:id pattern, the :id will be a string and this will probably lead to routing problems if some ids get weirdly formatted ;)

+1  A: 

I'm working on a project that uses UUIDs as primary keys, and honestly, I don't recommend it unless you're certain you absolutely need it. There are a ton of Rails plugins out there that will not work unmodified with a database that uses strings as primary keys.

Bob Aman
A: 

I really need a long as a primary key, because my real primary key...is bigger than a breadbox. Is there really no sensible way to work around atleast having a non-default type?

+2  A: 

Proper relational database theory in Rails? oh no no... that's bad. You will burn in the fiery pits of RoR hell!