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
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.
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
...
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.
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 caseclass 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
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
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
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.
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 publiclycontext "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
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
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
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
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…
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
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 }
...
