Resque tasks, worker, web, GenericJob setup for Rails

Usage

resque-web
QUEUE='*' COUNT=3 rake resque:workers &

GenericJob.publish(Product, :reindex_all, :args=> [{:limit=>1000}]

Setup

#append to Rakefile
require 'resque/tasks'
namespace :resque do
  task :setup => :environment
end

class GenericJob
  @queue = :generic

  def self.perform(klass, method, options={})
    options = options.with_indifferent_access
    if options.has_key?(:args)
      klass.constantize.send(method, *options[:args])
    else
      klass.constantize.send(method)
    end
  end

  def self.publish(klass, method, options={})
    Resque.enqueue(self, klass.to_s, method.to_s, options)
  end
end


If you plan to process instances of AR with this setup, be sure to add serialize_ar / deserialize_ar from solving background processing with a single generic background-job

Kill process in capistrano without pkill

Pkill has issues with capistrano, because the pkill command is always inside a capistrano command, thereby matching and killing itself.

pkill free solution

task :foo do
  kill_processes_matching "MaintenanceDaemon"
end

def kill_processes_matching(name)
  run "ps -ef | grep #{name} | grep -v grep | awk '{print $2}' | xargs kill || echo 'no process with name #{name} found'"
end

Prevent paths in mails (ActionMailer)

It happens once in a while, a path gets into a mail, but with this patch it should happen nevermore.

Looks for paths in non-production and raises if it finds one.


unless Rails.env.production?
  class ActionMailer::Base
    def render_message_with_path_protection(method_name, body)
      body = render_message_without_path_protection(method_name, body)
      if body =~ %r{((href|src)=['"]/.*)}
        raise "Use absolute path in mail urls! #{$1}"
      end
      body
    end

    alias_method_chain :render_message, :path_protection
  end
end

Hash#first for ruby 1.8.6

Just got some failing specs from our 1.8.6 test runner, when using OrderedHash#first, so we fix that…

# add {}.first if its not there (1.8.6)
unless {}.respond_to?(:first)
  class Hash
    def first
      return if keys.empty?
      [keys.first, self[keys.first]]
    end
  end
end

Fixing Rails nested attributes on collections with sti

user.persons.build(:type=>’Manager’).class != Manager, which makes a lot of problems with single table inheritance, especially when dealing with accepts_nested_attributes_for / fields_for that rely on correct class of the associated.

# Make build associations have their given type
# Makes that: user.persons.build(:type=>Manager).class == Manger
class ActiveRecord::Reflection::AssociationReflection
  def build_association(*options)
    if options.first.is_a?(Hash) and options.first[:type].presence
      options.first[:type].to_s.constantize.new(*options)
    else
      klass.new(*options)
    end
  end
end

rails issue