Well, I don't have an actual answer for you. But.....
Why, oh why, are you using composite primary keys if you're creating
the table? I can certainly see having the need with legacy databases,
where you have no control over the design. However, given that you are
showing a migration in your original post, then why are you making
your life unnecessarily complicated?
Why not just give Rails its simple integer primary key? Rails will be
happier, you will be happier, in the long run, and all will be right
with the world.
Now don't get me wrong, there may be a perfectly reasonable need in
your case. I don't have all the facts here. But, as many on this list
have said before, "Fight Rails and it will fight back."
I don't find this unique to Rails. I see this with just about any
object-relational mapping systems. It's usually best to have a simple
identifier that can be managed entirely by the framework whenever
possible. Rows in a database become object instances. Having that one-
to-one, object-to-row identity just makes things run much smoother.
All that aside, looking at your programmes table it sure looks to me
like a perfectly resaonable join between courses and programes. Why,
do you need a composite_primary_keys plugin for this anyway? Why not
just let Rails handle that relationship for you using a has_many?
has_many :somethings :through => :programmes <-- ??? wait a
second, is this many-to-many or one-to-many?
--- one-to-many ---
--- migration ---
class CreateProgrammes < ActiveRecord::Migration
create_table :programmes do |t|
t.column :programme_code, :string, :null => false << --- Not
the table's PK but a unique programme code column
t.column :course_id, :integer
t.column :type, :string
t.column :last_updated, :timestamp, :null => false
add_index :programmes, :programme_code, :unique => true
Note: This table will have an id column since you didn't tell Rails
not to create one.
--- Before Save ---
Then write a before_save method to generate a user presentable
programme_code for display in your interface.
Again, I'm speculating a lot here. I just wanted to make sure you're
thinking about this the right way.