Delayed_job: Undefined method error on any call - ruby-on-rails

I have a rails 3.0.5 app that was working just fine with delayed_job 2.1.4.
It's been a few weeks since I touched the app, but I just went to tweak it and noticed that delayed_job is broken. Specifically, any call to delayed_job returns an "undefined method" error on the method after delay. (eg StudentMailer.delay.student_mail('test') returns "undefined method" on "student_mail") I cannot figure out why. A few things:
Replacing StudentMailer.delay.student_mail('test') with StudentMailer.student_mail('test').deliver delivers the mail just fine.
Have not changed any gem versions on the site, they've been locked since development
RVM has been uninstalled & reinstalled
Happens across all mailer methods
Code & error below:
MAILER:
class StudentMailer < ActionMailer::Base
def course_signup(email, password, course, enrolment)
#email = email
#password = password
#course = course
#enrolment = enrolment
#student = Student.where(:email => email).first
if (#student.user.first_name && #enrolment.student.user.last_name) then
#username = #student.first_name.gsub(/[^[:alnum:]]/, '').downcase + '.' + #student.last_name.gsub(/[^[:alnum:]]/, '').downcase
else
#username = "fcuser#{#student.id}"
end
mail(:to => email, :from => ENV['ACCOUNTS_EMAIL'], :subject => "You have been enrolled as a student for #{course}", :content_type => 'text/plain')
end
end
MODEL (Mailer called on after_save)
after_create {
studentmailer = StudentMailer
#studentmailer.course_signup(self.student.email, self.purchase.course).deliver
randompass = RandomPassword.random_string(20)
randomGatewayPass = RandomPassword.random_string(8)
studentmailer.delay.course_signup(self.student.email, randomGatewayPass, self.purchase.course, self)
self.save }
CONFIG/BOOT.RB
require 'yaml'
YAML::ENGINE.yamler = 'syck'
require 'rubygems'
gemfile = File.expand_path('../../Gemfile', __FILE__)
begin
ENV['BUNDLE_GEMFILE'] = gemfile
require 'bundler'
Bundler.setup
rescue Bundler::GemNotFound => e
STDERR.puts e.message
STDERR.puts "Try running `bundle install`."
exit!
end if File.exist?(gemfile)
DELAYED JOB ERROR:
{undefined method course_signup' for #<Class:0x007fbcf61850c8>
/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.1.4/lib/delayed/performable_mailer.rb:6:in
perform'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.1.4/lib/delayed/backend/base.rb:87:in
invoke_job'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.1.4/lib/delayed/worker.rb:120:in
block (2 levels) in
run'\n/Users/john/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/timeout.rb:58:in
timeout'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.1.4/lib/delayed/worker.rb:120:in
block in
run'\n/Users/john/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/benchmark.rb:310:in
realtime'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.1.4/lib/delayed/worker.rb:119:in
run'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.1.4/lib/delayed/worker.rb:177:in
reserve_and_run_one_job'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.1.4/lib/delayed/worker.rb:104:in
block in
work_off'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.1.4/lib/delayed/worker.rb:103:in
times'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.1.4/lib/delayed/worker.rb:103:in
work_off'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.1.4/lib/delayed/worker.rb:78:in
block (2 levels) in
start'\n/Users/john/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/benchmark.rb:310:in
realtime'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.1.4/lib/delayed/worker.rb:77:in
block in
start'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.1.4/lib/delayed/worker.rb:74:in
loop'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.1.4/lib/delayed/worker.rb:74:in
start'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.1.4/lib/delayed/command.rb:104:in
run'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.1.4/lib/delayed/command.rb:83:in
block in
run_process'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/daemons-1.1.4/lib/daemons/application.rb:249:in
call'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/daemons-1.1.4/lib/daemons/application.rb:249:in
block in
start_proc'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/daemons-1.1.4/lib/daemons/daemonize.rb:197:in
call'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/daemons-1.1.4/lib/daemons/daemonize.rb:197:in
call_as_daemon'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/daemons-1.1.4/lib/daemons/application.rb:253:in
start_proc'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/daemons-1.1.4/lib/daemons/application.rb:293:in
start'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/daemons-1.1.4/lib/daemons/controller.rb:70:in
run'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/daemons-1.1.4/lib/daemons.rb:195:in
block in
run_proc'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/daemons-1.1.4/lib/daemons/cmdline.rb:109:in
call'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/daemons-1.1.4/lib/daemons/cmdline.rb:109:in
catch_exceptions'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/daemons-1.1.4/lib/daemons.rb:194:in
run_proc'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.1.4/lib/delayed/command.rb:81:in
run_process'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.1.4/lib/delayed/command.rb:75:in
block in
daemonize'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.1.4/lib/delayed/command.rb:73:in
times'\n/Users/john/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.1.4/lib/delayed/command.rb:73:in
daemonize'\nscript/delayed_job:5:in `' | 2011-09-06 07:42:21 |
NULL | 2011-09-06 07:43:00 | NULL | 2011-09-06 07:40:07 |
2011-09-06 07:43:00 |

I was Googling the same issue, and I found a fix for this(it worked for me).
add these two lines to the head of your config/application.rb
require 'yaml'
YAML::ENGINE.yamler = 'syck'
then, restart your server(webrick/thin/whatever) and delayed_job
(bundle exec ./script/delayed_job restart)
done.

I had the same problem. If you are using thin, try doing "bundle exec thin start". It worked for me.

try to change method definition
def self.course_signup
or
studentmailer = StudentMailer.new
because now you call method from class but method belongs to object

Related

uninitialized constant ActiveSupport::Json despite "require 'active_support/all'"

I'm receiving a "uninitialized constant ActiveSupport::Json" error on the line where I call responseJson = ActiveSupport::Json.decode(response), in a small controller in my small Rails app.
The response variable returns a string with a response of the type {"token":"this_is_your_session_token"}.
I've added gem 'activesupport', '~> 4.2.3', to my Gemfile, tried different require statements with 'active_support/core_ext/object/json, and tried this in the IRB (with the same error). I'm not sure how to debug this further. Any help would be greatly appreciated.
require 'active_support/json'
require 'active_support'
require 'active_support/all'
require 'rest-client'
class WelcomeController < ApplicationController
def login_attempt
username = params[:u]
password = params[:p]
puts "waiting on request"
response = RestClient.post 'http://localhost:3001/v1/login', :email => username, :password => password
responseJson = ActiveSupport::Json.decode(response)
end
end
ActiveSupport::JSON (all caps). FYI, if you use pry instead of irb, you can run a command like 'ls ActiveSupport' and see the contained modules, methods, etc.

Rails + Rspec: Test says value of variable is nil, console says otherwise

I have a test that's failing for a custom non active record class I'm writing:
test:
describe "#xml_for_initial_request" do
it "calls the access_request method" do
ups_shipping = UpsShipping.new
ups_shipping.should_receive(:credentials)
ups_shipping.print_xml
end
end
console:
Failures:
1) UpsShipping#xml_for_initial_request calls the access_request method
Failure/Error: ups_shipping.print_xml
NoMethodError:
undefined method `to_xml' for nil:NilClass #<-- FAILURE HERE
# ./app/models/ups_shipping.rb:14:in `print_xml'
# ./spec/models/ups_shipping_spec.rb:465:in `block (3 levels) in <top (required)>'
Finished in 0.45009 seconds
1 example, 1 failure
This occurs in this model:
require 'net/https'
require 'uri'
class UpsShipping
attr_reader :products, :purchase
def initialize(options = {})
#products = options.fetch(:products, [])
#purchase = options[:purchase]
end
def print_xml
xml = ''
xml << credentials.to_xml #<-- ERROR OCCURS HERE
return xml
end
def credentials #<-- CREDENTIALS COMES FROM HERE
{
"AccessLicenseNumber" => UPS_API["access_key"],
"UserId" => UPS_API["user_id"],
"Password" => UPS_API["password"]
}
end
....
However, when I try this in the console in the test environment it works:
Nets-Mac-Pro:myproject emai$ RAILS_ENV=test bundle exec rails c --sandbox
/Users/emai/.rvm/gems/ruby-1.9.3-p362#myproject/gems/ruby-debug-ide-0.4.18/lib/ruby-debug-ide/command.rb:27: warning: already initialized constant DEF_OPTIONS
Loading test environment in sandbox (Rails 3.2.13)
Any modifications you make will be rolled back on exit
1.9.3p362 :001 > ups_shipping = UpsShipping.new
=> #<UpsShipping:0x007feb0c974790 #products=[], #purchase=nil>
1.9.3p362 :002 > ups_shipping.print_xml
=> "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<hash>\n <AccessLicenseNumber>xxxxx</AccessLicenseNumber>\n <UserId>xxxx</UserId>\n <Password>xxx</Password>\n</hash>\n"
1.9.3p362 :003 > ups_shipping.credentials
=> {"AccessLicenseNumber"=>"xxxx", "UserId"=>"xxxx", "Password"=>"xxxx"}
What's the deal???
should_receive is intercepting the method call and not calling the original and, by default, returning nil. Add a call to and_call_original:
ups_shipping.should_receive(:credentials).and_call_original

Rails cron not sending emails

I'm using the whenever gem to have a rails cron job send emails. Everything seems to work just fine and i have no errors in my cron.log or my production.log file, but i never receive an email. I've checked that the email address is correct also.
Any help is appreciated.
The production.log file contains this:
Connecting to database specified by database.yml
Rendered email_mailer/send_birthday_reminders.html.erb (5.3ms)
Sent mail to tomcaflisch#gmail.com (409ms)
Here's my whenever gem schedule.rb file
set :output, "#{path}/log/cron.log"
every :hour do
runner "BirthdayRemindersController.send_birthday_email_reminders"
end
birthday_reminders_controller.rb
class BirthdayRemindersController < ApplicationController
# cron job that sends birthday reminders
def self.send_birthday_email_reminders
users = User.all
email_addresses = []
users.each_with_index do |user, i|
if user.user_details.birthday_reminders == true
email_addresses[i] = get_primary_email(user)
end
end
p "email_addresses to send to:"
p email_addresses
users.each do |user|
p "this user is"
p user.user_details.full_name
if user.user_details.birthday.try(:strftime, "%m") == Date.today.strftime("%m") && user.user_details.birthday.try(:strftime, "%d") == Date.today.strftime("%d")
p "reminder sent"
EmailMailer.send_birthday_reminders(user, email_addresses).deliver
end
end
end
end
email_mailer.rb snippet
class EmailMailer < ActionMailer::Base
include ApplicationHelper
default :from => "\"FamNFo\" <no-reply#mysite.com>"
def send_birthday_reminders(birthday_person, email_addresses)
p "we in send_birthday_reminders mailer"
p email_addresses
#birthday_person = birthday_person
mail(:subject => "Birthday Reminder For The Caflisch Family", :to => email_addresses, :reply_to => email_addresses)
end
end
capistrano's deploy.rb contains this
# needed for the 'whenever' gem
set(:whenever_command) { "RAILS_ENV=#{rails_env} bundle exec whenever"}
require "whenever/capistrano"
Check your spam folder. To make sure emails don't end up there, add an "Unsubscribe" link in each email.
This could happen if your action mailer configuration specifies perform_deliveries=false. You can check out the configuration in your environment files.
If your application is deployed to cloud services then you may be getting your emails in a spam folder. Their entire IP blocks are registered as spam at services like Spamhaus, which is a sensible precaution or else we'd be getting even more spam than usual.
You should enter your server's IP address in that field to see if you're listed as a spammer.
If you are, you can request to Spamhaus that the block be lifted.
The other big issues I have found is that the PATH and rbenv may not be initialized in the CRONTAB depending on how you have it setup.
I would recommend adding the following to the top of your .bashrc file
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"
This ensures that if you are using whenever to call model methods that rbenv and ruby are fully available.

delayed_job gives "NameError: uninitialized constant"

I'm trying to move a current working task (in production and in the console) to use delayed_job in a Rails 2 app but keep getting the error:
ThermalImageJob failed with NameError: uninitialized constant Barby::Code128B
I've pored through others' code searching for an answer to no avail. Here's my code:
/lib/thermal_image_job.rb
class ThermalImageJob < Struct.new(:order_id)
def perform
order = Order.find(order_id)
order.tickets.each do |ticket|
ticket.barcodes.each do |barcode|
barcode.generate_thermal_image
end
end
end
end
/app/controllers/orders_controller.rb
Delayed::Job.enqueue(ThermalImageJob.new(#order.id))
/app/models/barcode.rb
def generate_thermal_image(format=:gif)
filename = "#{barcode}_thermal.#{format}"
temp_file_path = File.join("#{RAILS_ROOT}", 'tmp', filename)
unless FileTest.exists?(temp_file_path)
barcode_file = File.new(temp_file_path, 'w')
code = Barby::Code128B.new(barcode)
....
end
Gemfile
gem "delayed_job", "2.0.7"
gem "daemons", "1.0.10"
Well, after much head banging, I figured it out, so I'm posting this to help the next person. The problem was that it couldn't find the barby libs, so I added a require at the beginning of my class:
require "barby/outputter/rmagick_outputter"
require "barby/barcode/code_128"

Delayed_job in rails failing

I am just beginning to look into using the delayed_job gem.
To test it, I added "delayed" to the welcome email function and changed that call from
UserMailer.welcome_email(self).deliver
to
UserMailer.delay.welcome_email(self)
This is called inside the User model after_create. I see an entry show up in the delayed_job table after the function executes. Now when I run "rake jobs:work" on command line the task starts but gives errors as below
[Worker(host:Sanjay-PC pid:7008)] Starting job worker
[Worker(host:Sanjay-PC pid:7008)] Class#welcome_email failed with NoMethodError: undefined method `welcome_email' for #<Class:0x4871d60> - 0 failed attempts
[Worker(host:Sanjay-PC pid:7008)] 1 jobs processed at 0.0939 j/s, 1 failed ...
Thinking that if I changed the welcome_email method declaration to a Class method as
def self.welcome_email(user)
(added self. in front) that might help. But then when I run rake jobs:work I get the following error
rake aborted!
undefined method `welcome_email' for class `UserMailer'
C:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.0.5/lib/active_support/core_ext/module/aliasing.rb:31:in `alias_method'
C:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.0.5/lib/active_support/core_ext/module/aliasing.rb:31:in `alias_method_chain'
C:/Ruby192/lib/ruby/gems/1.9.1/gems/delayed_job-2.1.4/lib/delayed/message_sending.rb:50:in `handle_asynchronously'
c:/mgn/mgn-r3/app/mailers/user_mailer.rb:10:in `<class:UserMailer>'
c:/mgn/mgn-r3/app/mailers/user_mailer.rb:1:in `<top (required)>'
C:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.0.5/lib/active_support/dependencies.rb:454:in `load'
<Stack truncated>
It seems to now know the class as UserMailer but it somehow doesn't see the class method welcome_email.
I am on Rails 3.0.5, Ruby 1.9.2p180 and the installed delayed_job gem is 2.1.4 - on Windows
Can't seem to find any related answers anywhere.
Thanks for your thoughts.
-S
Adding UserMailer code per #pjammer's request
class UserMailer < ActionMailer::Base
default :from => "from#example.com"
def welcome_email(user)
#user = user
#url = "http://example.com/login"
mail(:to => user.email,
:subject => "Welcome to My Awesome Site")
end
end
Just use this
UserMailer.delay.welcome_email(self).deliver
instead of
UserMailer.welcome_email(self).delay.deliver
My solution was to redefine function at the handler class (for you it's UserMailer class)
def self.taguri
'tag:ruby.yaml.org,2002:class'
end
It's a hack and I'll try to find a better solution but now it works for me.
(Rails 3.0.9, Ruby 1.9.2-p290, delayed_job 2.1.4)
https://groups.google.com/forum/?fromgroups=#!topic/delayed_job/_gvIcbXrOaE solved my handles_asynchronously error for class methods.
As per Brandon Keeper in the link above, the code is the following:
class ClassName
class << self
def foo
end
handle_asynchronously :foo
end
end
then use ClassName.delay.foo

Resources