在Rails中从一个gem重写一个模块方法

在我的Oracle版本中,will_paginate gem被打破了。 WillPaginate模块中默认的paginate_by_sql方法会在查询中插入一个额外的“AS”,导致它失败。

代码本身很容易修复,但我不确定让Rails接受我的更改的最佳方式。

我不想更改gem本身的代码,因为这会使我的代码在其他机器上断开。

我试图创build一个lib / test.rb文件,其中包含:

 module WillPaginate def paginate_by_sql (my code goes here) end end 

并要求从environment.rb,但它没有拿起我的变化。 我也尝试要求从控制器/ application.rb,但再次,不接受我的变化。

暂时我通过重写特定模型本身的方法来实现它,但是这有点破解,意味着我不能在这个项目的任何其他模型中使用它。

我确信有一个简单的方法来做到这一点,但我没有任何运气使用谷歌追踪它。

你在做什么都可以,但是你的代码需要像这样:

 module WillPaginate module Finder module ClassMethods def paginate_by_sql(sql, options) # your code here end end end end 

换句话说,进入finder.rb,删除除了模块标题和要覆盖的方法之外的所有内容,然后保存到lib文件中,并包含在environment.rb中。 瞧,即时猴子补丁!

更简洁的解决scheme:

 WillPaginate::Finder::ClassMethods.module_eval do def paginate_by_sql sql, options # Your code here end end 

把代码放入一个初始化文件在config / initializers中。 这是加载环境时需要运行的代码的正确位置。 它也更好地组织你的代码,使每个文件的意图更清晰,因此错误将更容易追查。 不要搞乱environment.rb!

好吧,我只是想让像我这样的人过来,在阅读其他答案后仍然有点困难。

首先通过search代码行(你可以很容易地find这个使用pry )你想在gem中进行更改,然后selectCode在左边,而不是Issuesfind你想要更改在github repo上的代码

在这里输入图像说明

在这里输入图像说明

下一步复制要更改的模块的内容,并将其放置在config / initializers文件夹内的一个合适的.rb文件中。 这里是一个例子:

 module Forem module TopicsHelper def link_to_latest_post(post) text = "#{time_ago_in_words(post.created_at)} #{t("ago_by")} #{post.user}" link_to text, forum_topic_path(post.topic.forum, post.topic, :anchor => "post-#{post.id}") end end end 

现在,将其更改为:

 Forem::TopicsHelper.module_eval do def link_to_latest_post(post) text = "#{time_ago_in_words(post.created_at)} #{t("ago_by")} #{post.user}" link_to text, forum_topic_path(post.topic.forum, post.topic, :anchor => "post-#{post.id}") end end 

现在,对代码进行任何其他更改并重新启动服务器。

你走吧!