Ruby Parallel Processing made simple

Parallel processing for ruby:

  • Speeds up processing by %{number_of_cpus} X
  • Protects data from destructive operations

Usage

data = something_big()

require 'parallel'

#runs in number_of_your_cpus
results = Parallel.map(data) do |chunk|
  expensive_computation chunk
end

#4 processes
results = Parallel.map(data, :in_processes=>4) do |chunk|
  expensive_computation chunk
end

#same with threads (no speedup through multiple cpus,
#but speedup for blocking operations)
results = Parallel.map(data, :in_threads=>4) do |chunk|
  blocking_computation chunk
end

Parallel.each(data){|chunk| ..same.. }

Go parallel !

Simple Translated Storage of ActiveRecord Columns

There are several solutions for storing translations, but most of them involve additional migrations for each  translated column. A more as-you-go solution offers translated_attributes Rails Plugin

  • stores all translations into one ‘translations’ table
  • AR-like interface (validations/update_attributes etc works)
  • performance (only one request to translations table for any amount of translated columns)
class User < ActiveRecord::Base
  translated_attributes :name, :about, :description
end

User.new.name = 'Myself' #stores name_in_#{I18n.locale}
User.new.name_in_de = "Ich"
...

Have a look and tell me your opinion!

Ruby Monkey-Reflection to get Method Parameter Names

The standard Ruby reflection does not provide for getting method parameter names (at least afaik), and the only other solution that I found is using parsetree, which is “more clean” then this method, but requires another gem…

So here it comes Monkey-Style:

def methods_with_parameters(klass, path_to_file)
  methods = klass.instance_methods(false).sort
  lines = File.read(path_to_file)
    
  #find params for methods
  methods.map do |method|
    lines.detect{|l|l=~/def #{method}(.*)$/}
    parameters = $1.tr('()','').split(',').map{|p| p.gsub(/=.*/, '')}.reject(&:blank?).map(&:strip)
    [method, parameters]
  end
end

How to Preview All ActionMailer Mails in the Browser

Notice: this needs to be admin/development only, since it can be really dangerous in the wrong hands… (uses eval or param…)

  • Developers see what they are dooing (just hit Refresh)
  • Livesaver for HTML Emails
  • Non-developers can check alignment/spelling/… sooo easy
  • Generated mails can be shared through url so no need for forwarding/screenshots

View
Just make a form that submits:

  • the method you want to call
  • list of arguments to use
  <%form_tag({:action=>'make_mail'}, :method=>:get) do%>
    <%=select_tag :method_name, options_for_select(UserMailer.public_instance_methods(false).sort)%>
    Models: Product.find(12322) / String: "abc" / Numbers: 123 / Array: [1,2,3]
    <table>
      <%5.times do |i|%>
        <tr>
          <td><%=i%></td>
          <td><%=text_field_tag "args[]", '', :style=>'width:300px'%></td>
        </tr>
      <%end%>
    </table>
    <%=submit_tag 'Preview'%>
    <%=submit_tag 'Send'%>
  <%end%>
<%end%>

Controller
Evals the ‘args’ and send or previews the mail.

def make_mail
  args = params[:args].map{|arg| eval arg}.compact

  if params[:commit]=='Preview' #preview button
    @text = UserMailer.send("create_#{params[:method_name]}", *args).body
    if @text =~ /<body>/
      render :text=>@text
    else
      render :text=>"<pre>#{@text}</pre>"
    end
  else #Send button
    UserMailer.send("deliver_#{params[:method_name]}", *args)
    flash[:notice] = 'Mail sent!'
    redirect_to params.merge(:action=>:index)
  end
end

Happy mail preview too you 😀