Comparing myisam_suggest with a book’s index

Recently I had an idea how to illustrate how myisam_suggest works by a comparison with a normal printed book’s index:

“AutoSuggest” for a printed book

Image you have a thick book with hundreds of thousands of words in it. Now you want to know all words beginning with “fu” for some reason (= AutoSuggest).

Without the (full-text) index on the book’s last pages, you’d have to read the whole book, remember all words, sort them alphabetically, erase duplicates and then look at the words beginning with “fu”. A very time-intensive process.

However, if an index is available, you can just scroll to the index, scroll further to “f”, then “fu” and read the words there (ignoring the referenced page numbers). Takes almost no time.

AutoSuggest for MyISAM tables

The same process applies to MyISAM tables, too. Without full-text index, all tables would have to be scanned with something like WHERE description LIKE “% fu%” which would take unacceptable time and resources.

But with full-text index, there’s already a sorted list with all words where you can scroll to and then read all entries beginning with “fu” (in this case, ignoring the referenced records instead of the referenced pages). This is exactly what myisam_suggest does.

Rails: Digitally sign outgoing emails (S/MIME)

In this article, I will introduce one method to digitally sign outgoing emails with S/MIME using Ruby on Rails.

require ‘openssl’ vs. Kernel.system openssl

At first, I tried to sign mails using the Ruby OpenSSL library which is basically a lightweight wrapper for libopenssl. However, I was not successful; I found out how to create PKCS7 signatures in general, but not especially for S/MIME mails.

So I decided to use the openssl command line tool that can be invoked like this:

openssl smime -sign -signer $CERT_FILE -passin pass:$CERT_PASS
  -in $UNSIGNED_MAIL -out $SIGNED_MAIL -certfile $CERT_CA_FILE
  -from 'your ' -to 'recipients <email@address>'
  -subject 'The Subject'

This command takes an unsigned MIME mail (located in a file whose path is stored in $UNSIGNED_MAIL), signs it with $CERT_FILE (protected by $CERT_PASS), attaches the Certification Authority’s certificate ($CERT_CA_FILE) and stores the resulting signed mail (which is in multipart/signed format) into $SIGNED_MAIL, setting the From:, To: and Subject: headers appropriately.

Invoking openssl from your mailer

To sign all emails that go out from your mailer (which is probably derived from ActionMailer::Base), you can use this code:

class Notifications < ActionMailer::Base
  CERT_DIR = ‘…’
  CERT_FILE = ‘cert.pem’
  CERT_PASS = ‘passphrase for cert.pem’
  CERT_CA_FILE = ‘your-ca.pem’

  #… your other mailer code …

  # overload deliver! to sign outgoing emails
  def deliver!
    unsigned = Tempfile.new ‘notification-unsigned’
    unsigned.write mail
    unsigned.close

    signed = Tempfile.new ‘notification-signed’
    signed.close

    Kernel.system ‘openssl’, ‘smime’, ‘-sign’, ‘-signer’, CERT_DIR+CERT_FILE, ‘-passin’, ‘pass:’+CERT_PASS,
      ‘-in’, unsigned.path, ‘-out’, signed.path, ‘-certfile’, CERT_DIR+CERT_CA_FILE,
      ‘-from’, ‘YOUR NAME <EMAIL@ADDRESS>’, ‘-to’, mail.to.join(’,’), ‘-subject’, mail.subject
    unsigned.close!

    mail.instance_variable_set ‘@smime_encoded’, File::read(signed.path)
    signed.unlink

    class << mail
      define_method :encoded do
        self.instance_variable_get ‘@smime_encoded’
      end
    end

    super mail
  end
end

This is a bit dirty because the first parameter for “deliver!” is normally a TMail::Mail object whose “encoded” method is called by the delivery method. In the code above, I have replaced the “mail” object (first parameter for “deliver!”) by a String with an attached “encoded” method that returns the string itself. However, it was the most simple working solution I could think of. Please tell me if you know a cleaner solution (re-parsing the signed email into a TMail::Mail object doesn’t work because it changes the signed mail by a few bytes and makes the signature invalid).

The above code assumes that both public (signature) and private key are stored in the $CERT_FILE. If this is not the case for you, you’d have to modify the command line slightly.

Rails: Using HTML typography automatically

There’s a way you can use special characters for HTML typography in Rails without much work: Just let your views about raw text and then overwrite the html_escape (h) method:

module ApplicationHelper

  def h(s)
    super(s). \
      gsub(‘(c)’  , ‘&copy’). \
      gsub(‘(r)’  , ‘&reg;’). \
      gsub(‘(tm)’ , ‘&trade;’). \
      gsub(’ 1/2 ‘, ’ &frac12; ‘). \
      gsub(’ 1/4 ‘, ’ &frac14; ‘). \
      gsub(’ 3/4 ‘, ’ &frac34; ‘). \
      gsub(‘… ‘ , ‘&hellip; ‘). \
      gsub(’ — ‘ , ’ &mdash; ‘). \
      gsub(’ - ‘  , ’ &ndash; ‘)
  end

In this case, three hyphens are replaced by ” — “, three dots by an ellipse etc.

Now just make sure that your views use it correctly and output “--” instead of “-” etc. when it is necessary.

Rails 2.3: Using ActiveRecord from within console application

If you use Ruby on Rails and want to have access to ActiveRecord and all the other nifty features from within a standalone Ruby script (for instance, a cronjob script that checks integrity of your data), all you need to do is including the “environment” script that fully sets up the Rails environment. In this case I use the “../config” path because my script is located in the app’s “scripts” directory.

#!/usr/bin/ruby
require ’../config/environment’

# now all Rails features are available, all plugins loaded etc.

# demo
records = Model.find :all
for r in records
  puts ‘Checking ‘ + r.name + ’ …’
end

Image | WordPress Themes