尝试使用delayed_job_active_record升级到Rails 4.2.我没有为测试环境设置delayed_job后端,因为工作会立即执行.
我正在尝试使用Rspec测试新的'deliver_later'方法,但我不确定如何.
旧控制器代码:
ServiceMailer.delay.new_user(@user)
Run Code Online (Sandbox Code Playgroud)
新控制器代码:
ServiceMailer.new_user(@user).deliver_later
Run Code Online (Sandbox Code Playgroud)
我用它来测试它是这样的:
expect(ServiceMailer).to receive(:new_user).with(@user).and_return(double("mailer", :deliver => true))
Run Code Online (Sandbox Code Playgroud)
现在我使用它会出错.(Double"mailer"收到意外消息:deliver_later with(no args))
只是
expect(ServiceMailer).to receive(:new_user)
Run Code Online (Sandbox Code Playgroud)
nil的'undefined方法`deliver_later'也失败了:NilClass'
我已经尝试了一些示例,允许您查看作业是否在ActiveJob中使用test_helper排队,但我还没有设法测试正确的作业是否排队.
expect(enqueued_jobs.size).to eq(1)
Run Code Online (Sandbox Code Playgroud)
如果包含test_helper,则会通过,但它不允许我检查它是否是正在发送的正确电子邮件.
我想做的是:
有任何想法吗??谢谢
rspec ruby-on-rails actionmailer delayed-job rails-activejob
我在Rails中找到了这个 Schedule一次性工作, 但这只显示了如何一次性安排.我有兴趣安排一份经常性的工作.
Delayed_job有这个
self.delay(:run_at => 1.minute.from_now)
Run Code Online (Sandbox Code Playgroud)
我如何在Rails 4.2/Active Job中做类似的事情?
我正在使用Rails API应用程序中的reset_password方法.当该端点被命中时,ActiveJob将排队,该命令将触发对Mandrill(我们的交易电子邮件客户端)的请求.我正在尝试编写测试以确保在控制器端点被命中时ActiveJob正确排队.
def reset_password
@user = User.find_by(email: params[:user][:email])
@user.send_reset_password_instructions
end
Run Code Online (Sandbox Code Playgroud)
send_reset_password_instructions在创建ActiveJob之前创建了一些url等,其代码如下:
class SendEmailJob < ActiveJob::Base
queue_as :default
def perform(message)
mandrill = Mandrill::API.new
mandrill.messages.send_template "reset-password", [], message
rescue Mandrill::Error => e
puts "A mandrill error occurred: #{e.class} - #{e.message}"
raise
end
end
Run Code Online (Sandbox Code Playgroud)
目前我们没有为ActiveJob使用任何适配器,所以我只想检查Rspec ActiveJob是否排队.
目前我的测试看起来像这样(我正在使用工厂女孩来创建用户):
require 'active_job/test_helper'
describe '#reset_password' do
let(:user) { create :user }
it 'should create an ActiveJob to send the reset password email' do
expect(enqueued_jobs.size).to eq 0
post :reset_password, user: { email: user.email }
expect(enqueued_jobs.size).to eq 1
end …
Run Code Online (Sandbox Code Playgroud) 这是我第一次异步处理作业我在我的应用程序中实现Sidekiq进行后台处理.我会将它用于提醒电子邮件和应用内通知.我很困惑我是否应该使用Active Job创建一个发送电子邮件的工作或者Sidekiq Worker来发送电子邮件.他们似乎做同样的事情,Rails 4.2 Active Job似乎很新......它是否取代了对Sidekiq工作者的需求?
以下是使用Active Job作业和Sidekiq Worker发送邮件代码的相同内容.我正在使用Whenever gem进行调度.
my_mailers.rb
class MyMailers < ActionMailer::Base
def some_mailer(r.user_id)
@user = User.find(r.user_id)
mailer_name = "ROUNDUP"
@email = @user.email
@subject ="subject text"
mail(to: @email,
subject: @subject,
template_path: '/notifer_mailers',
template_name: 'hourly_roundup.html',
)
end
end
Run Code Online (Sandbox Code Playgroud)
使用Sidekiq"Worker"
some_worker.rb
class SomeWorker
include Sidekiq::Worker
def perform()
@user = User.all
@reminders = @user.reminders.select(:user_id).uniq.newmade
@reminders.each do |r|
MyMailers.some_mailer(r.user_id).deliver_later
end
end
end
Run Code Online (Sandbox Code Playgroud)
使用活动作业"作业"
some_job.rb
class SomeJob < ActiveJob::Base
queue_as :mailer
def perform()
@user = User.all
@reminders = @user.reminders.select(:user_id).uniq.newmade
@reminders.each do |r| …
Run Code Online (Sandbox Code Playgroud) 有没有办法禁用ActiveJob和Sidekiq的自动重试?
我知道只有Sidekiq,我们只需要放
sidekiq_options :retry => false
Run Code Online (Sandbox Code Playgroud)
如上所述:https://github.com/mperham/sidekiq/wiki/Error-Handling#configuration
但它似乎不适用于ActiveJob和Sidekiq.
我也知道这里提出的重新启用重试的解决方案:https://stackoverflow.com/a/28216822/2431728
但这不是我需要的行为.
从Rails API,我发现ActiveJob可以retry_job间隔:
my_job_instance.enqueue
my_job_instance.enqueue wait: 5.minutes
my_job_instance.enqueue queue: :important
my_job_instance.enqueue wait_until: Date.tomorrow.midnight
Run Code Online (Sandbox Code Playgroud)
但是如果我想设置重试计数,比如Sidekiq:
include Sidekiq::Worker
sidekiq_options :retry => 5
Run Code Online (Sandbox Code Playgroud)
该示例代码怎么办?
class SiteScrapperJob < ActiveJob::Base
rescue_from(ErrorLoadingSite) do
retry_job queue: :low_priority
end
def perform(*args)
# raise ErrorLoadingSite if cannot scrape
end
end
Run Code Online (Sandbox Code Playgroud)
现在我把它添加到我的工作班:
Sidekiq.default_worker_options = { retry: 5 }
Run Code Online (Sandbox Code Playgroud)
但似乎不是很好.
ActionJob
在Rails中连接的常见模式是使用一个perform()
方法设置一个Job,该方法通过perform_now
或者异步调用perform_later
在邮件程序的特殊情况下,可以直接打电话deliver_now
或deliver_later
因为ActionJob
是很好的集成ActionMailer
.
该轨道文档有以下评论-
# If you want to send the email now use #deliver_now
UserMailer.welcome(@user).deliver_now
# If you want to send the email through Active Job use #deliver_later
UserMailer.welcome(@user).deliver_later
Run Code Online (Sandbox Code Playgroud)
措辞使得它看起来像deliver_now
会不会使用ActiveJob
发送邮件.那是正确的,如果有啥之间真正的差异deliver_now
和deliver_later
?一个不是异步的吗?
同样,同样的差异适用于perform_now
和perform_later
?
谢谢!
我有这个代码用Rspec测试ActiveJob和ActionMailer我不知道如何真正执行所有排队的工作
describe 'whatever' do
include ActiveJob::TestHelper
after do
clear_enqueued_jobs
end
it 'should email' do
expect(enqueued_jobs.size).to eq(1)
end
end
Run Code Online (Sandbox Code Playgroud) 我正在尝试使用Rails 4.2的deliver_later方法设置联系表单.但是,我只能让deliver_now工作,因为deliver_later正在尝试序列化我的对象并且每次都失败.
这是我的设置:
messages_controller.rb
class MessagesController < ApplicationController
def new
@message = Message.new
end
def create
@message = Message.new(params[:message])
if @message.valid?
ContactMailer.contact_form(@message).deliver_later
redirect_to root_path, notice: "Message sent! Thank you for contacting us."
else
render :new
end
end
end
Run Code Online (Sandbox Code Playgroud)
contact_mailer.rb
class ContactMailer < ApplicationMailer
default :to => Rails.application.secrets['email']
def contact_form(msg)
@message = msg
mail(:subject => msg.subject, from: msg.email)
end
end
Run Code Online (Sandbox Code Playgroud)
message.rb
class Message
include ActiveModel::Model
include ActiveModel::Conversion
## Not sure if this is needed ##
include ActiveModel::Serialization
extend ActiveModel::Naming
attr_accessor :name, …
Run Code Online (Sandbox Code Playgroud) 有人知道一种干净的方法来避免ActiveJob::SerializationError
在尝试序列化Date
或Time
对象时发生这种情况吗?
我到目前为止的两个解决方案是:
dump
在加载参数时调用Marshal/JSON/YAML 然后load
返回到Job(这很糟糕,因为我需要修补邮件程序作业)Date
和Time
像这样:/lib/core_ext/time.rb
class Time
include GlobalID::Identification
def id
self.to_i
end
def self.find(id)
self.at(id.to_i)
end
end
Run Code Online (Sandbox Code Playgroud)
/lib/core_ext/date.rb
class Date
include GlobalID::Identification
def id
self.to_time.id
end
def self.find(id)
Time.find(id).to_date
end
end
Run Code Online (Sandbox Code Playgroud)
哪个也很糟糕.谁有更好的解决方案?
rails-activejob ×10
rspec ×3
sidekiq ×3
actionmailer ×2
ruby ×2
asynchronous ×1
delayed-job ×1
jobs ×1
whenever ×1