views:

198

answers:

1

Ok title is confusing, Ill tell you my problem first:

the polymorphic_url method was changed in Rails 2.2.1 to include some extra functionality I need. However, I want to make the application still work in older versions of Rails, so I wanted to patch on the 2.2.1 behaviour if an older Rails version is running.

alias_method_chain to the rescue right? I cant get it to work.

def polymorphic_url_with_compat(*args)
  whatever...
  return polymorphic_url(*args)
end
alias_method_chain :polymorphic_url, :compat

Now I first tried putting this in the helper - alias_method_chain fails because polymorphic_url isnt defined by then. So I moved the same code into the controller, and it doesnt error, but it gets ignored. Then I tried patching it into ApplicationController::Base with a plugin - polymorphic_url is still not defined.

polymorphic_url is defined in the module ActionController::PolymorphicRoutes. I dont really know when/where it is mixed into the controller/view.

How can I wrap this method in the way i want to?

+3  A: 

Before we proceed, are you sure that polymorphic_url existed in Rails version prior to 2.2.1?

You're code is mostly right, you're forgetting to call the original version of the method. Which is renamed polymorphic_url_without_compat after the alias_method_chain call.

class ActiveRecord::PolymorphicRoutes
  def polymorphic_url_with_compat(*args)
    whatever...
    return polymorphic_url_without_compat(*args)
  end
  alias_method_chain :polymorphic_url, :compat
end

You mentioned you tried to add it to a plugin, so the following may not be necessary if the previous bit fixed your problem.

The best way to ensure it's loaded after the rails core, is to turn it into a plugin.

$ script/generate plugin polymorphic_url_backport

Will create a plugin stub. All directions from this point on are relevant to the created plugin directory.

In the init.rb add

if RAILS_GEM_VERSION < "2.2.1"
  require File.dirname(__FILE__) + '/lib/yournamespace'
  ActionController::PolymorphicRoutes.send(:include, YourNameSpace::ActionController::PolymorphicRoutes) 
end

Then paste the above code into your lib/yournamespace.rb

module YourNameSpace
  class ActiveRecord::PolymorphicRoutes
    def included(base)
      base.class_eval %~
        def polymorphic_url_with_compat(*args)
          whatever...
          return polymorphic_url_without_compat(*args)
        end
        alias_method_chain :polymorphic_url, :compat
      ~
    end
  end
end

Just make sure the plugin ships with your application and there should be no problems. You could alternately add this to the lib of your rails root, but I'm no sure exactly where you would place the require code to run it at the right time.

EmFi
nice :). thx EmFi!
reto