Is it possible to have a compound foreign key in rails?

和自甴很熟 提交于 2019-12-05 09:10:00
Bill Karwin

There is apparently an project at sourceforge to extend Rails' ActiveRecord with support for Composite Primary Keys. I haven't used this extension, but it might help you. It's also a gem at rubyforge.

Plain Ruby on Rails, as of version 2.0, does not support compound primary keys (cf. HowToUseLegacySchemas). Every table must have a single-column, auto-increment key named "id".

The explanation I have seen is: "You only need compound primary keys if you want to use a legacy database." This is of course a ridiculously ignorant view of data modeling.

The solution I see would be:

  • Usage.client_id -> Client.id
  • Usage.type_id -> Usagetype.id
  • Usage.resource_id -> Resource.id
  • Billing.usage_id -> Usage.id
  • Billing.client_id -> Client.id
  • Billing.type_id -> Usagetype.id
  • Billing.resource_id -> Resource.id

The apparently redundant foreign keys in Billing attempt to enforce partial referential integrity. But it doesn't quite get there -- it does not prevent you from creating rows in Billing that reference a row in Usage with the wrong client/resource/usagetype combination, not matching those in the referencing row in the Billing table.

edit: @Yarik: yes, you're right. It makes more sense for Usage to reference Billing.

  • Usage.billing_id -> Billing.id

Hmm. I made an ER diagram but I'm having trouble inserting it as an image.

You can create any constraint you want with the 'execute' command in a migration.

You would probably want to add some error handling to .save to deal with cases when the constraint throws an error.

You can't use AR's built-in method generators to generate the usages off the billing, but you can still have the method:

class Billing
  def usages
    Usage.find(:all, :conditions => ["x = ? and y = ?", self.x, self.y])
  end
end
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!