2015-09-28 5 views
1

У меня есть приложение для рельсов, использующее sidekiq w/redis для почтовых отправлений. У меня есть 2 сотрудника, но для одного из них я ошибаюсь в количестве аргументов error (ArgumentError: неправильное количество аргументов (5 для 2)), и я не знаю, почему, поскольку другой, который в принципе тот же, отлично работает , Вот код/​​пояснение для обоих: Contactmailer w/Postmanworker - это рабочий, который отправляет электронное письмо, когда sby отправляет форму контакта; Taskmailer w/Taskcreatorworker дает ошибку, которая отправляет электронное сообщение при создании задачи. Я уже пробовал с разным количеством аргументов, так как я вижу, что на данный момент у меня есть 6 аргументов, но все равно дает 5 для 2 ошибок => До sidekiq, taskmailer работал. Для начала я попытался передать только 2 args @ task.id и @current_user, и я мог бы вызвать все 6 переменных, которые можно найти в task_created.html.erb. С тех пор я пробовал разные типы и количество аргументов. Как вы видите ниже, на данный момент я стараюсь дать все 6 переменных в контроллере и почтовой программе точно так же, как они называются. Я также показываю user.rb, так как модель немного сложна.sidekiq work rails аргумент ошибка для одного из двух работников

Поскольку контактная почта работает отлично как в dev/prod env, я, вероятно, допустил ошибку в приведенном ниже коде, и это не проблема сервера/установки.

tasks_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 

task_mailer.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: '[email protected]', 
     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: '[email protected]' 

    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> 

user.r б сообщение

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\":\"[email protected]\",\"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\":\"[email protected]\",\"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' 
+0

Пожалуйста, пост трассировки стека вашей ошибки. –

+0

Вам нужны и другие журналы? –

+0

Журналы показывают, что ошибка исходила из метода 'TaskMailer # task_created' точно. Примеры кода показывают, что метод действительно ожидает более двух аргументов. Поэтому я пришел к выводу, что наиболее вероятным решением является то, что вы не перезапустили sidekiq через некоторое время. Код кэшики Sidekiq и может иметь старую ссылку на 'TaskMailer'. –

ответ

1

Вы используете ссылку на ваш @task переменной экземпляра, который не задан при выходе из sidekiq. Вам нужно инициализировать переменную @task в самом методе почтовой программы. В зависимости от желаемого результата это можно сделать несколькими способами.

  1. @task = Task.new

    Инициализировать задачу и все объекты, которые он нуждается (assigner и executor), а затем дать им значение, переданное в от вашего работника.

  2. @task = Task.find(task_id)

    Это лучшее решение, так как тогда вам не нужно передавать все параметры через sidekiq. Ваша задача уже сохранена в базе данных, поэтому просто передайте идентификатор и используйте его для поиска задачи. У него будут все необходимые данные.

tasks_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 

task_mailer.rb

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

Сиим отлично работает. Спасибо! Я довольно новичок в рельсах, жаждущий быть настолько некомпетентным. Позвольте мне задать два последних вопроса, так как я все еще немного смущен: 1. Я последовал этому: https://www.codefellows.org/blog/how-to-set-up-a-rails-4-2- почтовая программа-с-sidekiq. Является ли это хорошим примером в соответствии с вами, или JSON.generate не нужен? 2. Почему он работал с моим контактным лицом и почему не с задачей? Для моих глаз эти два идентичны. Thx, заранее! –

+0

1) Я не видел ничего плохого в этом учебнике на первый взгляд. Sidekiq по умолчанию использует YAML для хранения данных, которые вы вставляете в него. JSON может использоваться для управления форматом данных, если вы хотите, но не обязательно. 2) В вашей другой почтовой программе вы не использовали ранее инициализированные переменные. Вы присвоили значения 3 новым переменным, как и в моем новом ответе. В предыдущем коде вы ссылались на переменную '@ task', которая не была установлена. –