Suppose the following data schema:
Usage
======
client_id
resource
type
amount
Billing
======
client_id
usage_resource
usage_type
rate
In this example, suppose I have multiple resources, each of which can be used in many ways. For example, one resource is a widget
. Widgets
can be foo
ed and they can be bar
ed. Gizmo
s can also be foo
ed and bar
ed. These usage types are billed at different rates, possibly even different rates for different clients. Each occurence of a usage (of a resource) is recorded in the Usage table. Each billing rate (for client, resource, and type combination) is stored in the billing table.
(By the way, if this data schema is not the right way to approach this problem, please make suggestions.)
Is it possible, using Ruby on Rails and ActiveRecord, to create a has_many
relationship from Billings to Usages so that I can get a list of usage instances for a given billing rate? Is there a syntax of the has_many, :through
that I don't know?
Once again, I may be approaching this problem from the wrong angle, so if you can think of a better way, please speak up!
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
来源:https://stackoverflow.com/questions/279791/is-it-possible-to-have-a-compound-foreign-key-in-rails