Rails, Composite Keys, OpenMRS and Cloning
openmrs softwareWell, I just spent a good few hours pouring over some code and finally found the problem. Composite Keys. In OpenMRS there are 12 tables that use composite primary keys. I think we have mentioned that this is easily handled in rails using the composite_keys gem and set_primary_keys function in the respective models. What I didn’t know is that things get a little wacky when you try to clone an ActiveRecord object that has composite keys.
p = PatientIdentifer.new p.patient_id = 2 new_patient = p.clone new_patient.patient_id = 3 NoMethodError: undefined method `patient_id=' ...
The clone method in ActiveRecord actually deletes the primary key from the list of attributes. This way if you save it, it will act like a new record. Of course when there are multiple primary keys and they are not autoincrementing this is a problem, because you can’t set them and can’t save the clone. Ever. What is needed is an alternate clone function when the model is composite. So I hacked this together and threw it in our OpenMRS model that is the basis of all our ActiveRecord models in this application.
# cloning when there are composite primary keys # will delete all of the key attributes, we don't want that def composite_clone if composite? attrs = self.attributes_before_type_cast self.class.new do |record| record.send :instance_variable_set, '@attributes', attrs end else clone end end
Now, ideally this would go into a module and I would use alias_method and map clone to orig_clone, then override the actual clone method. But let me just tell you that doesn’t work. Or didn’t work. Something to do with order of operations or some such. If you can get that working please comment.
Add comment March 20th, 2007
