I’m working on a project that does some graphing, I and needed to do a linear best fit. A quick google search didn’t find the ruby code snippet I was looking for, so I converted one from PHP. ( Original nasty looking quasi-OO PHP source ) Sorry, no unit tests :)


class LinearRegression
  attr_accessor :slope, :offset

  def initialize dx, dy=nil
    @size = dx.size
    dy,dx = dx,axis() unless dy  # make 2D if given 1D
    raise "arguments not same length!" unless @size == dy.size
    sxx = sxy = sx = sy = 0
    dx.zip(dy).each do |x,y|
      sxy += x*y
      sxx += x*x
      sx  += x
      sy  += y
    end
    @slope = ( @size * sxy - sx*sy ) / ( @size * sxx - sx * sx )
    @offset = (sy - @slope*sx) / @size
  end

  def fit
    return axis.map{|data| predict(data) }
  end

  def predict( x )
    y = @slope * x + @offset
  end

  def axis
    (0...@size).to_a
  end
end

ruby Date extensions

I recently cooked these up, thought someone else might find them handy. Now you can say date.first_of_month, date.first_of_year, etc.


module DateExtensions
  def first_of_week
    self - self.wday
  end

  def first_of_month
    self - self.day+1
  end

  def first_of_quarter
    (self << (self.month%3 - 1 )%3) - self.day+1
  end

  def first_of_year
    (self << self.month-1) - self.day+1  
  end
end
Date.send :include, DateExtensions

Addendum: oops, looks like there are already similar methods in Rails’ ActiveSupport:

beginning_of_* rather than first_of_*

However, begining_of_week assumes Monday is the first day of the week, while my version assumes Sunday is the first day.

Here are my tests:

require File.dirname(__FILE__) + '/../test_helper'

class DateExtensionsTest < Test::Rails::TestCase

  def test_first_of_week
    day = Date.new( 2008, 1, 1 )
    w   = day.first_of_week
    # sunday is first day of week
    assert_equal 0, w.wday
    assert_equal 30, w.day
  end

  def test_first_of_month
    day = Date.new( 2008, 1, 15 )
    assert_equal 1, day.first_of_month.day
  end

  def test_first_of_year
    day = Date.new( 2008, 5, 27 )
    y   = day.first_of_year
    assert_equal 1, y.month
    assert_equal 1, y.day
  end

  def test_first_of_quarter_q1    
    [1,2,3].each do |month|
      day = Date.new( 2008, month, 13 )
      q   = day.first_of_quarter
      assert_equal 1, q.day
      assert_equal 1, q.month
    end
  end

  def test_first_of_quarter_q2
    [4,5,6].each do |month|
      day = Date.new( 2008, month, 13 )
      q   = day.first_of_quarter
      assert_equal 1, q.day
      assert_equal 4, q.month
    end
  end

  def test_first_of_quarter_q3
    [7,8,9].each do |month|
      day = Date.new( 2008, month, 13 )
      q   = day.first_of_quarter
      assert_equal 1, q.day
      assert_equal 7, q.month
    end
  end

  def test_first_of_quarter_q4
    [10,11,12].each do |month|
      day = Date.new( 2008, month, 13 )
      q   = day.first_of_quarter
      assert_equal 1, q.day
      assert_equal 10, q.month
    end    
  end

end

I’ve been playing with block helpers for some time now, and I love them for their semantic goodness and clarity. I know that Rails 2 has an assert_email method, which plays nicely with assert_select assert_select_email method. However, as far as I could tell, this doesn’t allow you to assert any of the headers such as to, from, etc.

Enter assert_emails_sent:


  def test_send_crash_data
    device_id = 2
    assert_email_sent :to => AdminNotifier::CLIENT_CRASH_EMAIL,
                      :from => AdminNotifier::SYSTEM_EMAIL,
                      :subject => "Application crashed.",
                      :body => /device id #{device_id} crashed.+whoops I crashed/ do
      AdminNotifier.deliver_send_crash_data('whoops I crashed', device_id)                      
    end
  end

  • One cool feature is that the values of :to and :from will be automagically sent #email, so you can just say :to => @user, as long as @user.responds_to?(:email).
  • Another bonus feature is that you can use either strings or regexps.

grab the code here.

staying DRY with custom shoulds

Recently I’ve been refactoring legacy Test::Unit code to use shoulda. Sometimes you can’t factor out repetitive stuff into a context, but you still want to be DRY. Below is an example case of refactoring into a custom should. Note that you need to use class variables, and that the self.should_* method needs to be defined before it’s actually used, since shoulda is built upon metaprogramming which gets evaluated at the class level.


...

  def self.should_request sym
    sym = sym.to_s
    context "when requesting #{sym}" do
      setup do
        get :download, {:id => @@podcast.id, :type => sym}, @@session
      end
      should "ask for a device" do
         assert_match /Please select a device to download content/,  @response.body
      end
      should "increment the message count when sent #add_to_device" do
        assert_difference 'Message.count( :conditions => "device_id = 1")', @@podcast.episodes.size do
          xhr :post, :add_to_device, {:id => 1, :type => 'all', :podcast_id => @@podcast.id}, @@session
        end
      end
    end
  end

  context "A valid account" do
    setup do
      @account = accounts(:accounts_002)
      @@session = {:account_id => @account.id}
      @account.devices << Device.find(1)
      @@podcast = podcasts(:joe_cartoon)
      @@session.merge!({:podcast_episodes => @@podcast.episodes})
    end

    should_request :all
    should_request :latest
    should_request :episode
  end

...

Shoulda talk from SF Ruby Meetup

We hosted the SF Ruby Meetup last night, which was a smashing success. It was fun to have 50+ Ruby geeks crammed into our office. :)

Here are the slides from my presentation about Shoulda.

valid model attribute factory test helpers

I like to use factory test helpers to generate attributes which I then pass to ActiveRecord. The default output is expected to be valid (hence the usage with create-bang below). If you want to override any of the defaults, you can simply use Hash#merge.

Here’s an example, using shoulda. It should be pretty clear how it can be applied to vanilla Test::Unit (or the testing framework du jour ;).


##  I put this in test_helper.rb so I can use it across all tests.
## You could put it in the actual derived test class as well.

  def valid_user_attrs( unique = DateTime.now )
    { :email => "{unique.hash.abs}@example.com", :first_name => "dummy", :last_name => "user_#{unique}", :profile_attributes => valid_profile_attrs }
  end

  def valid_profile_attrs
    ...
  end


## Here’s the actual test case
  
class UserTest < Test::Rails::TestCase

  context "Two Users" do
    setup do
      @user = User.create!( valid_user_attrs )
      @user2 = User.create!( valid_user_attrs.merge( :email => "dummy123@dummy.com" ) )
    end

    should "not be friends" do
      assert !@user.friends.include?( @user2 )
      assert !@user2.friends.include?( @user )
    end

  end
end

		
		
	

textmate bundle for shoulda

I’m pleased to announce a textmate bundle that I assembled for the wonderfully simple shoulda testing framework.

The snippets were contributed by Dan Croak, James Golick, and Sam Livingston-Gray, and mashed up by me.

Grab the latest version here: http://macromates.com/svn/Bundles/trunk/Review/Bundles/Ruby%20Shoulda.tmbundle

passing a block to gsub will yield for matches

did you know gsub can be passed a block to operate on matches? I just learned it from this blog post.

I was looking for a way to backquote parentheses and spaces… here’s how I did it:

>> puts "this (is a) test".gsub( /[\s\(\)]/ ){ |c| "\\#{c}" }
this\ \(is\ a\)\ test
=> nil

alphadecimal (base 36) hashes in ruby

Here’s a little trick I discovered about a year ago. The Integer#to_s method takes an argument to change the base (it defaults to base 10 of course). The highest base you can use is 36, which is [a-z0-9]. There are many names for base 36, including the proper sexatrigesimal, the common hextridecimal, and the more modern alphadecimal.

Combined with the String#hash and Time#hash methods, you can get sweet little TinyUrl style hashes.

check it:

# timestamp
>> DateTime.now.hash.abs.to_s(36)
=> "5ynfka" 

# invite code
>> "joe@momma.org".hash.to_s(36)
=> "emhs98" 

Not sure of the ultimate-in-the-entire-universe uniqueness of this type of hash, which I believe is based on some simple XORs… anyone care to comment?

I am writing some code to verify an RSA signature in ruby. I have the public key in the form of an exponent and modulus. Now, the trick is for me to generate the RSA public key from those values. I haven't found any documentation on this, but have discovered the answer by playing with ruby's OpenSSL library.

Here's the code:


key = OpenSSL::PKey::RSA.new
exponent = OpenSSL::BN.new '65537'
modulus = OpenSSL::BN.new '112864421120687974159372000080760039219116461925481276352886367473487891241213943153420378504937603763046030555516582638386721662553157906521599209028584201997048923805195002300818977900203259289042008628478507712149599372498945513622899023530831288613948081523445790489877779793487480652356150164543518882963'
key.e = exponent
key.n = modulus
key 

Now key is initialized with the modulus and exponent values. You can now use the public key to verify the signature.

a yaml_to_shoulda rake task

Inspired by err’s cryptic yaml_to_spec rake task, I wrote my own version for shoulda, based off of Jeremy Hubert’s textmate bundle It’s a bit less cryptic, and it for extra nerd points it uses recursion to allow for nested contexts. :)


desc "Converts a YAML file into a Shoulda skeleton" 
task :yaml_to_shoulda do
  require 'yaml'

  def yaml_to_context hash, indent=0
    indent1 = '  '*indent
    indent2 = '  '*(indent+1)
    hash.each_pair do |context,shoulds|
      puts indent1+"context \"#{context}\" do" 
      puts    
      shoulds.each do |should|
        yaml_to_context( should, indent+1 ) and next if should.is_a?( Hash )
        puts indent2+"should_eventually \"#{should.gsub(/^should +/,'')}\" do" 
        puts indent2+"end" 
        puts
      end
    puts indent1+"end" 
  end 

  yaml_to_context( YAML.load_file( ENV['FILE'] || !puts("Pass in FILE argument.") && exit ) )
end

Here is an example YAML file and it’s output:

This blog post:
- should mention shoulda
- should be concise
- should be written by me
- when saved as a draft:
  - should have multiple revisions
  - should not be published publicly



context "This blog post" do

  should_eventually "mention shoulda" do
  end

  should_eventually "be concise" do
  end

  should_eventually "be written by me" do
  end

  context "when saved as a draft" do

    should_eventually "have multiple revisions" do
    end

    should_eventually "not be published publicly" do
    end

  end
end

I will be adding this to my shoulda textmate bundle.

Have you ever wanted to refactor something into the model ( skinny controller, fat model ) but didn’t know how to deal with your flash notifications?

Here’s a solution that I cooked up:


module FlashExceptions
  class FlashException < StandardError; end
  class FlashError < FlashException; end
  class FlashNotice < FlashException; end
  class FlashSuccess < FlashException; end
end

###########################################

class Model < ActiveRecord::Base
  include FlashExceptions

  def self.do_something! opts = {}
    raise FlashError, opts[:error] if opts[:error]
    raise FlashNotice, opts[:notice] if opts[:notice]
    raise FlashSuccess, opts[:success] if opts[:success]
  end

end

###########################################

class Controller < ApplicationController

  def action
    Model.do_something! :error => 'oops!', :notice => 'ahem.', :success => 'yay!'
  rescue FlashException => e
    flash[ e.class.underscore.split('_').last ] = e.message
  end

end

openssl RSA signature example

So it seems that the openssl library is totally undocumented?? Here is an example we cooked up to demonstrate how to verify an RSA signature.



>> require 'openssl'
=> false
>> private_key = OpenSSL::PKey::RSA.new(1024)
=> -----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDO+Hl83kJL5qXiEpAMR1+e1JRxpEKBrMJu7wONEge+LjM7svuS
oSWf7+eOpI+Fr6IbNOLsX8x/ZsdWwGjqSIjWsdCvPOjodIi5SAD9UNpt6cUeFsN8
PQYnmy98jdoG9BwFpmMxDWKTVzft3qvKTCMF/b0E/3ELOU78blZp/cg70QIDAQAB
AoGAKqf1SfH40fHYcG6I967iGzcO3RkQh+9WJ0zle3ai1+RntL8fsEm8Gml0XOa3
mcLn8xmER1k7KWrCXLPNK7QFV3M/lbyIbYxXzMBAYuafSKmx6c2vUaGrFYO18oKA
N1dd/+gyuYSi8705Y3z07PoR1Ok7bsFWQM8cjYUwahazTFECQQD09iOdGQPp2OEc
ZLDvo++lvC03fxSGr338rWrVl40engQVB4HAOz3NsFfmDJPfISKL+pnWNyCmagcf
Ys8kppmFAkEA2EwTMZ2NOp9L6oq0+1/JZXnuF/kA6SNo6sRJjBXJk+OSHp9ylm+/
N3DxOVbLPvRzd9FkTetaUIhXW50PQZMk3QJAdldXGzUTk+ynzBzE8fDD/NBtE8t7
8hlkBycMXsXJckoqdLJct66nC/CudkALTBdo5jEaEsgtKNg+OqZ0piMqNQJASBtU
ar3zTw+75zzGiOat5T54uVUxkIdVeq5lNmYtBThghgTx1mT6gikMwejFaP9lXxRX
NAK54Q8S0F/TrjC3oQJBAK4qC/NZ7N/EAkants498sPy/8zZZH7OvjSgn1ScXaZo
PRv/E7Y/dE+DQWufPY9QnQZOl0c4MsFVWYzNduduXCQ=
-----END RSA PRIVATE KEY-----

>> public_key = private_key.public_key
=> -----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAM74eXzeQkvmpeISkAxHX57UlHGkQoGswm7vA40SB74uMzuy+5KhJZ/v
546kj4Wvohs04uxfzH9mx1bAaOpIiNax0K886Oh0iLlIAP1Q2m3pxR4Ww3w9Bieb
L3yN2gb0HAWmYzENYpNXN+3eq8pMIwX9vQT/cQs5TvxuVmn9yDvRAgMBAAE=
-----END RSA PUBLIC KEY-----

>> XML = "abcdefg" 
=> "abcdefg" 
>> sig = private_key.sign( OpenSSL::Digest::SHA1.new, XML )
=> "Q=W\3637\275\2340\250\306k>\320\335\275\252\242\3374\364d\021U\315\273\373\322\351\347\211'\344\b\270\a\207(\216\035\b\021\200|&,Sn|\323}4\327@\343a\263Yj\227\311-&\210\245K\350*\316B'\275-\352\377\366\001]q\346F\240\211\246E\313\340\025p3\331\235w\247\351E\026N~\272\371\025&\2208\270c\252>_\246\345\272\237\226u\301\273\212J\341\213%\343\255%\b\372\245" 
>> public_key.verify( OpenSSL::Digest::SHA1.new, sig, XML )
=> true

Ruby find and replace in files script

I'm more of a windows guy and am very novice when it comes to unix. I was trying to figure out how to do a find/replace searching in a specified path. I ended up writing it in Ruby. This is what I came up with.


require 'find' 
if ARGV.size <= 3 || ARGV[0] == '-h'
  puts "findreplace.rb Finds and replaces strings in the given directory."
  puts "syntax: findreplace.rb PATH find_string replace_string [ignore_dirs]"
  exit
end

Find.find(ARGV[0]) do |file_name| 
  if File.file? file_name
    file = File.new(file_name)
    lines = file.readlines
    file.close

    changes = false
    lines.each do |line|
      changes = true if line.gsub!(/#{ARGV[1]}/, ARGV[2])
    end

    # Don't write the file if there are no changes
    if changes
      file = File.new(file_name,'w')
      lines.each do |line|
        file.write(line)
      end
      file.close
    end
  end

  Find.prune if ARGV[3] && file_name =~ /#{ARGV[3]}/  
end

installing RMagick gem with fink

NOTE; this article is written for the most current rmagick-1.15.9 There are lots of articles about how to install ImageMagick and the RMagick gem, but none of them really cut to the chase in my opinion. Here is how to do it in no time at all, using fink.

#install imagemagick (and save some time by apt-getting ghostscript binaries)
sudo apt-get install ghostscript
sudo fink install imagemagick imagemagick10-dev

#set up stuff for rmagick compilation
export LIBRARY_PATH='/sw/lib'

# the location of this directory might be different if you didn't install rubygems with fink.
cd /sw/lib/ruby/gems/1.8/gems/rmagick-1.15.9
sudo chmod a+x configure
sudo ./configure --prefix=/sw    #point to fink installation
sudo gem install rmagick

Ruby Luhn check (aka mod 10) formula

I just rolled my own method for checking credit card digits:


def check_digits? num
  odd = true
  num.to_s.gsub(/\D/,'').reverse.split('').map(&:to_i).collect { |d|
    d *= 2 if odd = !odd
    d > 9 ? d - 9 : d
  }.sum % 10 == 0
end

ADDENDUM: Rick Hull’s comments from this blog post helped me remove a dependency on map_with_index

PS: the symbol#to_proc and Enumerable#sum are Rails add-ons…

Converting a hex string to ascii in rails

I am doing some work with encryption keys and was trying to find a method in ruby that would convert a string of hex values into their ascii equivalent. I am storing the keys in my database as a string. Here is a sample key that I am using:

"4bd3eb6bd171595764ec2050a20382e1"

which is represented in a hex array as:

0x4b, 0xd3, 0xeb, 0x6b, 0xd1, 0x71, 0x59, 0x57, 0x64, 0xec, 0x20, 0x50, 0xa2, 0x03, 0x82, 0xe1

I iterate through my array, 2 characters at a time, thanks to the rails enumerable "ingroupsof". I take the string of two hex values and convert it to their ascii equivalent first by converting the text into hex and then asking for the char equivalent in ascii. I stuff this back into a new string and voila!... I've got my ascii string.


  def hex_string_to_ascii str
    new_str = ''
    arr = str.split('')
    arr.in_groups_of(2){|c| new_str << ("#{c[0]}#{c[1]}".hex.chr) }
    new_str
  end

Array#rotate method

So I was looking for this in the ruby standard library and didn’t find it. So I rolled my own :) Enjoy!


class Array

  def rotate n=1 #positive right, negative left
    a = self.dup
    (n % self.size).times{ a = [ a.pop ] + a }
    a
  end

  def rotate! n=1
    replace rotate(n)
  end
end

Addendum: I found another way to do this at ruby quiz

   ...
    num.times{ a << a.shift }
   ...

actionmailer ActionView ActiveRecord ajax alphadecimal audio autotest BDD blocks capistrano ssh ruby controller css dashboard widget delegate dog puppy naming name DRM email obfuscation exceptions factories-and-workers factory pattern filemerge find and replace finder fink fixtures fun gem git google maps helper helpers imagemagick Intertrust javascript logo math meetup model openssl OS X patch Pioneer Electronics plugin polymorphism prototype.js rails rails gotcha railsconf rake rmagick RSA encryption ruby script shoulda subversion SyncTV TDD testing textmate tricks unique hashes unix shell validation view yaml zebra stripes