Advanced Rails - Building Industrial-Strength Web Apps in Record Time

(Tuis.) #1
Advanced Database Features | 113

For situations such as this, Dr Nic Williams has made composite keys work with
ActiveRecord. Thecomposite_primary_keysgem is available athttp://compositekeys.
rubyforge.org/.


As an example, consider the multimaster sequence problem discussed previously.
We have anOrdermodel that is replicated between two servers using multimaster
replication. We must use a composite key to ensure unique primary keys regardless
of which server an order is created on. First, we install the gem:


gem install composite_primary_keys

Then, we have to require this library in our application. From Rails, we can include
this statement at the end of ourenvironment.rb:


require 'composite_primary_keys'

The next step is to call theset_primary_keys(*keys)method to inform ActiveRecord
that we will be using composite keys:


class Order < ActiveRecord::Base
set_primary_keys :node_id, :order_id
end

After setting up the composite key, most ActiveRecord operations take place as
usual, with the exception that primary keys are now represented by an array rather
than an integer.


Order.primary_key # => [:node_id, :order_id]
Order.primary_key.to_s # => "node_id,order_id"
Order.find 1, 5 # => #<Order:0x1234567 @attributes={"node_id"=>"1",
"order_id"=>"5"}>

Even associations work normally; you only have to specify the foreign key explicitly
on both sides of the association. To demonstrate this, we can add aLineItemmodel
that belongs to a correspondingOrder.


class Order < ActiveRecord::Base
set_primary_keys :node_id, :order_id
has_many :line_items, :foreign_key => [:order_node_id, :order_id]
end

class LineItem < ActiveRecord::Base
set_primary_keys :node_id, :line_item_id
belongs_to :order, :foreign_key => [:order_node_id, :order_id]
end

Note that as in regular associations, the foreign keys are the same on both sides of
the association, as there is only one foreign key that defines the relationship (even
though, in this case, the foreign key is composed of two attributes). This can be con-
fusing if you don’t consider the way the relationship is represented in the schema,
because theforeign_keyoption defined inOrder’shas_many :line_itemsstatement
actually refers to attributes ofLineItem.

Free download pdf