A couple week ago, while I was developing the active_record_uuid gem, I need to do extension to the existing methods in active_record
library. The first one is to send portal_uuid
instead of portal_id
in the association methods such as has_many
, …. The second one is about quoting uuid
value and send it to mysql
. I went to see the source code of active_record
to find where the best place to do my job. After spending some times to understand the codebase, I find the place to overwrite, ActiveRecord::Associations::ClassMethods
and ActiveRecord::ConnectionAdapters::Quoting
. The first thing that comes to my head is to do alias_method_chain
of these methods. I didn’t think much, write the test and implement it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Read that code again, I realized there are two things that my code could be changed in the future. Those are the module and method’s name. If one day the Rails
team decide to change the module name, then I would have to do another commit to fix that. In addition, method name is a bit longer and cumbersome as well.
I took one step back and think about it again. That module is simply included into ActiveRecord::Base
. From here, it reminds about my ruby lesson. Ruby method lookup path is the reverse order of module inclusion. Why Ruby does that? Well, it is because it is designed to be extensible.
Therefore, if I define another module and include it very last, my method should be run before the original method. That’s cool, isn’t it? Calling the original version is even easier, call #super
will does the job. It’s awesome.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
The question arrives to my head. What is the use of alias_method_chain
? What is it for? Well, in the above case, I wouldn’t need it, but it’s still useful to overwrite the methods which are defined originally in that class.
1 2 3 4 5 6 7 8 9 10 11 |
|
There is no use if I include
MyModule
into Person
class, because Ruby will run the method inside that class, then the method inside the module. In this case, only alias_method_chain
could help.
It’s hard to see any good guidelines to do extensions when developing the gem, but here it’s a better way to do the job.