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.