Upgrade aplikacji

Witam,

dostałem zadanie upgrade’u aplikacji na najnowse wersje gemów i tak z rails 2.3.5 i hobo 1.0.1 zacząłem przechodzić na rails 3.0.9 i hobo 1.3.0.RC
Po drodze pojawił mi się jednak pewien problem.

Otóż, po starcie aplikacji i próbie zalogowania do niej użytkownika w modelu user.rb zgłaszany jest NoMethodError w procedurze:

def method_missing(method, *args, &block) str = method.to_s if(str.length < 11) return super end if(str[0,10] == 'calls_week') week = str[10, str.length - 10].to_i return super if (week == nil) return calls_week(week) end if(str[0,10] == 'leads_week') week = str[10, str.length - 10].to_i return super if (week == nil) return leads_week(week) end if(str[0,10] == 'projs_week') week = str[10, str.length - 10].to_i return super if (week == nil) return projs_week(week) end super end
konkretnie w pierwszym ‘return super’

Czy wiecie może jak ten błąd wyrugować?
Próbowałem znaleźć jakieś informacje o tym ‘super’, ale nieszczególnie znalazłem cokolwiek
Dla próby zbudowałem nową, pustą aplikację są w niej dwa wystąpienia (dla aplikacji hobo1.3.0 trzy) słowka ‘super’, ale tylko w plikach .js
W aplikacji, którą mam upgradować, są 142 wystąpienia w 76 plikach.

Z góry dziękuję za odpowiedź,
Piotr

Słówko kluczowe ‘super’ wywołuje tę samą metodę, ale z klasy rodzica.

Rzucanie wyjątku jest normalnym zachowaniem w przypadku method_missing, jeśli czegoś nie przegapiłem. Jakiej reakcji oczekujesz?

Szczerze mówiąc nie wiem czego oczekiwać.
Na rails 2.3.5 nigdy nie wystąpił taki błąd - przynajmniej od czasu kiedy dostałem tą aplikację do opieki.

Czyli jeśli dobrze rozumiem, mechanizm logowania do aplikacji wywołuje jakąś metodę usera, której nie ma, wtedy zgłasza się method_missing i superem wywołuje bład ogólny, tak?

W railsach 3 przepisano sposób generowania metod atrybutów, wydaje mi się, że teraz są leiniwie ładowane podczas pierwszego odwołania, być może to jest przyczyną. Nie miałem jeszcze czasu się dokładnie temu przyjrzeć, więc niestety żadnych konkretów nie podam :wink:

No backtrace, no answer

piotroslav: Tak sądzę. Spróbuj dojść do miejsca, które wywołuje tę nieistniejącą metodę. Na pewno będzie to w backtrace.

Co do tego ‘super’, to to jest część języka ruby a nie specjalna metoda Railsów. W tym przypadku (zgaduję, że klasa User dziedziczy z ActiveRecord::Base), super w metodzie zdefiniowanej w klasie User wywoła metodę ‘method_missing’ z klasy ActiveRecord::Base, a tamta zapewne też ma gdzieś w swojej treści jakieś ‘super’, które z kolei wywoła metodę z kolejnej klasy rodzica, aż dojdzie toto do klasy Object, który nie ma już żadnego ‘super’, tylko rzuca wyjątkiem.

Przyznam, że jak analizowałem co będzie łatwiejsze - przekonwertować program (średniej jakości - NIE MÓJ!) z railsów 2 na railsy 3, to zdecydowałem się napisać go na nowo. Ale trzymam kciuki :slight_smile:

https://gist.github.com/1063958 - backtrace, jak równiez zawartość modelu

O samym ‘super’ znalazłem tylko informację, ze to z Ruby’iego i że do konstruktorów czesto używane może być - sta moje dociekanie

Co do samego pomysłu przenosin na rails3 - jakies dziwne rzeczy zaczęły się dziać przy deployach na heroku - środowisko przestało ogarniać, ze ma tylko pliki do odczytu i próbowało odswierzać jakieś template’y, przez co crashowało aplikację - my nic nie zmienialiśmy w konfiguracji - heroku twierdzi, że tez nic nie robili.
W efekcie poświęciliśmy bezowocnie dużo czasu na wymuszenie w naszej konfiguracji trybu read-only i wciąż mamy zablokowaną możliwość releasowania nowych wersji.

Może łatwiej będzie stworzyć nową aplikację, a potem przenosić po kolei modele, później kontrolery? (pamiętając o zmianie mechanizmu escapowania w widokach - chyba najbardziej uciążliwa rzecz)

Z backtrace widzę, że problemem jest nie ‘super’ tylko ‘generated_methods’. Google ma trochę wyników na to, ale nie wiem, które jest rozwiązaniem. No i jeszcze Windows może być problematycznym środowiskiem, ale to już zupełnie inna bajka.

Na moje oko winowajcą jest:
validates_timeliness (2.3.1) lib/validates_timeliness/active_record/attribute_methods.rb:46:in `define_attribute_methods’

Update:

Prawie na pewno:

Wersja 2.3.1 sugeruje, że ten plugin działa tylko z rails 2.3.x. Najnowsze wersje mają już numerację 3.x.

Faktycznie - update tego gemu pchnął nas do przodu.
Dziękuję!

Mam kolejny problem (w zasadzie to jest ich sporo, ale po kolei…)

W starej wersji aplikacji używany był gem hobo w postaci pluginu.
UserMailer w dowolnej metodzie miał dwie poniższe linie:

host = Hobo::Controller.request_host app_name = Hobo::Controller.app_name || host
a w /vendor/plugins/… …/hobo/controller.rb były zdefiniowane:

[code]def request_host
Thread.current[‘Hobo.current_controller’].request.host_with_port
end

def app_name
Thread.current[‘Hobo.current_controller’].send(:call_tag, :app_name)
end[/code]
Hobo 1.3.0 jest w postaci gemu i dostaje bład nieznanem metody w >> Hobo::Controller.request_host
Nie znalazłem informacji o instalowaniu hobo 1.3.0 w postaci pluginu, dlatego chciałbym zapytać w jaki sposób mógłbym rozwiązać (nie rezygnując z hobo) powyższy problem?

te zmienne podejrzewam nie zmieniają się dla danego środowiska, np. development, więc możesz je wrzucić do jakiegos configa i stamtąd wczytać, nie używam Hobo, więc tak tylko strzelam

Przerzuciłem to do mailera i wyglada to tak:

[code]class UserMailer < ActionMailer::Base
default :from => “no-reply@#{host}”
def request_host
Thread.current[‘Hobo.current_controller’].request.host_with_port
end

def app_name
Thread.current[‘Hobo.current_controller’].send(:call_tag, :app_name)
end
def forgot_password(user, key)
host = request_host
app_name = app_name || host
@subject = “#{app_name} – password reset”
@body = { :user => user, :key => key, :host => host, :app_name => app_name }
@recipients = user.email_address
@from = “no-reply@#{host}”
@sent_on = Time.now
@headers = {}
end[/code]
Co ciekawe kod wysypuje się na słowku request.

Jeśli się zastanowić, to Thread.current[] zwraca thread, więc Thread.current[].request to powinna byc metoda Thread’a, ale takiej metody nie ma… więc jak to mogło wcześniej działać? :confused:

Dlaczego uważasz, że Thread.current[] zwraca Thread? To zwraca lokalną zmienna danego wątku. A co to jest ta zmienna, to już inna zagadka.

Thread.current to faktycznie Thread, ale ten kwadratowonawiasowy operator zwraca (lub ustawia) zmienne lokalne. Zobacz 'ri Thread.[]`