草庐IT

ruby-on-rails - sidekiq worker rails 两个 worker 之一的参数错误

coder 2023-07-19 原文

我有一个 Rails 应用程序,它使用带有 Redis 的 sidekiq 来发送邮件。我有 2 个 worker ,但其中一个我得到错误的参数数量错误(ArgumentError:错误的参数数量(5 个为 2)),我不知道为什么,因为另一个基本相同,工作完美.这是两者的代码/解释:Contactmailer w/Postmanworker 是工作人员,它在 sby 提交联系表格时发送电子邮件;带有 Taskcreatorworker 的 Taskmailer 给出了错误,它会在创建任务时发送一封电子邮件。我已经尝试过使用不同数量的参数,因为我看到我现在有 6 个参数,但仍然给出 5 for 2 错误 => 在 sidekiq 之前,taskmailer 也能正常工作。首先,我尝试只传递 2 个参数@task.id 和@current_user,我可以调用 task_created.html.erb 中的所有 6 个变量。从那时起,我尝试了不同种类和数量的参数。正如您在下面看到的,目前我尝试在 Controller 和邮件程序中给出所有 6 个变量,以及它们被调用的样子。我还展示了 user.rb,因为模型有点棘手。

由于联系人邮件程序在开发/生产环境中都能完美运行,我可能在下面的代码中犯了错误,这不是服务器/安装问题。

任务 Controller .rb

def create
  @user = current_user
  @task = Task.new(task_params))
  if @task.save
    h = JSON.generate( {'task_assigner_first_name' => @current_user.profile.first_name,
                      'task_assigner_last_name' => @current_user.profile.last_name,
                      'task_executor_first_name' => @task.executor.profile.first_name,
                      'task_executor_email' => @task.executor.email,
                      'task_executor_id' => @task.executor_id,
                      'task_id' => @task.id
                       } )
    TaskcreatorWorker.perform_async(h, 5)
    #TaskMailer.task_created(current_user, @task).deliver_later
    flash[:success] = "Task saved!"
    redirect_to user_tasks_path(current_user)
  else
    render action: :new
  end
end

private
def task_params
  params.require(:task).permit(:executor_id, :name, :content, :deadline).merge(assigner_id: current_user.id)
end

contacts_controller.rb

def create
  @contact = Contact.new(contact_params)
  if @contact.save
    h = JSON.generate({ 'name' => params[:contact][:name],
                      'email' => params[:contact][:email],
                      'comment' => params[:contact][:comment] })

    PostmanWorker.perform_async(h, 5)
    #ContactMailer.contact_email(name, email, comment).deliver_later
    flash[:success] = "Message sent."
    redirect_to new_contact_path
  else
    flash[:danger] = "Error occured."
    render action: :new
  end
end

private
def contact_params
  params.require(:contact).permit(:name, :email, :comment)
end

taskcreator_worker.rb

class TaskcreatorWorker
  include Sidekiq::Worker

  def perform(h, count)
    h = JSON.load(h)
    TaskMailer.task_created(h['task_assigner_first_name'], h['task_assigner_last_name'], h['task_executor_first_name'], h['task_executor_email'], h['task_executor_id'], h['task_id']).deliver_later
  end
end

postman_worker.rb

class PostmanWorker
  include Sidekiq::Worker

  def perform(h, count)
    h = JSON.load(h)
    ContactMailer.contact_email(h['name'],h['email'],h['comment']).deliver_later
  end 
end

任务邮件.rb

class TaskMailer < ActionMailer::Base

  def task_created(task_assigner_first_name, task_assigner_last_name, task_executor_first_name, task_executor_email, task_executor_id, task_id) 
    @task.assigner.profile.first_name = task_assigner_first_name
    @task.assigner.profile.last_name = task_assigner_last_name
    @task.executor.profile.first_name = task_executor_first_name
    @task.executor.email = task_executor_email
    @task.executor_id = task_executor_id
    @task.id = task_id

    mail(from: 'faskyn@gmail.com',
         to: "#{task.executor.email}",
         subject: "[Faskyn] New task/favor from #{task.assigner.profile.first_name} #{task.assigner.profile.last_name}"
         )
  end
end

contact_mailer.rb

class ContactMailer < ActionMailer::Base
  default to: 'faskyn@gmail.com'

  def contact_email(name, email, content)
    @name = name
    @email = email
    @content = content

    mail(from: email, subject: 'Contact form message')
  end
end

task_created.html.erb

<p>Hi <%= @task.executor.profile.first_name%>,</p>

<p><%= @current_user.profile.first_name %> <%= @current_user.profile.last_name %> just sent you a new task/favor.</p>

<p>You can check it out <%= link_to "here", user_task_url(@task.executor_id, @task.id) %>.</p>

<p>Cheers,<br />Faskyn Team</p>

contact_email.html.erb

<!DOCTYPE html>
<html>
  <head>
  </head>
  <body>
   <p>You have received a message from the site's contact form, from <%= "#{ @name }, #{ @email}." %></p>
   <p><%= @comment %></p>
 </body>
</html>

用户.rb

  has_one :profile, dependent: :destroy
  has_many :assigned_tasks, class_name: "Task", foreign_key: "assigner_id", dependent: :destroy
  has_many :executed_tasks, class_name: "Task", foreign_key: "executor_id", dependent: :destroy

sidekiq 日志的错误信息:

2015-09-28T12:48:33.600Z 20264 TID-outp8berw TaskcreatorWorker JID-a0816ab8d1881e81c58569d2 INFO: start
2015-09-28T12:48:33.633Z 20264 TID-outp8berw TaskcreatorWorker JID-a0816ab8d1881e81c58569d2 INFO: fail: 0.033 sec
2015-09-28T12:48:33.635Z 20264 TID-outp8berw WARN: {"class"=>"TaskcreatorWorker", "args"=>["{\"task_assigner_first_name\":\"Szilard\",\"task_assigner_last_name\":\"Hungarian\",\"task_executor_first_name\":\"Andrew\",\"task_executor_email\":\"szilard.magyar@speaktoit.com\",\"task_executor_id\":3,\"task_id\":82}", 5], "retry"=>true, "queue"=>"default", "jid"=>"a0816ab8d1881e81c58569d2", "created_at"=>1443439028.7889678, "enqueued_at"=>1443444513.5961752, "error_message"=>"wrong number of arguments (5 for 2)", "error_class"=>"ArgumentError", "failed_at"=>1443439028.8198888, "retry_count"=>8, "retried_at"=>1443444513.632468}
2015-09-28T12:48:33.636Z 20264 TID-outp8berw WARN: ArgumentError: wrong number of arguments (5 for 2)
2015-09-28T12:48:33.636Z 20264 TID-outp8berw WARN: /Users/Silo/Desktop/ruby_on_rails/faskyn/app/mailers/task_mailer.rb:3:in `task_created'


2015-09-28T16:17:07.015Z 23136 TID-ow4vpw9ik TaskcreatorWorker JID-6cb35b9b42bebdbf128746c0 INFO: start
2015-09-28T16:17:08.178Z 23136 TID-ow4vpw9ik TaskcreatorWorker JID-6cb35b9b42bebdbf128746c0 INFO: fail: 1.163 sec
2015-09-28T16:17:08.180Z 23136 TID-ow4vpw9ik WARN: {"class"=>"TaskcreatorWorker", "args"=>["{\"task_assigner_first_name\":\"Szilard\",\"task_assigner_last_name\":\"Hungarian\",\"task_executor_first_name\":\"Peter\",\"task_executor_email\":\"szilard@api.ai\",\"task_executor_id\":2,\"task_id\":83}", 5], "retry"=>true, "queue"=>"default", "jid"=>"6cb35b9b42bebdbf128746c0", "created_at"=>1443456758.3800051, "enqueued_at"=>1443457026.97385, "error_message"=>"undefined method `assigner' for nil:NilClass", "error_class"=>"NoMethodError", "failed_at"=>1443456758.398172, "retry_count"=>3, "retried_at"=>1443457028.177601}
2015-09-28T16:17:08.180Z 23136 TID-ow4vpw9ik WARN: NoMethodError: undefined method `assigner' for nil:NilClass
2015-09-28T16:17:08.180Z 23136 TID-ow4vpw9ik WARN: /Users/Silo/Desktop/ruby_on_rails/faskyn/app/mailers/task_mailer.rb:4:in `task_created'

最佳答案

您正在使用来自 sidekiq 时未设置的对 @task 实例变量的引用。您需要在邮件程序方法本身中初始化您的 @task 变量。根据所需的结果,可以通过多种方式完成。

  1. @task = Task.new

    初始化任务及其所需的所有对象(assignerexecutor),然后将从您的 worker 传入的值赋予它们。

  2. @task = Task.find(task_id)

    这是一个更好的解决方案,因为您不需要通过 sidekiq 传递所有参数。您的任务已经保存在数据库中,因此只需传递 id 并使用它来查找任务。它将已经拥有所有必需的数据。

任务 Controller .rb

    def create
      @user = current_user
      @task = Task.new(task_params)
      if @task.save
        TaskcreatorWorker.perform_async(@task.id, @user.id)
        flash[:success] = "Task saved!"
        redirect_to user_tasks_path(current_user)
      else
        render action: :new
      end
    end

taskcreator_worker.rb

    class TaskcreatorWorker
      include Sidekiq::Worker
    
      def perform(task_id, user_id) # Removed count since you weren't using it. Add it back if needed
        TaskMailer.task_created(
          Task.find(task_id),
          User.find(user_id)
        ).deliver_now # deliver_now since we're already in a sidekiq worker
      end
    end

任务邮件.rb

    class TaskMailer < ActionMailer::Base
      def task_created(task, user)
        # Initialize variables you use in your view
        @task = task
        @current_user = user
        mail(from: 'faskyn@gmail.com',
             to: "#{task.executor.email}",
             subject: "[Faskyn] New task/favor from "\
                      "#{task.assigner.profile.first_name} "\
                      "#{task.assigner.profile.last_name}"
        )
      end
    end

关于ruby-on-rails - sidekiq worker rails 两个 worker 之一的参数错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32823087/

有关ruby-on-rails - sidekiq worker rails 两个 worker 之一的参数错误的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. Ruby 解析字符串 - 2

    我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?

  4. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  5. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  6. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  7. ruby-on-rails - rails : keeping DRY with ActiveRecord models that share similar complex attributes - 2

    这似乎应该有一个直截了当的答案,但在Google上花了很多时间,所以我找不到它。这可能是缺少正确关键字的情况。在我的RoR应用程序中,我有几个模型共享一种特定类型的字符串属性,该属性具有特殊验证和其他功能。我能想到的最接近的类似示例是表示URL的字符串。这会导致模型中出现大量重复(甚至单元测试中会出现更多重复),但我不确定如何让它更DRY。我能想到几个可能的方向...按照“validates_url_format_of”插件,但这只会让验证干给这个特殊的字符串它自己的模型,但这看起来很像重溶液为这个特殊的字符串创建一个ruby​​类,但是我如何得到ActiveRecord关联这个类模型

  8. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  9. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  10. ruby - 如何在 Ruby 中顺序创建 PI - 2

    出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits

随机推荐