Nie powiem Ci co jest przyczyną tego konkretnego problemu i jak ten konkretne błąd naprawić, ale powiem Ci dlaczego podejście jakiego używasz jest złe i że inne podejście rozwiąże Twoje problemy (no chyba, że się mylę to wtedy zwracam honor).
Używasz w kodzie metody delay, prawda? (w tym wypadku zdaje się user.delay.send_confirmation_instructions) Żeby ta piękna magia zadziałała cały obiekt usera musi zostać zserializowany i zapisany w bazie. Potem delayed_job pobiera taki zserializowany obiekt, deserializuje go i wykonuje na nim podaną metodę. Nie zawsze jednak to się powiedzie. Najprostszy przypadek: dj próbuje zdeserializować klasę, której nie zna (dzieje się tak gdy daemon dj nie posiada załadowanej klasy X, która została zserializowana w aplikacji).
[code=irb]> class Foo; attr :foo; def initialize; @foo = 1; end; end
nil
foo = Foo.new
#<Foo:0x00000102433368 @foo=1>
dump = YAML.dump(foo)
“— !ruby/object:Foo \nfoo: 1\n”
Object.send(:remove_const, :Foo)
Foo
YAML.load(dump).foo
NoMethodError: undefined method foo' for #<Syck::Object:0x00000102440fb8 @class="Foo", @ivars={"foo"=>1}> from (irb):36 from /Users/radarek/opt/bin/irb1.9:12:in'[/code]
Innym problemem jaki możesz napotkać to próba deserializacji obiektu starszej wersji klasy z załadowaną nowszą definicją (w przypadku dj łatwo o coś takiego gdy chcesz coś wykonać ze sporym opóźnieniem).
Moje osobiste zdanie na ten temat jest taki: twórz klasę per każde logiczne zadanie, które chcesz wykonać asynchronicznie (w tle) i przesyłaj do niej tylko prymitywne typy (liczny, stringi, tablice liczb itp), z którymi nigdy nie będziesz mieć problemów w kwestii serializacji.
Dla Twoje konkretnego przykładu byłoby to:
class ConfirmationInstructionsJob < Struct.new(:user_id)
def perform
user = User.find(user_id)
UserMailer.deliver_confirmation_instructions(user)
end
end
Prócz tego, że to działa (i mnie nigdy w kwestiach technicznych nie zawiodło, w przeciwieństwie do delay i send_later) ma to dodatkową zaletę. W jednym miejscu ma się wszystkie brackgroundowe taski.