"Extending" classes: redefining an instance method from a module via alias_method

Posted by Tim Connor Tue, 24 Oct 2006 07:50:00 GMT

The Typo plugin is finished, but it’s gotten late and I should review it before deploying and releasing it into the wild. A quick post on more I learned, though….

I had to do a fair bit of research to get the second part of the plugin working – the part where I overload/redefine a controller method from my plugin, specifically the permalink method of an ArticlesController. You can spend a lot of time reading about the intricacies of how mixins work in ruby, without getting working code. Dig through ruby-talk and you’ll learn about the difference between include/extend, what happens to “self” in different cases, the reasons for the odd module nesting and, ultimately why the ClassMethods convention caught on.

It’s not so straight-forward to overload a method, apparently, in ruby. God knows I tried each different nesting include/extend combo 6 times, with no luck. Then I came across an easier way for my case, alias_method. While that usage wasn’t exactly what I wanted, the only problem was that it did too much. I just had to drop off the unneccessary bits, and walla:

module TypoPermalinkWithId
  ....

  module ModifyArticlesController
    def self.included(base)
      base.class_eval do
        alias_method :permalink, :modified_permalink
      end
    end
    def modified_permalink
      article = this_blog.published_articles.find_by_permalink(*params.values_at(:year, :month, :day, :title))
      redirect_to article.permalink_url and return if article.nil? and article = Article.find_by_id(params[:title].to_i)
      redirect_to article.permalink_url and return if article.nil? and article = Article.find_by_title(params[:title])
      display_article(article)
    end
  end
end

ArticlesController.send :include, TypoPermalinkWithId::ModifyArticlesController