ruby-从Rails中的gem重写模块方法

在我的Oracle版本上,will_paginate gem损坏了。 WillPaginate模块中的默认paginate_by_sql方法在查询中插入了额外的“ AS”并导致查询失败。

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

我不想更改gem本身中的代码,因为那样会使我的代码在其他计算机上损坏。

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

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

并从environment.rb要求它,但是它没有接受我的更改。我也尝试从controllers / application.rb要求它,但是再次,没有取得我的更改。

暂时,我通过重写特定模型本身中的方法使它起作用,但这有点麻烦,这意味着我不能在该项目的任何其他模型中使用它。

我敢肯定有一个简单的方法可以做到这一点,但是我没有运气可以使用Google进行跟踪。

Dave Smylie asked 2020-02-13T05:12:55Z
3个解决方案
67 votes

更简洁的解决方案:

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

将代码放入config / initializers中的初始化文件中。 这是放置环境加载时需要运行的代码的正确位置。 它还可以更好地组织代码,使每个文件的意图更加清晰,从而使错误更易于跟踪。 不要弄乱environment.rb!

Steve Graham answered 2020-02-13T05:14:00Z
49 votes

好的,对于那些像我这样的人,他们在阅读了其他答案后仍然感到有些挣扎,我将使其变得更容易。

首先,通过在gem中搜索要更改的代码行(可以使用pry轻松找到此代码),在github repo上找到要更改的代码,然后选择左侧的.rb(而不是Issues

enter image description here

enter image description here

下一步复制要更改的模块的内容,并将其放入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

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

走开!

Abram answered 2020-02-13T05:14:43Z
29 votes

您正在执行的操作将起作用,但是您的代码需要如下所示:

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

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

Sarah Mei answered 2020-02-13T05:13:35Z
translate from https://stackoverflow.com:/questions/580314/overriding-a-module-method-from-a-gem-in-rails