Переопределение метода модуля из гема в Rails
Гем will_paginate не работает в моей версии Oracle. Метод по умолчанию paginate_by_sql
в модуле WillPaginate вставляет дополнительный AS в запрос и вызывает его сбой.
Сам код легко исправить, но я не уверен, как лучше всего заставить Rails принять мои изменения.
Я не хочу менять код в самом геме, так как это приведет к поломке моего кода на других машинах.
Я попытался создать файл lib / test.rb, содержащий:
module WillPaginate
def paginate_by_sql
(my code goes here)
end
end
и требует его от environment.rb, но он не принимает мои изменения. Я также пробовал требовать его из controllers / application.rb, но опять же, не собирая свои изменения.
Временно я заставил его работать, переопределив метод в самой конкретной модели, но это своего рода взлом и означает, что я не могу использовать его ни на одной из других моделей в этом проекте.
Я уверен, что есть простой способ сделать это, но мне не удалось отследить его с помощью Google.
Ответов (3)3
То, что вы делаете, будет работать, но ваш код должен выглядеть так:
module WillPaginate
module Finder
module ClassMethods
def paginate_by_sql(sql, options)
# your code here
end
end
end
end
Другими словами, зайдите в finder.rb, удалите все, кроме заголовков модулей и метода, который вы хотите переопределить, затем сохраните в файл в lib и включите в environment.rb. Вуаля, мгновенный патч обезьяны!
Хорошо, я просто собираюсь облегчить это для таких людей, как я, которые приходят и все еще немного борются после прочтения других ответов.
Сначала найдите код, который вы хотите изменить, в репозитории github, выполнив поиск строки кода (вы можете легко найти ее с помощью pry ), которую хотите изменить в геме, а затем выберите Code
слева вместо Issues
Затем скопируйте содержимое модуля, который вы хотите изменить, и поместите его в .rb
файл с подходящим названием внутри папки config / initializers. Вот пример:
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
Теперь внесите любые дополнительные изменения в код и перезапустите сервер.
Вы уходите!
Более лаконичное решение:
WillPaginate::Finder::ClassMethods.module_eval do
def paginate_by_sql sql, options
# Your code here
end
end
Поместите код в файл инициализатора в config / initializers. Это правильное место для размещения кода, который должен запускаться при загрузке среды. Это также лучше организует ваш код, делая более понятным намерение каждого файла, поэтому ошибки будет легче отследить. Не загромождайте environment.rb!