Nadpisanie metody z gem-a

W gemie mam następujący kod (podaję tylko jedną metodę, jest ich więcej):

[code=ruby]module Wiki
class Dom
include ActionView::Helpers::TagHelper
include ActionView::Helpers::UrlHelper

def link_int text
  addr,link = text.join('').split("|")
  if link.nil?
    link = addr
  end    
  addr = addr.to_url_format
  link_to link,addr       
end

end
end[/code]
Metoda ta nie jest rozwiązaniem idealnym gdyż jej faktyczny kształt zależy od konkretnej aplikacji. Chciałbym w aplikacji nadpisać tę metodę. Zatem w pliku lib/wiki/dom.rb zamieściłem kod (wiem, że jeszcze nie jest idealny):

[code=ruby]module Wiki
class Dom

def link_int text
  addr,link = text.join('').split("|")
  if link.nil?
    link = addr
  end    
  doc = Article.find_by_title(addr)
  unless doc
    doc = Book.find_by_title(addr)
  end
  link_to link, doc       
end

end
end[/code]
Niestety metoda nie jest nadpisywana. Co robię źle?

Prawdopodobnie klasy te ładują się w innej kolejności niż myślisz. Najlepiej zrób klasę, ktora po tej klasie dziedziczy lub zrób możliwość include’owania do niej modułów (coś jak tutaj: http://piotrsarnacki.com/2010/07/31/rails3-modularity/ )

To raczej nie jest problem kolejności. Na próbę wyrzuciłem z gem-a tą metodę więc gdyby to był problem kolejności to powinno “rozwiązać” problem. Niestety aplikacja wyłożyła się z komunikatem o braku metody. Wygląda to raczej tak jakby plik lib/wiki/dom.rb w ogóle nie był brany pod uwagę.

Do kompletu informacji link do repozytorium http://svn.turox.org.pl/repos/wiki/trunk lub http://svn.turox.org.pl/bin/cgi/viewvc.cgi/wiki/trunk/

[quote=Tuptus]To raczej nie jest problem kolejności. Na próbę wyrzuciłem z gem-a tą metodę więc gdyby to był problem kolejności to powinno “rozwiązać” problem. Niestety aplikacja wyłożyła się z komunikatem o braku metody. Wygląda to raczej tak jakby plik lib/wiki/dom.rb w ogóle nie był brany pod uwagę.

Do kompletu informacji link do repozytorium http://svn.turox.org.pl/repos/wiki/trunk lub http://svn.turox.org.pl/bin/cgi/viewvc.cgi/wiki/trunk/[/quote]
A masz w config/application.rb require na tym pliku? Bo w poprzednich wersjach railsów trzeba było to dodać samemu. I najlepiej żeby nazywał się inaczej nić w gemie - np. wiki/dom_ex.rb. Ale nie mam pewności, czy tego nie zmienili jednej z najnowszych wersji.

[quote=apohllo][quote=Tuptus]To raczej nie jest problem kolejności. Na próbę wyrzuciłem z gem-a tą metodę więc gdyby to był problem kolejności to powinno “rozwiązać” problem. Niestety aplikacja wyłożyła się z komunikatem o braku metody. Wygląda to raczej tak jakby plik lib/wiki/dom.rb w ogóle nie był brany pod uwagę.

Do kompletu informacji link do repozytorium http://svn.turox.org.pl/repos/wiki/trunk lub http://svn.turox.org.pl/bin/cgi/viewvc.cgi/wiki/trunk/[/quote]
A masz w config/application.rb require na tym pliku? Bo w poprzednich wersjach railsów trzeba było to dodać samemu. I najlepiej żeby nazywał się inaczej nić w gemie - np. wiki/dom_ex.rb. Ale nie mam pewności, czy tego nie zmienili jednej z najnowszych wersji.[/quote]
Tak jak mówi apohollo Rails 3 nie autoloadują lib już. Tutaj mała dyskusja na ten temat: http://stackoverflow.com/questions/3356742/best-way-to-load-module-class-from-lib-folder-in-rails-3 .

Bardzo dziękuję za zainteresowanie. Wasze uwagi pozwoliły mi posunąć się krok dalej ale po kolei.

  1. Zmieniłem w aplikacji lib/wiki/dom.rb na lib/wiki/dom_local.rb i zamiast klasy jest teraz moduł

[code=ruby]module Wiki
module DomLocal

def link_int text
  # tutaj kod metody
  link_to link, new_article_path
end

end
end[/code]
2. Teraz trzeba jakoś dodać ten moduł do klasy Wiki::Dom w gem-ie. I tu pojawia się problem. Ani require ani include nie zadziała niezależnie od ustawień Rails.application.config.autoload_paths dlatego, że gem-y są “wczytywane” przed aplikacją i $LOAD_PATH jeszcze nie zawiera ścieżki {RAILS_ROOT}/lib. Rozwiązałem ten problem tworząc plik config/initializers/wiki.rb

require 'wiki/dom_local' Wiki::Dom.send :include, Wiki::DomLocal
3. W gem-ie zmieniłem nieco metodę link_int

[code=ruby]module Wiki
class Dom
include ActionView::Helpers::TagHelper
include ActionView::Helpers::UrlHelper

def link_int text
  super
end

end
end[/code]
Teraz to działa choć pojawiły się inne problemy np. new_article_path nie jest rozpoznawana jako istniejąca metoda mimo, że w innych miejscach aplikacji działa poprawnie. Poza tym będę musiał dodać w gem-ie generator, który będzie dodawał do aplikacji inicjalizator wiki.rb oraz odpowiednie katalogi i pliki w lib/. Ale to już inna bajka.

Jeszcze raz dziękuję za podpowiedzi. Poprawki do przedstawionego rozwiązania mile widziane :slight_smile: