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

发布于 2024-08-09 09:44:52 字数 727 浏览 11 评论 0原文

好吧,标题很混乱,我先告诉你我的问题:

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 模块中定义。我真的不知道它何时/在何处混合到控制器/视图中。

我怎样才能以我想要的方式包装这个方法?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

国际总奸 2024-08-16 09:44:52

在我们继续之前,您确定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 核心之后加载的最佳方法是将其变成插件。

$ 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 根目录的库中,但我不确定您将需要的代码放置在正确的时间运行它的确切位置。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文