Ruby on Rails:延迟的作业无法使用邮件程序并给出路由错误
Posted
技术标签:
【中文标题】Ruby on Rails:延迟的作业无法使用邮件程序并给出路由错误【英文标题】:Ruby on Rails: delayed jobs are not working with mailer and give route error 【发布时间】:2021-12-15 17:35:10 【问题描述】:我尝试为我的邮件程序实现延迟作业,但即使按照文档进行操作也遇到了一些问题。
应用程序.rb
require_relative 'boot'
require 'rails/all'
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module AjaxApp
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 5.1
config.action_view.embed_authenticity_token_in_remote_forms = true
config.active_job.queue_adapter = :delayed_job
# Settings in config/environments/* take precedence over those specified here.
# Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded.
end
end
我也有 config/initilizers/delayed_jobs.rb
Delayed::Worker.max_attempts = 5 #25
Delayed::Worker.destroy_failed_jobs = false
Delayed::Worker.sleep_delay = 60
Delayed::Worker.max_run_time = 5.minutes
Delayed::Worker.read_ahead = 10
Delayed::Worker.default_queue_name = 'default'
Delayed::Worker.delay_jobs = !Rails.env.test?
Delayed::Worker.raise_signal_exceptions = :term
Delayed::Worker.logger = Logger.new(File.join(Rails.root, 'log', 'delayed_job.log'))
还有迁移
class CreateDelayedJobs < ActiveRecord::Migration[6.0]
def self.up
create_table :delayed_jobs do |table|
table.integer :priority, default: 0, null: false # Allows some jobs to jump to the front of the queue
table.integer :attempts, default: 0, null: false # Provides for retries, but still fail eventually.
table.text :handler, null: false # YAML-encoded string of the object that will do work
table.text :last_error # reason for last failure (See Note below)
table.datetime :run_at # When to run. Could be Time.zone.now for immediately, or sometime in the future.
table.datetime :locked_at # Set when a client is working on this object
table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
table.string :locked_by # Who is working on this object (if locked)
table.string :queue # The name of the queue this job is in
table.timestamps null: true
end
add_index :delayed_jobs, [:priority, :run_at], name: "delayed_jobs_priority"
end
def self.down
drop_table :delayed_jobs
end
end
我也通过命令rails jobs:work
运行我的工人
完成所有这些设置后,我尝试发送密码重置电子邮件
我的密码_resets_controller.rb
def create
@user = User.find_by(email: params[:password_reset][:email].downcase)
if @user
@user.create_reset_digest
@user.send_password_reset_email
flash[:info] = 'Email sent with password reset instructions.'
redirect_to root_url
else
flash.now[:danger] = 'Email address not found.'
render 'new'
end
end
从user.rb中调用方法
def send_password_reset_email
UserMailer.password_reset(self).deliver_later
#deliver_later must working under the hood of delayed_job
end
我也试过
def send_password_reset_email
UserMailer.delay.password_reset(self)
end
和
def send_password_reset_email
UserMailer.password_reset(self)
end
handle_asynchronously :send_password_reset_email
在所有情况下,http://localhost:3000/delayed_job/failed?queues=mailers 都会出现错误(是的,我使用 gem 'delayed_job_web')
ID 1
Priority 0
Attempts 1
Queue mailers
Handler
--- !ruby/object:ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper
job_data:
job_class: ActionMailer::DeliveryJob
job_id: f5efa6e2-18e5-4d99-836b-8800d34b7289
provider_job_id:
queue_name: mailers
priority:
arguments:
- UserMailer
- password_reset
- deliver_now
- _aj_globalid: gid://ajax-app/User/1
executions: 0
exception_executions:
locale: en
timezone: UTC
enqueued_at: '2021-10-31T17:49:54Z'
Last Error No route matches :action=>"edit", :controller=>"password_resets", :email=>"psychotrop@gmail.com", :...
但我在 routes.rb 中有
resources :password_resets, only: [:new, :create, :edit, :update]
当我使用没有延迟作业的邮件程序时,一切都按预期工作。 请帮助解决该问题。提前致谢!
更新
user_mailer.rb
class UserMailer < ActionMailer::Base
default from: "psychotrop@gmail.com"
#def welcome_email(user)
# @user = user
# @url = 'http://example.com/login'
# mail(to: @user.email, subject: 'Welcome to Test Site')
#end
def registration_confirmation(user)
@user = user
mail(to: @user.email, subject: 'Verify your accounts')
end
#handle_asynchronously :registration_confirmation
def account_activation(user)
@user = user
mail to: user.email, subject: "Account activation", template_name: 'account_activation'
end
#handle_asynchronously :account_activation
def password_reset(user)
@user = user
mail to: user.email, subject: "Password reset", template_name: 'password_reset'
end
#handle_asynchronously :password_reset
end
password_reset.html.erb
<h1>Password reset</h1>
<p>To reset your password click the link below:</p>
<%= link_to "Reset password", edit_password_reset_url(@user.reset_token,
email: @user.email) %>
<p>This link will expire in two hours.</p>
<p>
If you did not request your password to be reset, please ignore this email and
your password will stay as it is.
</p>
更新 2
rake routes | grep password_reset
password_resets POST /password_resets(.:format) password_resets#create
new_password_reset GET /password_resets/new(.:format) password_resets#new
edit_password_reset GET /password_resets/:id/edit(.:format) password_resets#edit
password_reset PATCH /password_resets/:id(.:format) password_resets#update
PUT /password_resets/:id(.:format) password_resets#update
【问题讨论】:
似乎错误来自 UserMailer 的方法或电子邮件模板。您能否使用 UserMailer 代码和电子邮件模板编辑您的问题。 @NitinSrivastava。感谢您的回复。我添加了邮件和模板 似乎问题出在password_reset.html.erb
模板中的edit_password_reset_url(@user.reset_token, email: @user.email)
url 中。要检查正确的 url,请在您的终端上运行 rake routes | grep password_reset
并使用命令结果更新问题。我们即将解决此问题。
@NitinSrivastava 谢谢你还在这里,我编辑了我的帖子。好像网址很好
【参考方案1】:
从路由中,edit_password_reset
url 需要一个资源 ID。您可以通过将 @user
作为 url 的参数传递来修复它。
<%= link_to "Reset password", edit_password_reset_url(@user) %>
如果你想发送额外的参数然后
<%= link_to "Reset password", edit_password_reset_url(@user, reset_token: @user.reset_token, email: @user.email) %>
如果您想在 url 中使用 reset_password_token
而不是 :id
,请使用自定义路由,例如
在 routes.rb 中
resources :password_resets, only: [:new, :create, :update] # Take out edit route
get '/password_resets/:reset_password_token/edit', to: "password_resets#edit", as: "edit_password_reset"
现在在电子邮件模板中
<%= link_to "Reset password", edit_password_reset_url(@user.reset_token) %>
如果您觉得这有帮助,请告诉我。
【讨论】:
以上是关于Ruby on Rails:延迟的作业无法使用邮件程序并给出路由错误的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Ruby on Rails 中完成延迟作业后执行 ajax 回调?