how to override a mixin method, but then call the overridden method within this??? (e.g. like calling "super")

Hi,

Can anyone recommend how to override a mixin method but then call the overridden method within this??? (e.g. like calling “super”)

Specifically I would like to provide an overridden “link_to” method to my views which would add a params[:locale] parameter to the mix and THEN call the original/rails “link_to” method after this. Like a “super” type call.

Any suggestions on how to do this sort of overridding/overloading with mixin methods?

Thanks

Greg Hauptmann wrote:

Can anyone recommend how to override a mixin method but then call the overridden method within this??? (e.g. like calling "super")

Specifically I would like to provide an overridden "link_to" method to my views which would add a params[:locale] parameter to the mix and THEN call the original/rails "link_to" method after this. Like a "super" type call.

Any suggestions on how to do this sort of overridding/overloading with mixin methods?

To have access to the original link_to as link_to_orig, put this in your helper module:

   def self.append_features(base)      base.class_eval 'alias :link_to_orig :link_to'      super    end

excellent - thanks

Is there any good tutorial on advanced use of Ruby to perform these types of tweaks that are available? e.g. other key ruby methods that help in injecting/overriding methods etc?

Anyone pick why this modified version of “url_for” doesn’t seem to be picked up by a “url_for” in one of my views? (i.e . it still seems to use the original rails version)

============== application_helper.rb =============== module ApplicationHelper

def self.included(base) base.class_eval do alias_method :link_to_old, :link_to unless method_defined?(:link_to_old)

  alias_method :link_to, :link_to_new
end

end

def link_to_new return “link_to_newTEXT” end

end

Mark Reginald James :

Greg Hauptmann wrote:

> Can anyone recommend how to override a mixin method but then call the > overridden method within this??? (e.g. like calling "super") > > Specifically I would like to provide an overridden "link_to" method to > my views which would add a params[:locale] parameter to the mix and THEN > call the original/rails "link_to" method after this. Like a "super" > type call. > > Any suggestions on how to do this sort of overridding/overloading with > mixin methods?

To have access to the original link_to as link_to_orig, put this in your helper module:

   def self.append_features(base)      base.class_eval 'alias :link_to_orig :link_to'      super    end

Hi Mark and Greg,

I think it should work with alias_method_chain : http://weblog.rubyonrails.com/2006/4/26/new-in-rails-module-alias_method_chain

alias_method_chain :link_to, :locale so you can access to link_to_without_locale

best,

    -- Jean-François.

thanks Mark,

So this is basically what I had in the previous post (which wasn’t working) but adds the “base.extend(ClassMethods)”?

So my take of this is I hadn’t allowed the ClassMethods to be extended then, and that’s why it wasn’t working???

oh oh - just tried this Mark and this doesn’t work in fact…something to do with using this technique within application_helper.rb and access the updated method (link_to) from a view??

Can anyone help here? The following is still not working. Again I’m trying to override for my views the “link_to” method, but within my version I still need to call the real rails “link_to” version at the end.

The problem with the code below is it never actually triggers the views to use a different version of “link_to”.

Suggestions?

======= application_helper.rb =================== module ApplicationHelper

def self.included(base) base.extend(ClassMethods) base.class_eval do alias_method :link_to_old, :link_to unless method_defined?(:link_to_old) alias_method :link_to, :link_to_new end end

def link_to_new (*args) link_to “test text” <==== THIS NEVER GETS CALLED end

end ======= application_helper.rb ===================

Thanks in advance

bump (just really keen to understand this stuff & where I’m going wrong if someone knows)

Greg Hauptmann wrote:

Can anyone help here? The following is still not working. Again I'm trying to override for my views the "link_to" method, but within my version I still need to call the real rails "link_to" version at the end.

The problem with the code below is it never actually triggers the views to use a different version of "link_to".

Suggestions?

======= application_helper.rb =================== module ApplicationHelper

  def self.included(base)     base.extend(ClassMethods)     base.class_eval do       alias_method :link_to_old, :link_to unless method_defined?(:link_to_old)       alias_method :link_to, :link_to_new     end   end    def link_to_new (*args)     link_to "test text" <==== THIS NEVER GETS CALLED   end end

Yes, it looks like this sort of technique won't work with helpers because Rails first includes all the relevant application helper modules into an anonymous master helper module, before including that in the controller and view template classes (in which the Rails helpers have already been included). So the alias has to be delayed by one include step. Is there any nice way to do this other than trying to push into the master module its own included/append_features method?

As for the details of what the above code is doing: You only need the "base.extend(ClassMethods)" if you want to define class methods on the target class or module, not usually needed for controllers and views. And append_features is called before the module methods are included, so you can name your method link_to and simply alias the old one. The included method is called after the module's methods are included, so you need two aliases.