We are deep in the process of migrating from Rails 2.3.14 / CPK 2.3.2 to Rails 3.2.8 / CPK 5.0.9. CPK seems to be working for associations where composite foreign keys are being mapped to composite primary keys.
However, we have several belongs_to legacy database tables where the primary key is a single column that corresponds to the concatenated (or otherwise transformed) values of the composite foreign keys.
When we first implemented CPK several years ago in Rails 2.x, my colleague googled up a solution for this problem. But the solution does not work on Rails 3.x, and my colleague is unable to locate the prior googled reference to see if any Rails 3.x discussion has been added.
In pseudo-code here is what we were doing on Rails 2.x:
class PerPay < ActiveRecord::Base
belongs_to :leave_grp,
:primary_key => :pk_di_lg, # non-existent col refers to dynamic finder class method find_by_pk_di_lg
:foreign_key => [:di_no, :leave_group]
end
class LeaveGrp < ActiveRecord::Base
set_primary_key :codex_4 # di_no + leave_group
def self.find_by_pk_di_lg(*args)
opts = args.extract_options!
pk_di, pk_lg = args.first # :foreign_key is an array in the belongs_to
find(('%02d' % pk_di) + pk_lg)
end
end
In PerPay, :di_no is integer (i.e. 39) and :leave_group is string (i.e. 'AV'). In LeaveGrp, the :codex_4 primary key is a 4-char string, i.e. '39AV'. By specifying the belongs_to :primary key to be a non-existent column on Rails2, the dynamic finder in the target table would be invoked, and we would concatenate the multiple foreign keys passed by CPK, then do a find.
This does not work on Rails3. Rather than invoking the LeaveGrp.find_by_pk_di_lg() method, SQL gets generated referring to the non-existent pk_di_lg column, which fails.
Changing the legacy LeaveGrp table is not an option. For performance purposes, we really need to access that table by the true :codex_4 primary key.
One solution would be to abandon the belongs_to association entirely and just make this a regular method within the PerPay model to retrieve the LeaveGrp row, but we prefer to stay as Rails-ish as possible and Rails encourages associations.
Thanks...