has_many with different primary key

I've got quite the ActiveRecord challenge, any help would be appreciated.

  In my current project Companies can have many reviews.

class Company < ActiveRecord::Base   has_many :reviews, :as => :reviewable end

  However, my company table, I have two different IDs to identify my company.

id - This is the typical id we use for normal stuff other_company_id - This is the id we use for reviews (on a shared db)

  Don't ask why, we're integrating two systems. So, rather then using id as the primary key for the relationship (as the above code would do) I want to use other_company_id for the primary key. It'd be great if I could do this:

class Company < ActiveRecord::Base   has_many :reviews, :as => :reviewable, :with_primary_key => :other_company_id end

  It would then use the other_company_id to lookup and create reviews. Unfortunately, Rails has no such option.

  There has to be someone else out there that has run into this limitation. Thanks in advance for the help.

Gregg Pollack RailsEnvy.com

Do you mean :foreign_key => “other_company_id”?

Nope, the opposite of that. Rather then specifying a different foreign key, I want to specify a different primary key from the has_many side of the relationship.

Another way to write what I'm trying to do (but it doesn't work) is:

class Company < ActiveRecord::Base   has_many :reviews, :as => :reviewable, :dependent => :destroy do     Company.set_primary_key "hr_company_id"   end end

I want to have a different primary key when referencing the relationship.


Ryan Bigg wrote:

So there’s a field inside the reviews table that is hr_company_id and represents an ID for the linked company? :foreign_key does exactly what you’re explaining unless I’m getting it horribly wrong or misinterpreting what you’re saying.

Say I have blogs and comments with model blog has_many :comments and the comments table has a field called hr_blog_Id, I specify :foreign_key => “hr_blog_id” on the has_many and it works.


:foreign_key allows you to specify a different field for the "belongs_to" side of the relationship. What I'm talking about is the has_many side.

Company has two primary_keys which it needs to use at different times. Some tables it uses "id" for the relationship, some tables it uses "hr_company_id" for the relationship.

On the Reviews side (the belongs_to side of the relationship), which is a polymorphic table, the foreign_key is ALWAYS reviewable_id. This foreign key does not need to change, so I wouldn't want to specify a different foreign_key.

What I need to specify is a different primary key for the relationship to be referenced by. Typically when you need to use a different primary key on a table you call "set_primary_key".

I want to have a different primary key, just when referencing this relationship.

companies.hr_company_id (primary key - has_many side) => reviews.reviewable_id (foreign_key belongs_to side)

I'm pretty sure I'm not going to be able to do this without monkey patching ActiveRecord somehow.


Ryan Bigg wrote:

You are correct, you can set it on both sides to identify a different foreign_key. Unfortunately I don't need to change the foreign_key, I need to change the primary key.

Anyone else want to chime in here?

Ryan Bigg wrote:

I've been struggling with this problem as well. a possible solution to this might be to create a new class for the secondary primary key, something like:

Company2 << Company   set_primary_key :hr_primary_key_id end

and then use Company2 when you want to get the alternate has_many association.

Something else which has occured to me, is that maybe you could use a habtm association. but then you'd need to make access Company as a join model for this particular operation and you'd need to have something else on the left of it.

not sure how much any of this helps as its purely hypothetical but i'm interested to see where this discussion goes.

Cheers, -vince


   Thanks for the response. I've considered using a subclass, which does get around the problem in some circumstance. Unfortunately in my case, I'm using a polymorphic association.

   I would need to somehow define a different "type" when the polymorphic association gets stored, because it would store the subclass type as "reviewable_type = Company2". So I would need some way to override the class name in the polymorphic association. I haven't found this is possible.

   I wonder how hard it would be to patch rails to do:

   has_many :reviews, :as => :reviewable, :with_primary_key => :hr_company_id


vincey wrote:


Facing the same problem here but with the simpler case of non-polymorphic has_many association. We use the standard 'id' for most associations but we also have a 'uuid' field that I need to associate on. Using your Company/Review example it would be like this:

companies has a uuid column as uniqe index reviews has a company_uuid column

Company has_many :reviews, :foreign_key => "company_uuid"

Now, I'd need reviews.company_uuid to join on companies.uuid and not companied.id.

Using a new class to set_primary_key is not really an option because instantiated Company objects through activerecord finders won't work for this association.

Any other suggestions/ideas?

I am working on this right now, I'll keep you posted of my finding.


Gregg Pollack wrote:

Found this on lighthouse http://rails.lighthouseapp.com/projects/8994/tickets/765-primary_key-option-for-belongs_to

seems they are going that direction for being able to specify :primary_key is associations.


Hey Gregg Pollack,

Have you found the solution for the issue. I'm also facing the same problem and found this is the ditto problem. Would like to hear if you found some solution to it ??

Thanks Akshay

Hey Gregg Pollack,

Have you found the solution for the issue. I'm also facing the same problem and found this is the ditto problem. Would like to hear if you found some solution to it ??

has_many takes a :primary_key option.


Hey Frederick,

Thats what i did and thought its working fine after going through the documentation. But surprisingly its not working that way its supposed to be :frowning:


Frederick Cheung wrote: