I'm trying to use delayed_job to send emails from an input form. In my view i have replaced the line
Emailer.deliver_signup(#usercontact)
with
Emailer.send_later(:deliver_signup, #usercontact)
but when i run the job with rake jobs:work, i get: undefined method 'deliver_signup' for "CLASS:Emailer":String
What am I doing wrong? (Note that the code works without delayed_job)
Delayed job mailer might help rather than trying to implement the details yourself.
Related
We have recently migrated from sending emails with deliver_now to deliver_later. So that queued emails aren't lost when the system restarts, we implement this with Sidekiq.
When we used deliver_now, our Rake tests could test the sending of an email with
assert_equal 1, ActionMailer::Base.deliveries.count
For Rspec there is the assert_enqueued_emails method to test whether or not emails are queued. Is there an equivalent for Rake test?
You can use the have_enqueued_mail matcher (documentation). Then your spec would use something like the following.
have_enqueued_mail(MyMailer, :my_particular_email).once
The solution was quite simple, once I knew what to do:
Add the line include ActionMailer::TestHelper to the start of the test file
Execute the method perform_enqueued_jobs after all emails were queued.
After that, all the old tests worked fine.
See https://api.rubyonrails.org/classes/ActiveJob/TestHelper.html#method-i-perform_enqueued_jobs
I am using sidekiq to queue a job to validate the input of a field on a model (a link) and visit the link to make sure it doesn't return a 404 if it passes a regex validation.
If the regex validation passes and the link does not return 404 I assign another attribute to the same model but on a different field.
The worker is trigger by calling a method, the method is triggered after an after_commit, on: :update callback
The method only triggers the worker if 'previous_changes['json object I am using to make changes']' is true. This is so the worker won't continue to be called over and over again.
All of this works fine in development, confirmed with multiple use cases by QA'ing it myself
I am trying to write a test in MiniTest to ensure that a worker gets queued when the model's json field is changed but a worker is not being queued and for the life of me I can't figure out why.
I am testing the expectations for the worker being queued with:
assert_difference 'WorkerClass.jobs.size' do
site = sites(:site_from_fixtures)
site.attribute_that_triggers_change = { "random" => "json_object" }
site.save
end
The test returns: "Expected: 1, Actual: 0"
Any input would be greatly appreciated!
This issue was fixed by installing the test_after_commit gem.
Apparently after_commit's don't fire in tests unless you either use that gem or specify the necessary changes in a test_helper. I opted for the gem option just to keep things a little easier.
I am getting the following error while writing mail notification process asynchronously by using delay method.
NoMethodError in SampleController#create
undefined method `delay' for UserMailer:Class
I have the following code in my controller.
UserMailer.delay.idea_author_notification(self,nfication)
I have already installed delayed_job gem also started delayed_job by using jobs:work rake task.
Shall I need to do some other changes for using delay method for executing mail related code in background ?
Please help me on this asap..
Thanks in advanced...
the method delay is not existed for any action mailer class. So you can not call that method for the UserMailer:Class.
For that you can check all the methods for the mailer class in the rails console. i.e
UserMailer.methods
and to check particular method existed or not, run the following line.
UserMailer.methods.include?(:delay)
The above line returns false
OR
if you want to use delayed jobs, please go through the following link in github. It would definitely help you.
delayed_jobs_for_rails2.x.x
I'm using delayed_job to send emails in a Rails app and I'd like to test the email sending locally. Normally what I do is just set the mailer config to :test and then take a peek at ActionMailer::Base.deliveries, but the problem is when I call MyMailer.delay.some_email instead of MyMailer.some_email.deliver, the email never gets added to deliveries. I assume it's because I'm not longer calling "deliver", but you're not supposed to call "deliver" when using delayed_job.
All my production emails work fine. It's only the testing ones that don't.
Thoughts?
The jobs are not being worked off in the test environment because there's no jobs runner working. You need to instead check that the job has been added to the queue.
# Call the function
assert_not_equal Delayed::Job.count, 0, "Jobs have been added to the queue"
You can then test the job works by working it off, like so:
Delayed::Worker.new.work_off 1
# Check the job has been done as expected
I'm working to learn how to user delayed_job on my rails 3 + heroku app.
I currently have the following which emails on a request (not delayed job) but it works!
UserMailer.conversation_notification(record.commentable, participant, record, #comments).deliver
I updated that to this to start using delayed_job:
Delayed::Job.enqueue UserMailer.conversation_notification(record.commentable, participant, record, #comments).deliver
But that error'd with: "ArgumentError (Cannot enqueue items which do not respond to perform):"
I also tried:
UserMailer.delay.conversation_notification(record.commentable, participant, record, #comments)
But that error'd with:
NoMethodError (undefined method `delay' for UserMailer:Class):
Any delayed_job guru's out there? Thanks
From the docs https://github.com/collectiveidea/delayed_job
Your second method was correct which removes the .deliver method:
UserMailer.delay.conversation_notification(record.commentable, participant, record, #comments)
If you are getting an undefined method delay did you add DelayedJob to the Gemfile?
gem "delayed_job"
Since including the delayed_job will add the "delay" method to everything.
I have mixed results with using delay, and I've found it very challenging to debug. So you are not alone! But when you get it working, its worth it.
I've learned to save my object before calling delay on it. Typically I will trigger my job from an after_save call back.
As an experiment, for awhile I was using a different pattern. I'd create a job object for each job that I have. For example, I would call
Delayed::Job.enqueue(PersonJob.new(#person.id))
Elsewhere in my project I would create the job object. In Rails 2, I put these in lib/ if you do that with rails 3, you need to alter the application.rb config.autload_path
class PersonJob < Struct.new(:person_id)
def perform
person = Person.find(person_id)
#do work
end
end
config.autoload_paths += Dir["#{config.root}/lib/**/"]
I just had a look at the documentation, it's been a while since I actually used delayed_job...
Jobs are Ruby objects with a method called perform, so you'd need enqueue an object which does
UserMailer.conversation_notification(record.commentable, participant, record, #comments).deliver
in its perform method.
Alternatively, you can use send_later:
UserMailer.conversation_notification(record.commentable, participant, record, #comments).send_later(:deliver)