require 'sidekiq' module Softwear module Lib module Enqueue extend ActiveSupport::Concern class Worker include ::Sidekiq::Worker def perform(model_name, id, method, *args) model_name.constantize.find(id).send(method, *args) end end module ClassMethods def enqueue(*method_names) if method_names.last.is_a?(Hash) options = method_names.pop else options = {} end raise "enqueue what?" if method_names.empty? # We will extend the class mod and include the instance mod. # This allows us to override the generated enqueue methods and # call `super`. # enqueue_class_mod = Module.new enqueue_instance_mod = Module.new method_names.each do |method_name| enqueue_class_mod.module_eval <<-RUBY, __FILE__, __LINE__ + 1 def #{method_name}(id, *args) find(id).#{method_name}(*args) end RUBY if Rails.env.production? enqueue_class_mod.module_eval <<-RUBY, __FILE__, __LINE__ + 1 def enqueue_#{method_name}(id, *args) ::Sidekiq::Client.push( 'class' => ::Softwear::Lib::Enqueue::Worker, 'args' => [name, id, #{method_name.inspect}] + args, 'queue' => #{options[:queue].inspect} ) end RUBY enqueue_instance_mod.module_eval <<-RUBY, __FILE__, __LINE__ + 1 def enqueue_#{method_name}(*args) self.class.enqueue_#{method_name}(id, *args) end RUBY else enqueue_class_mod.module_eval <<-RUBY, __FILE__, __LINE__ + 1 def enqueue_#{method_name}(id, *args) self.#{method_name}(id, *args) end RUBY enqueue_instance_mod.module_eval <<-RUBY, __FILE__, __LINE__ + 1 def enqueue_#{method_name}(*args) self.#{method_name}(*args) end RUBY end end send :extend, enqueue_class_mod send :include, enqueue_instance_mod r = method_names.map { |m| "enqueue_#{m}".to_sym } r.size == 1 ? r.first : r end end included do extend ClassMethods def enqueue(method_name, *args) send("enqueue_#{method_name}", *args) end end end end end