覆盖Rails核心mixin方法,并且仍然能够调用旧方法

时间:2009-10-25 09:37:48

标签: ruby-on-rails alias-method-chain

好的标题令人困惑,我首先告诉你我的问题:

在Rails 2.2.1中更改了polymorphic_url方法,以包含我需要的一些额外功能。但是,我想让应用程序仍然可以在旧版本的Rails中运行,所以如果旧的Rails版本正在运行,我想修补2.2.1行为。

alias_method_chain救援对吗?我无法让它发挥作用。

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

现在我首先尝试将其放在帮助器中 - alias_method_chain失败,因为polymorphic_url当时没有定义。 所以我将相同的代码移动到控制器中,它没有错误,但它被忽略了。 然后我尝试使用插件将其修补到ApplicationController :: Base中 - polymorphic_url仍未定义。

polymorphic_url在模块ActionController :: PolymorphicRoutes中定义。我真的不知道它何时/在哪里被混合到控制器/视图中。

如何以我想要的方式包装此方法?

1 个答案:

答案 0 :(得分:3)

在我们继续之前,你确定在2.2.1之前的Rails版本中存在polymorphic_url吗?

您的代码大部分是正确的,您忘记调用该方法的原始版本。在alias_method_chain调用之后,将其重命名为polymorphic_url_without_compat。

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

您提到过您尝试将其添加到插件中,因此如果前一位修复了您的问题,则可能不需要以下内容。

确保在rails core之后加载的最佳方法是将其变成插件。

$ script/generate plugin polymorphic_url_backport

将创建一个插件存根。从这一点开始的所有方向都与创建的插件目录相关。

在init.rb中添加

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

然后将上面的代码粘贴到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  

只需确保插件附带您的应用程序,应该没有问题。你可以将它添加到rails root的lib中,但是我不确定你在哪里放置require代码来在正确的时间运行它。