在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
在左边,而不是Issues
find你想要更改在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
现在,对代码进行任何其他更改并重新启动服务器。
你走吧!