<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7975027231082637331</id><updated>2012-01-29T11:25:41.010-08:00</updated><category term='Heroku ruby sinatra PATSY'/><category term='viruses'/><category term='ruby mongo mongoid mongomapper mysql'/><category term='metasearch'/><category term='path'/><category term='html5'/><category term='snow leopard'/><category term='html5 textarea spellcheck'/><category term='Apache SSL Certificates'/><category term='ruby  bundler'/><category term='Mac laptop disk error repair'/><category term='lab automation'/><category term='malware'/><category term='ruby rvm gem rails'/><category term='&apos;mac os x&apos;'/><category term='ghostscript'/><category term='jetpack'/><category term='firefox'/><category term='&apos;Mac OS X&apos; PDF Preview &quot;Snow Leopard&quot;'/><category term='Flash'/><category term='git github lightouse'/><category term='passenger'/><category term='popup'/><category term='git'/><category term='gem'/><category term='window'/><category term='nginx'/><category term='rails'/><category term='environment variables'/><category term='date ruby rails'/><category term='Mac'/><category term='biotechnology'/><category term='ruby mongo mongoid mongomapper'/><category term='ruby utf-8 character encodings'/><category term='ruby regex'/><category term='Mongo ruby mongoid authentication'/><category term='Rails3'/><category term='mcafee'/><category term='simple-tooltip'/><category term='javascript date browsers Mac'/><category term='jQuery image rollover'/><category term='unix shell'/><category term='safari'/><category term='Adobe'/><category term='mod_fastcgi'/><category term='searchlogic'/><category term='MySQL import export'/><category term='mysql'/><category term='httpd'/><category term='sequence'/><category term='AIR'/><category term='rails routes'/><category term='utf-8'/><category term='chef aws ec2 ubuntu ruby'/><category term='browser hijack'/><category term='biotech'/><category term='oracle'/><category term='patent'/><category term='PostgreSQL'/><category term='trackball'/><category term='html5 chrome forms'/><category term='sinatra'/><category term='nokogiri'/><category term='plugins'/><category term='rails devise authentication'/><category term='ActionMailer'/><category term='craic'/><category term='ruby'/><category term='Intel Core 2 Duo'/><category term='meta_search'/><category term='Win XP'/><category term='sqipdb.com'/><category term='javascript'/><category term='seqid'/><category term='Ruby terminal ANSI escape codes'/><category term='ipad'/><category term='AWS ec2 ubuntu'/><category term='rails testing machinist factory_girl'/><category term='paperclip'/><category term='fedora'/><category term='rails has_many through testing simple_form'/><category term='antibody'/><category term='rail update gem'/><category term='console'/><category term='listing'/><category term='raphael'/><category term='ruby-oci8'/><category term='rails heroku homebrew gem taps sqlite3'/><category term='sqip'/><category term='open'/><category term='imagemagick'/><category term='x86_64'/><category term='ruby rvm shell script'/><category term='csv'/><category term='html form'/><category term='database'/><category term='apache'/><category term='linux'/><category term='asus P5B'/><category term='Heroku'/><category term='MacPymol'/><category term='chrome rails login'/><category term='internet explorer'/><category term='ajax'/><category term='ubuntu rvm ruby'/><category term='sorting'/><category term='mac os x'/><category term='migration'/><category term='Ruby Jruby 1.5.3'/><category term='&quot;Mac OS X&quot;'/><category term='ruby logical operators'/><category term='jquery'/><category term='select menu'/><category term='antivirus'/><category term='ruby erb rails'/><category term='unix'/><category term='codemirror'/><category term='captain beefheart'/><category term='Ruby 1.9 Sinatra Heroku'/><category term='Rails 3'/><category term='microtiter plate map'/><category term='html5 firefox security'/><category term='unzip'/><title type='text'>Craic Computing Tech Tips</title><subtitle type='html'>A collection of computer systems and programming tips that you may find useful.
&lt;br&gt; &lt;br&gt;
Brought to you by &lt;a href="http://www.craic.com"&gt;Craic Computing LLC&lt;/a&gt;, a bioinformatics consulting company.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default?start-index=101&amp;max-results=100'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/13582954721486542844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_f8EIq63pOsk/SdzN4VmaUoI/AAAAAAAAAAM/lS_mySaOTlQ/S220/craic_logo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>184</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-6842009435830771824</id><published>2012-01-27T11:16:00.000-08:00</published><updated>2012-01-27T11:16:20.080-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unix'/><title type='text'>Getting absolute paths with the Unix ls command</title><content type='html'>The standard Unix command &lt;span style="color: red;"&gt;ls &lt;/span&gt;lists filenames and directories in the specified directory. The default behaviour is to list just the filenames as including the full pathname would clutter the screen.&lt;br /&gt;&lt;br /&gt;But sometimes you want the absolute paths. I need this all the time if I want to create a file containing a list fo filenames. The obvious command to get all the YAML files, for example, is:&lt;br /&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;$ &lt;span style="color: red;"&gt;ls -1 *yml&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;A.yml&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;B.yml&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In order to get the full pathnames you need to use this:&lt;br /&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;$&amp;nbsp;&lt;span style="color: red;"&gt;ls -1 -d $PWD/*yml&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;/home/jones/A.yml&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;/home/jones/B.yml&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-6842009435830771824?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/6842009435830771824/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=6842009435830771824' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/6842009435830771824'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/6842009435830771824'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2012/01/getting-absolute-paths-with-unix-ls.html' title='Getting absolute paths with the Unix ls command'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/07503053614730814672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-8278495777355887758</id><published>2012-01-25T12:23:00.000-08:00</published><updated>2012-01-25T12:23:51.115-08:00</updated><title type='text'>Wolfram CDF Player and Chrome Browser</title><content type='html'>&lt;a href="http://www.wolfram.com/cdf/"&gt;Wolfram Computable Document Format&lt;/a&gt; (CDF) is a way to embed interactive documents into web pages, in particular those that perform calculations in response to a user changing the parameters. For example you can create graphs of functions that will change as the function is modified. It is an extension of the Wolfram Mathematica software.&lt;br /&gt;&lt;br /&gt;It looks really promising for some applications and you should check out their demonstrations - some impressive, some not so much.&lt;br /&gt;&lt;br /&gt;You 'play' CDF files using a browser plugin - just like Flash - and these are available for all the current browsers.&lt;br /&gt;&lt;br /&gt;I'm running it on Google Chrome on Mac OS X on a fairly recent laptop. It performs OK depending on the specific application and the amount of data it is asked to push around. But when you close that window or move to another page the CDF player process continues to run. In my case that was taking 5% of my cpu and 66MB of memory and it continued to do so for perhaps 10 minutes after the page was closed.&lt;br /&gt;&lt;br /&gt;This sort of plugin drain on your cpu is fairly common - just look at everything going on in Activity Monitor when you are browsing an 'active' web page with ads, etc.&lt;br /&gt;&lt;br /&gt;In Chrome you can go to Window -&amp;gt; Task Manager, select a process and End it - but that didn't appear to do anything in my case.&lt;br /&gt;&lt;br /&gt;CDF looks very interesting but if it requires too many resources, and then fails to release them properly, then it is not likely to be broadly adopted. It is something to keep an eye on, for sure.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-8278495777355887758?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/8278495777355887758/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=8278495777355887758' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/8278495777355887758'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/8278495777355887758'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2012/01/wolfram-cdf-player-and-chrome-browser.html' title='Wolfram CDF Player and Chrome Browser'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/07503053614730814672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-5619268430551658278</id><published>2012-01-04T08:59:00.000-08:00</published><updated>2012-01-04T08:59:09.092-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mac os x'/><title type='text'>Disabling Spotlight (mds) on Mac OS X (Snow Leopard)</title><content type='html'>I run a lot of command line scripts on my laptop - some of which can run for hours. I want to continue using the machine for reading mail, etc., but I don't want any other intensive task sucking up the cpu cycles. So I shut down iTunes, don't watch any videos, etc.&lt;br /&gt;&lt;br /&gt;But sometimes I see some other process taking all my cycles. The odds are that it is either something to do with Flash or it is a process called &lt;span style="color: red;"&gt;mds&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: red;"&gt;mds&lt;/span&gt; is the indexing software that powers &lt;span style="color: red;"&gt;Spotlight&lt;/span&gt; - the built in Mac search facility.&lt;br /&gt;&lt;br /&gt;I suspect that when I'm generating gigabytes of data and hundreds of files in one of my compute jobs, mds is responding by trying to index them at the same time.&lt;br /&gt;&lt;br /&gt;I don't use spotlight at all, so let's turn it off and see if that helps.&lt;br /&gt;&lt;br /&gt;This turns it off:&lt;br /&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;$ sudo mdutil -a -i &lt;span style="color: red;"&gt;off&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This turns it back on:&lt;br /&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;$ sudo mdutil -a -i &lt;span style="color: red;"&gt;on&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Turning it back on will presumably trigger a big mds run as it plays catch up, so run this command only when you can afford the cycles.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-5619268430551658278?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/5619268430551658278/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=5619268430551658278' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5619268430551658278'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5619268430551658278'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2012/01/disabling-spotlight-mds-on-mac-os-x.html' title='Disabling Spotlight (mds) on Mac OS X (Snow Leopard)'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/07503053614730814672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-8922834395167239709</id><published>2011-11-17T08:48:00.001-08:00</published><updated>2011-11-17T09:01:31.809-08:00</updated><title type='text'>strsplit in R</title><content type='html'>The strsplit function in the R statistics package splits a string into a list of substrings based on the separator, just like split in Perl or Ruby. The object returned is a List, one of the core R object types. For example:&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt; a &amp;lt;- strsplit("x y z", ' ')&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt; a&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;[[1]]&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;[1] "x" "y" "z"&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt; class(a)&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;[1] "list"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you are not that familiar with R, like me, the obvious way to access an element in the list will not work:&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt; a[1]&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;[[1]]&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;[1] "x" "y" "z"&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt; a[2]&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;[[1]]&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;NULL&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So what do you do? There seem to be two options:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1: You can 'dereference' the element (for want of a better word) by using the multiple sets of brackets&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt; a[[1]][1]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;[1] "x"&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt; a[[1]][2]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;[1] "y"&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;... but I'm not going to write code that looks like that !!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;2: You can &lt;span class="Apple-style-span" style="color: red;"&gt;unlist&lt;/span&gt; the List to create a Vector and then access elements directly&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt; b &amp;lt; unlist(a)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;[1] FALSE FALSE FALSE&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt; b &amp;lt;- unlist(a)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt; b&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;[1] "x" "y" "z"&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt; class(b)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;[1] "character"&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt; b[1]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;[1] "x"&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt; b[2]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;[1] "y"&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;Much nicer !&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-8922834395167239709?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/8922834395167239709/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=8922834395167239709' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/8922834395167239709'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/8922834395167239709'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/11/strsplit-in-r.html' title='strsplit in R'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/07503053614730814672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-8429891372184878604</id><published>2011-11-16T13:26:00.001-08:00</published><updated>2011-11-16T14:27:31.666-08:00</updated><title type='text'>Running R scripts on the Command Line</title><content type='html'>&lt;br /&gt;Using the R statistics package via a GUI is great for one off tasks or for learning the language, but for repeated tasks I want the ability to create and run scripts from the UNIX command line.&lt;br /&gt;&lt;br /&gt;There are several ways to do this:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: red;"&gt;R CMD BATCH&lt;/span&gt; executes R code in a script file with output being sent to a file.&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;$ R CMD BATCH myscript.R myoutputfile&lt;/span&gt;&lt;br /&gt;If no output file is given then the output goes to myscript.Rout. There is no way that I know of to have it go to STDOUT.&amp;nbsp;Passing parameters to your script with this approach is a pain. Here is an example script:&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;args &amp;lt;- commandArgs(TRUE)&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;for (i in 1:length(args)){&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;print(args[i])&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is invoked with this command:&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;$ R CMD BATCH &amp;nbsp;--no-save --no-restore --slave --no-timing "--args foo=1 &amp;nbsp;bar='/my/path/filename'" myscript.R tmp&lt;/span&gt;&lt;br /&gt;In particular, note the strange quoting of the arguments, preceded by --args &lt;span class="Apple-style-span" style="color: red;"&gt;inside&lt;/span&gt; the outer quotes -&lt;span class="Apple-style-span" style="color: red;"&gt; it's not a typo!&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: red;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;That command produces this output in file 'tmp':&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;[1] "foo=1"&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;[1] "bar='/my/path/filename'"&lt;/span&gt;&lt;br /&gt;All those '--' options are necessary ! Try leaving out &lt;span class="Apple-style-span" style="color: red;"&gt;--slave&lt;/span&gt; and &lt;span class="Apple-style-span" style="color: red;"&gt;--no-timing&lt;/span&gt; and you'll see why.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Thankfully there is a better option ...&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: red;"&gt;Rscript&lt;/span&gt; is an executable that is part of the standard installation&lt;br /&gt;&lt;br /&gt;You can add a 'shebang' line to the file with your R script, invoking Rscript, make the file executable and run it directly, just like any other Perl, Python or Ruby script.&lt;br /&gt;&lt;br /&gt;You don't need those extra options as they are the default for Rscript, and you pass command line options directly without any of that quoting nonsense.&lt;br /&gt;&lt;br /&gt;Here is an example script:&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;#!/usr/bin/env Rscript&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;args &amp;lt;- commandArgs(TRUE)&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;for (i in 1:length(args)){&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; print(args[i])&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;div&gt;Running this with arguments:&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;$ ./myscript.R foo bar&lt;/span&gt;&lt;/div&gt;&lt;div&gt;produces this output on STDOUT (which you can then redirect as you choose)&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;[1] "foo"&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;[1] "bar"&lt;/span&gt;&lt;br /&gt;&lt;div&gt;Much nicer - but we've still got those numeric prefixes. If you are passing the output to another progran these are a major pain.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The way to avoid those is to use cat() instead of print() - BUT you need to explicitly include the newline character as a separate argument to the cat() function&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;#!/usr/bin/env Rscript&lt;/span&gt;&lt;span class="Apple-tab-span" style="font-family: 'Courier New', Courier, monospace; white-space: pre;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;args &amp;lt;- commandArgs(TRUE)&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;for (i in 1:length(args)){&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; cat(args[i], "\n")&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;results in this output:&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;$ ./myscript.R foo bar&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;foo&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;bar&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;For the sake of completeness, you can run R scripts with a shebang line that invokes R directly. But Rscript seems to be the best solution.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;If you want to pass command line arguments as attribute pairs then you need to parse them out within your script. I haven't got this working in a general sense yet. What I want is to pass arguments like this:&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;$ ./myscript.R infile="foo" outfile='bar'&lt;/span&gt;&lt;br /&gt;But I'm not quite there yet...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-8429891372184878604?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/8429891372184878604/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=8429891372184878604' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/8429891372184878604'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/8429891372184878604'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/11/running-r-scripts-on-command-line.html' title='Running R scripts on the Command Line'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/07503053614730814672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-7244661262598015531</id><published>2011-11-16T12:35:00.001-08:00</published><updated>2011-11-16T12:42:52.859-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unix'/><title type='text'>Deleting a File that starts with '-' on UNIX</title><content type='html'>Filenames that begin with 'special' characters like '-', '.' or '*' cause problems on Unix. Standard commands like &lt;span class="Apple-style-span" style="color: red;"&gt;ls&lt;/span&gt; or &lt;span class="Apple-style-span" style="color: red;"&gt;rm&lt;/span&gt; view the characters as signifying command options.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You don't typically create files with names like this but they can arise through errors such as cut and pasting text into your command line.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Simply escaping the character or quoting the filename does not work.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The solution is to use a longer path to the file - the easiest being a relative path to the same directory.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If the filename is '&lt;span class="Apple-style-span" style="color: red;"&gt;--myfile&lt;/span&gt;' you will get an error like this:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;$ ls --myfile&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;ls: illegal option -- -&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;usage: ls [-ABCFGHLOPRSTUWabcdefghiklmnopqrstuwx1] [file ...]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But this works just fine:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;$ ls ./--myfile&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;./--myfile&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-7244661262598015531?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/7244661262598015531/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=7244661262598015531' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/7244661262598015531'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/7244661262598015531'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/11/deleting-file-that-starts-with-on-unix.html' title='Deleting a File that starts with &apos;-&apos; on UNIX'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/07503053614730814672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-3425339911839709259</id><published>2011-11-16T10:53:00.001-08:00</published><updated>2011-11-16T14:44:27.739-08:00</updated><title type='text'>Plotting a simple bar plot in R</title><content type='html'>Here is my cheat sheet for loading data from a CSV file into the &lt;a href="http://www.r-project.org/"&gt;R statistics package&lt;/a&gt;, plotting one column of data as a bar plot and saving it as a PNG image.&lt;br /&gt;&lt;br /&gt;My input file is simple CSV file with two columns :&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Position,Entropy&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;1,0.2237&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;2,0.4051&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;3,0.1312&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;4,0.1312&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;[...]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I want to load this into R as a data frame, then plot the values in the second column (Entropy) as a bar plot, using the values in the first column as the labels for the bars.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First step is to use read.csv (a shortcut version of read.table)&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt; d &amp;lt;- read.csv('&amp;lt;your path&amp;gt;/myfile.csv')&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I can use barplot directly on the data frame (d)&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt; barplot(d[,'Entropy'])&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;But the default plot options are not great, so I can add custom options to the call, such as a main title and labels for X and Y axes. I set the lower and upper limits for the Y axis to be 0.0 and 1.0 and use the values in the first column of the data frame as the labels for the bars on the X axis&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt; barplot(d[,'Entropy'], main="Entropy Plot", xlab="Position",&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; ylab="Entropy", ylim=c(0.0,1.0), names.arg=d[,'Position'])&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The plot is displayed on my screen and looks the way I want it. To save it out to an image file, I specify the plotting device ('png') and the output filename, repeat the plot and then close/detach the plotting device.&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt; png('&amp;lt;your path&amp;gt;/myfile.png')&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt; barplot(d[,'Entropy'], main="Entropy Plot", xlab="Position",&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; ylab="Entropy", ylim=c(0.0,1.0), names.arg=d[,'Position'])&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt; dev.off()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This produces the following image:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-Z8hz65Q5QUE/TsQKY9K78FI/AAAAAAAAAAQ/8EdJ7DAk0tA/s1600/r_test.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://2.bp.blogspot.com/-Z8hz65Q5QUE/TsQKY9K78FI/AAAAAAAAAAQ/8EdJ7DAk0tA/s320/r_test.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;There are endless configuration options to play with but this works for a quick, simple plot.&lt;br /&gt;&lt;br /&gt;Here are the steps without the prompts for you to cut and paste as needed:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;d &amp;lt;- read.csv('&amp;lt;your path&amp;gt;/myfile.csv')&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;png('&amp;lt;your path&amp;gt;/myfile.png')&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;barplot(d[,'Entropy'], main="Entropy Plot", xlab="Position",&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;ylab="Entropy", ylim=c(0.0,1.0), names.arg=d[,'Position'])&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;dev.off()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You could put these into a text file and run it from your system command line like this:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;$ R CMD BATCH myfile.R&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;R is an incredibly useful system but as an occasional user I find the syntax and command names/options &amp;nbsp;hard to learn. Hopefully this simple example helps you with the learning curve.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: red; font-family: Arial, Helvetica, sans-serif;"&gt;... and always remember - arrays in R start at 1, not 0 ...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-3425339911839709259?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/3425339911839709259/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=3425339911839709259' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3425339911839709259'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3425339911839709259'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/11/plotting-simple-bar-plot-in-r.html' title='Plotting a simple bar plot in R'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/07503053614730814672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-Z8hz65Q5QUE/TsQKY9K78FI/AAAAAAAAAAQ/8EdJ7DAk0tA/s72-c/r_test.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-6487143573172447895</id><published>2011-11-14T10:34:00.001-08:00</published><updated>2011-11-14T10:46:24.430-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><category scheme='http://www.blogger.com/atom/ns#' term='captain beefheart'/><category scheme='http://www.blogger.com/atom/ns#' term='sinatra'/><title type='text'>Captain Beefheart Song Titles</title><content type='html'>Here is a silly project that I knocked out last week - a generator of &lt;a href="http://beefheart.craic.com/"&gt;Fake Captain Beefheart Song Titles&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It was inspired by a comment on &lt;a href="http://www.bbc.co.uk/programmes/b0072l9v"&gt;Gideon Coe&lt;/a&gt;'s radio show on &lt;a href="http://www.bbc.co.uk/6music/"&gt;BBC 6 Music&lt;/a&gt; where he wondered if such a thing existed - it didn't - so I wrote one!&lt;br /&gt;&lt;br /&gt;The 'algorithm', if you can call it that, combines words from real Beefheart song titles and a list of others that sound (to me) like they could be. The structure of the real titles is relatively simple with most of them following a few simple patterns. Some of the generated titles don't work but every so often it'll spit out a good one.&lt;br /&gt;&lt;br /&gt;The site is built with Ruby and Sinatra, with some jQuery thrown in for the scrolling effect. It serves as a nice example if you are learning Sinatra. You can find the code at &lt;a href="https://github.com/craic/fake_song_titles"&gt;Github&lt;/a&gt;&amp;nbsp;and the application is hosted on &lt;a href="http://heroku.com/"&gt;Heroku&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;It's just a bit of fun, but writing a small, self-contained application like this is a great way to learn new technologies. Giving yourself a short time frame in which to develop and deploy a complete application is a great exercise in efficiency.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-6487143573172447895?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/6487143573172447895/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=6487143573172447895' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/6487143573172447895'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/6487143573172447895'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/11/captain-beefheart-song-titles.html' title='Captain Beefheart Song Titles'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/07503053614730814672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-4019911659025640479</id><published>2011-11-11T13:55:00.001-08:00</published><updated>2011-11-11T14:03:36.655-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='internet explorer'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><title type='text'>When jQuery $.ajax() keeps returning the same value on Internet Explorer</title><content type='html'>&lt;br /&gt;I just mentioned this in my last post, but it is important enough that I'm going to give it its own post!&lt;br /&gt;&lt;br /&gt;If you have jQuery Ajax calls, such as $.&lt;span class="Apple-style-span" style="color: red;"&gt;ajax&lt;/span&gt;() , $.&lt;span class="Apple-style-span" style="color: red;"&gt;get&lt;/span&gt;(), etc., that are continually fetching data from a remote server, you may find this works on Firefox, Chrome, etc. but in Internet Explorer it keeps returning the same value.&lt;br /&gt;&lt;br /&gt;IE has cached the first return value and thinks that you are making identical requests so it just uses the cached value and never contacts the server.&lt;br /&gt;&lt;br /&gt;Turn off caching by adding a&amp;nbsp;call to&amp;nbsp;&lt;span class="Apple-style-span" style="color: red;"&gt;ajaxSetup&lt;/span&gt;&amp;nbsp; at the start of your script block&amp;nbsp;and set cache to&amp;nbsp;&lt;span class="Apple-style-span" style="color: red;"&gt;false&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; $.&lt;span class="Apple-style-span" style="color: red;"&gt;ajaxSetup&lt;/span&gt;&amp;nbsp;({ &amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;cache: false &amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; });&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;[...]&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;The fix is simple once you realize it but it took me a while to figure it out this morning.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Debugging JavaScript is painful at the best of times. It's worse when you throw AJAX into the mix. So take small steps and &lt;span class="Apple-style-span" style="color: red;"&gt;test on multiple platforms right from the start&lt;/span&gt;. I need to learn that lesson.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-4019911659025640479?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/4019911659025640479/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=4019911659025640479' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/4019911659025640479'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/4019911659025640479'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/11/when-jquery-ajax-keeps-returning-same.html' title='When jQuery $.ajax() keeps returning the same value on Internet Explorer'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/07503053614730814672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-739050622709663370</id><published>2011-11-11T10:09:00.001-08:00</published><updated>2011-11-11T13:55:03.952-08:00</updated><title type='text'>Updating a DIV with jQuery and Sinatra</title><content type='html'>Here is a minimal example of how to update a DIV in a web page with content from a remote Sinatra server using jQuery AJAX.&lt;br /&gt;&lt;br /&gt;On the Server end you want an action that generates some new content and just returns it as a string. Let's just get the current time:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;get '/update' do&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp;Time.now.to_s &amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In the client web page you need to include the jQuery library:&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You need a named DIV that will receive the content&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;lt;div &lt;span class="Apple-style-span" style="color: red;"&gt;id='update-div'&lt;/span&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Then you need to create your script block. You need a function that updates the DIV. &lt;span class="Apple-style-span" style="color: red;"&gt;update_time()&lt;/span&gt; calls the jQuery &lt;span class="Apple-style-span" style="color: red;"&gt;get&lt;/span&gt; function with two arguments. The first is the URL of the server action. The second is a function that is called on the returned data and the third is a type of data that the server will return, which is 'text' in our case.&lt;br /&gt;&lt;br /&gt;Here we update the named DIV with the string returned from the server.&amp;nbsp;Then we use the &lt;span class="Apple-style-span" style="color: red;"&gt;setTimeout&lt;/span&gt; function to wait 5 seconds, and then we call the function itself to repeat the process. That instance fetches content from the server, waits 5 seconds, calls itself, and so on.&lt;br /&gt;&lt;br /&gt;At the start of the script block we add a call to &lt;span class="Apple-style-span" style="color: red;"&gt;ajaxSetup&lt;/span&gt; and set cache to &lt;span class="Apple-style-span" style="color: red;"&gt;false&lt;/span&gt;. This seems to be necessary for &lt;span class="Apple-style-span" style="color: red;"&gt;Internet Explorer&lt;/span&gt; which would otherwise cache the first value returned and keep using that instead of fetching new values.&lt;br /&gt;&lt;br /&gt;Finally we make the initial call to the function when the document is first loaded and ready.&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; $.&lt;span class="Apple-style-span" style="color: red;"&gt;ajaxSetup&lt;/span&gt; ({ &amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;cache: false &amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; });&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; $(document).ready(function() {&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: red;"&gt;update_time&lt;/span&gt;();&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;});&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; // fetch text from the server, wait 5 secs and repeat&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; function &lt;span class="Apple-style-span" style="color: red;"&gt;update_time&lt;/span&gt;() {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; $.&lt;span class="Apple-style-span" style="color: red;"&gt;get&lt;/span&gt;("/update",&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; function(data) {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $("#update-div").html(data);&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; window.setTimeout(&lt;span class="Apple-style-span" style="color: red;"&gt;update_time&lt;/span&gt;, 5000);&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; },&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 'text');&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://api.jquery.com/jQuery.get/"&gt;jQuery get&lt;/a&gt; function is a simplified wrapper around the ajax call.&lt;br /&gt;&lt;br /&gt;That is all you need to have a DIV continually updated with remote content, in this case coming from Sinatra.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-739050622709663370?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/739050622709663370/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=739050622709663370' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/739050622709663370'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/739050622709663370'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/11/updating-div-with-jquery-and-sinatra.html' title='Updating a DIV with jQuery and Sinatra'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/07503053614730814672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-5089023232768724322</id><published>2011-11-11T09:48:00.001-08:00</published><updated>2011-11-11T10:03:55.342-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><title type='text'>Latest version of jQuery on Google APIs</title><content type='html'>&lt;br /&gt;If a web page uses the &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; library it usually makes sense to link to copy hosted on an external content delivery network (CDN). You don't have to keep an updated copy on your site, the client may already have this copy cached, and the CDN has high bandwidth connections. Google, Microsoft and jQuery themselves offer CDN hosted jQuery.&lt;br /&gt;&lt;br /&gt;I use the Google version and call it with this line:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/&lt;span class="Apple-style-span" style="color: red;"&gt;1.7.0&lt;/span&gt;/jquery.min.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That is fine, but what happens when a new version comes out?&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In these cases some sites will offer a 'latest' url that automatically points to the most recent version.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Google does not do that - but they offer something similar, and which might be slightly better.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If I want version 1.7.0 and nothing else then I use the link given above.&amp;nbsp;&lt;/div&gt;&lt;div&gt;If I want the latest version in the 1.7 series then I use:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/&lt;span class="Apple-style-span" style="color: red;"&gt;1.7&lt;/span&gt;/jquery.min.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And if I want the latest version in the 1 series then I use:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/&lt;span class="Apple-style-span" style="color: red;"&gt;1&lt;/span&gt;/jquery.min.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Note that you don't always want to use the most general form. New releases are not necessarily back compatible. But you have the choice.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;And note that you no longer need to include&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;type="text/javascript"&lt;/span&gt; in the script tag anymore - it's the default.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-5089023232768724322?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/5089023232768724322/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=5089023232768724322' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5089023232768724322'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5089023232768724322'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/11/latest-version-of-jquery-on-google-apis.html' title='Latest version of jQuery on Google APIs'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/07503053614730814672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-3261298726655889620</id><published>2011-11-10T13:08:00.001-08:00</published><updated>2011-11-10T13:27:54.942-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='sorting'/><title type='text'>Sorting on multiple String keys in Ruby</title><content type='html'>Ruby gives you two ways to sort arrays of 'complex' objects - &lt;span class="Apple-style-span" style="color: red;"&gt;sort&lt;/span&gt; and &lt;span class="Apple-style-span" style="color: red;"&gt;sort_by&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Consider this array of hashes&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;array = [{:key0 =&amp;gt; 'foo', :key1 =&amp;gt; 'bar'},{:key0 =&amp;gt; 'hot', :key1 =&amp;gt; 'cold'}, ... ]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: red;"&gt;sort_by&lt;/span&gt; is the most compact form. To sort on :key0 in ascending order you write:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;array.sort_by{ |a| a[:key0] }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: red;"&gt;sort&lt;/span&gt; is a little more verbose, but offers more flexibility:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;array.sort{ |a, b| a[:key0] &amp;lt;=&amp;gt; b[:key0] }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you want to sort strings in &lt;span class="Apple-style-span" style="color: red;"&gt;descending&lt;/span&gt; order then you switch the a and b assignments:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;array.sort{ |a, b| b[:key0] &amp;lt;=&amp;gt; a[:key0] }&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;You can use &lt;span class="Apple-style-span" style="color: red;"&gt;sort_by&lt;/span&gt; with multiple keys if you include them in an array:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;array.sort_by{ |a| [ a[:key0], a[:key1] }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;But if you are using strings and you want one of the keys sorted in &lt;span class="Apple-style-span" style="color: red;"&gt;descending&lt;/span&gt; order then you need to use sort.&lt;br /&gt;&lt;br /&gt;In this example the desired ordering is to first sort on :key0 in &lt;span class="Apple-style-span" style="color: red;"&gt;descending&lt;/span&gt; order and then on :key1 in &lt;span class="Apple-style-span" style="color: red;"&gt;ascending&lt;/span&gt; order:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;array.sort do |a,b|&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; (b[:key0] &amp;lt;=&amp;gt; a[:key0]).nonzero? ||&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; (a[:key1] &amp;lt;=&amp;gt; b[:key1])&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Not the most elegant or concise piece of code, but it does the job.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-3261298726655889620?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/3261298726655889620/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=3261298726655889620' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3261298726655889620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3261298726655889620'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/11/sorting-on-multiple-string-keys-in-ruby.html' title='Sorting on multiple String keys in Ruby'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/07503053614730814672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-7491010088041928644</id><published>2011-11-09T15:43:00.000-08:00</published><updated>2011-11-09T15:43:47.329-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Rails 3'/><title type='text'>Manipulating Model/Table/Controller Names in Rails</title><content type='html'>There are some very useful methods that operate on the names of your models, tables and controllers in Rails. I use them infrequently enough that I have to relearn them every time - so I'm putting them in here:&lt;br /&gt;&lt;br /&gt;Given a string with the name of a model (e.g. Project), how can I create an ActiveRecord call on the fly using that model?&lt;br /&gt;&lt;br /&gt;str = 'Project'&lt;br /&gt;project = (str.&lt;span class="Apple-style-span" style="color: red;"&gt;constantize&lt;/span&gt;).find(1)&lt;br /&gt;&lt;br /&gt;How can I get the name of the corresponding controller ?&lt;br /&gt;&lt;br /&gt;controller = str.&lt;span class="Apple-style-span" style="color: red;"&gt;tableize&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Given a string with the name of a controller, how can I get the name of the Class/Model ?&lt;br /&gt;&lt;br /&gt;str = 'sales_contact'&lt;br /&gt;model_name = str.&lt;span class="Apple-style-span" style="color: red;"&gt;camelize&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I the string is plural:&lt;br /&gt;&lt;br /&gt;str = 'sales_contacts'&lt;br /&gt;model_name = str.&lt;span class="Apple-style-span" style="color: red;"&gt;classify&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;How do I do the reverse operation?&lt;br /&gt;&lt;br /&gt;str = 'SalesContact'&lt;br /&gt;name = str.&lt;span class="Apple-style-span" style="color: red;"&gt;underscore&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-7491010088041928644?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/7491010088041928644/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=7491010088041928644' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/7491010088041928644'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/7491010088041928644'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/11/manipulating-modeltablecontroller-names.html' title='Manipulating Model/Table/Controller Names in Rails'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/07503053614730814672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-783960355067348032</id><published>2011-11-09T13:16:00.000-08:00</published><updated>2011-11-09T13:29:27.803-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='microtiter plate map'/><category scheme='http://www.blogger.com/atom/ns#' term='lab automation'/><title type='text'>Parsing 96 / 384 well Plate Maps</title><content type='html'>&lt;div&gt;In molecular biology and related fields, we use rectangular plastic plates with 96 or 384 wells for many purposes, allowing us to run many experiments in parallel. In particular, they are the standard format for tasks involving laboratory robotics, such as fluid dispensing, DNA sequencing, mass spectrometry, etc.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In setting up a plate of samples, it is common for a researcher to use Excel to create a 'plate map' - a table of 8 rows and 12 columns, for a 96 well plate, with each cell holding information on the sample in that well.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Converting this into a list of individual wells for input into an instrument or a piece of software should be straightforward but variability in manually created plate maps can be an issue. Extraneous text and the placement of the table in the spreadsheet are just two of them.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I have to deal with this problem every year or two and so I decided to write a utility script that implements this conversion and offers several options for the output file. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It is not intended as a complete solution for any one application. Rather it is a starting point that I can customize as needed.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I know other people have to deal with the same type of data, so I've made the script as general as possible and put it up on &lt;a href="http://github.com"&gt;github&lt;/a&gt; under the MIT license. Please adapt this as you see fit for your needs.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The script can take CSV or Tab delimited files as input, containing 96 or 384 well plate maps. The output is a table with one well per row and the columns : plate, row, column, value. Options allow you to specify CSV or Tab delimited as the output format, whether to parse the input in row or column major order, and whether or not to output empty cells in the plate map.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The code is written in Ruby and you can find it at &lt;a href="https://github.com/craic/plate_maps"&gt;https://github.com/craic/plate_maps&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Let me know if you find it useful&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-783960355067348032?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/783960355067348032/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=783960355067348032' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/783960355067348032'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/783960355067348032'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/11/parsing-96-384-well-plate-maps.html' title='Parsing 96 / 384 well Plate Maps'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/07503053614730814672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-9117083442999572928</id><published>2011-08-10T08:10:00.001-07:00</published><updated>2011-08-10T08:17:19.372-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unzip'/><category scheme='http://www.blogger.com/atom/ns#' term='unix'/><title type='text'>Unzipping multiple zip files on Unix</title><content type='html'>To unzip multiple .zip files with one command command on a UNIX system the obvious command to try is 'unzip *.zip' - but that doesn't work...&lt;br /&gt;&lt;br /&gt;&lt;code&gt;$ unzip *zip&lt;br /&gt;Archive: ipab20080103_wk01.zip&lt;br /&gt;caution: filename not matched: ipab20080110_wk02.zip&lt;br /&gt;caution: filename not matched: ipab20080117_wk03.zip&lt;br /&gt;[...]&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;UNIX is expanding the wildcard and passing that string to unzip, which thinks that you are asking for specific files from the zip archive given as the first argument.&lt;br /&gt;&lt;br /&gt;You need to escape the wildcard with a backslash so that 'unzip' sees it and expands it correctly.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;$ unzip \*.zip&lt;br /&gt;Archive: ipab20080103_wk01.zip&lt;br /&gt;inflating: ipab20080103.xml&lt;br /&gt;inflating: ipab20080103lst.txt&lt;br /&gt;inflating: ipab20080103rpt.html&lt;br /&gt;&lt;br /&gt;Archive: ipab20080110_wk02.zip&lt;br /&gt;inflating: ipab20080110.xml&lt;br /&gt;inflating: ipab20080110lst.txt&lt;br /&gt;inflating: ipab20080110rpt.html&lt;br /&gt;[...]&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Glad I stumbled on that - saves me a lot of time...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-9117083442999572928?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/9117083442999572928/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=9117083442999572928' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/9117083442999572928'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/9117083442999572928'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/08/unzipping-multiple-zip-files-on-unix.html' title='Unzipping multiple zip files on Unix'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/07503053614730814672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-5857434632426899539</id><published>2011-07-26T20:20:00.000-07:00</published><updated>2011-07-26T20:33:31.508-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='html form'/><category scheme='http://www.blogger.com/atom/ns#' term='safari'/><category scheme='http://www.blogger.com/atom/ns#' term='html5'/><category scheme='http://www.blogger.com/atom/ns#' term='ipad'/><title type='text'>Default Auto Capitalization in HTML Forms with Safari on iPad2</title><content type='html'>Ran into a nasty gotcha testing out one of my web sites on an iPad2 with Safari.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;By default the iPad will capitalize the first letter in a sentence. But with my application the login page requires an email address and these are typically in al lower case. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Safari forces the first letter of the email address into upper case, e.g. Jones@example.com - but this does not match the text in the application's databases (jones@example.com).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My app doesn't force text into lower case on its end (and it shouldn't !), which means that I could not login to my site. And in this case using the SHIFT key on the keyboard does not let you enter the first letter in lower case.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The solution is for the User of the iPad to go to Settings -&amp;gt; General -&amp;gt; Keyboard and set Auto-Capitalization to Off.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is a really bad default setting - yes, it can be useful if you are entering regular text - but it's not that useful...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I can't expect my users to deal with this on their end. I could force all email address into lower case in my application and that is probably what I'll end up doing.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;HTML5 forms can define that a text entry box represents an email address. This adds convenience when entering from a mobile device (the keyboard can display a '.com' key, for example). Whether or not using this has any effect on auto-capitalization I have yet to test.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-5857434632426899539?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/5857434632426899539/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=5857434632426899539' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5857434632426899539'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5857434632426899539'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/07/default-auto-capitalization-in-html.html' title='Default Auto Capitalization in HTML Forms with Safari on iPad2'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/07503053614730814672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-9064266747297420196</id><published>2011-07-21T10:03:00.000-07:00</published><updated>2011-07-21T10:12:28.681-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='html5 firefox security'/><title type='text'>Firefox Security and file:/// URLs cause problems when testing HTML5</title><content type='html'>I'm experimenting with some of the great features in HTML5 and specifically with Web Storage. The way I typically try out things like this is to write a simple HTML page with the relevant JavaScript and CSS code and then open that in the browser.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;With my Web Storage example, things work great in Chrome and Safari but nothing happens in Firefox 5 on the Mac - even though I know the browser supports this feature.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The issue lies in the security model behind Firefox. It is quite restrictive in what it will let you do with file:/// urls. The intention is to avoid any chance of a remote page being able to access a local file. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That is fine, but there is no obvious alert or notification that Firefox is doing this - instead your code just doesn't work. If I hadn't run it on Chrome first, my reaction would have been to question my own code.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So bear that in mind if you work the same way that I do - perhaps use Chrome as your first choice for development - and if something simple doesn't work, try it in a different browser before questioning your own code.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-9064266747297420196?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/9064266747297420196/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=9064266747297420196' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/9064266747297420196'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/9064266747297420196'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/07/firefox-security-and-file-urls-cause.html' title='Firefox Security and file:/// URLs cause problems when testing HTML5'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/07503053614730814672</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-3999063471040701403</id><published>2011-06-10T11:17:00.000-07:00</published><updated>2011-06-10T11:17:14.001-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='meta_search'/><category scheme='http://www.blogger.com/atom/ns#' term='sorting'/><title type='text'>Rails meta_search - sorting on custom columns</title><content type='html'>I use Ernie Miller's excellent &lt;a href="https://github.com/ernie/meta_search"&gt;meta_search&lt;/a&gt; gem for searching the contents of tables in my Rails 3 Apps.&lt;br /&gt;&lt;br /&gt;I have a lot of index views that are tables of data and each has a search form at the top of the page that uses meta search and the column headers use the sort links provided by meta_search to reorder the rows.&lt;br /&gt;&lt;br /&gt;Typically I also have custom columns, such as the number of objects that are associated with a given row via some relationship. Some of those relationships can be quite complex and in some cases there is no simple way to express them in a way that works with meta_search.&lt;br /&gt;&lt;br /&gt;I handle the sorting in the controller. It's outside the database but with my current application the amount of data makes this perfectly manageable.&lt;br /&gt;&lt;br /&gt;I've come up with a way to let my custom column sorting coexist with meta_search and I reckon it might be useful to others.&lt;br /&gt;&lt;br /&gt;All the code can be found at this gist on Github :&lt;a href="https://gist.github.com/1019358"&gt;https://gist.github.com/1019358&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It works by adding another parameter called 'custom_sort' to the existing search[] parameters. The index action in the controller sees this, performs the custom sort and passes a custom_sort value to the view.&lt;br /&gt;&lt;br /&gt;The view calls the custom_sort_helper with a set of arguments and that creates the column header link with the correct parameters to pass back to the controller.&lt;br /&gt;&lt;br /&gt;So far it works well and allows me to sort on my custom columns with a set of rows selected by meta_search searches.&lt;br /&gt;&lt;br /&gt;I'm sure the code could be more elegant - leave me a column and tell my how.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-3999063471040701403?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/3999063471040701403/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=3999063471040701403' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3999063471040701403'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3999063471040701403'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/06/rails-metasearch-sorting-on-custom.html' title='Rails meta_search - sorting on custom columns'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-8714459113875837476</id><published>2011-06-07T08:58:00.000-07:00</published><updated>2011-06-07T08:58:02.090-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='utf-8'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><title type='text'>Rails send_data and UTF-8</title><content type='html'>I often use &lt;span class="Apple-style-span" style="color: red;"&gt;send_data&lt;/span&gt; to output plain text from a Rails action, typically as a simple way to download, say, a CSV format file.&lt;br /&gt;&lt;br /&gt;I'll have something like this to output the text to the browser:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; send_data(@output, :type =&amp;gt; 'text/plain', :disposition =&amp;gt; 'inline')&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But if the text is UTF-8 and contains non-ASCII characters then you need to specify the character set.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Confusingly, to me, you don't do this with a separate argument at the Rails level. Instead you add it as a modifier on the :type argument like this:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; send_data(@output, :type =&amp;gt; 'text/plain; charset=utf-8', :disposition =&amp;gt; 'inline')&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-8714459113875837476?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/8714459113875837476/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=8714459113875837476' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/8714459113875837476'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/8714459113875837476'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/06/rails-senddata-and-utf-8.html' title='Rails send_data and UTF-8'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-446947190591438074</id><published>2011-06-03T11:04:00.000-07:00</published><updated>2011-06-03T11:04:24.345-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='migration'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='PostgreSQL'/><title type='text'>Rails migration add_column and Postgresql</title><content type='html'>Just ran into a difference between MySQL and Postgresql when running a migration that added a new column to an existing table.&lt;br /&gt;&lt;br /&gt;The intent of the original line was to add a new boolean column called 'active' and set the default value to true:&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; add_column :people, :active, :boolean, :default =&amp;gt; true&lt;br /&gt;&lt;br /&gt;This works fine on MySQL but with Postgresql the default value was not used on existing records. It appears that Postgresql sees that NULL is an acceptable value for the column and uses that as the value.&lt;br /&gt;&lt;br /&gt;The way to fix this is to add a 'null' attribute to the call like this:&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; add_column :people, :active, :boolean, :default =&amp;gt; true, :null =&amp;gt; false&lt;br /&gt;&lt;br /&gt;&lt;div&gt;Now, running rake db:migrate sets all existing records to true&lt;/div&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-446947190591438074?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/446947190591438074/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=446947190591438074' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/446947190591438074'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/446947190591438074'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/06/rails-migration-addcolumn-and.html' title='Rails migration add_column and Postgresql'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-6913515003753762972</id><published>2011-06-03T10:21:00.000-07:00</published><updated>2011-06-03T10:22:13.803-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='html5 chrome forms'/><title type='text'>Google Chrome Browser, Integers and HTML5 forms</title><content type='html'>In HTML5 forms you can specify the type of input that is expected with the 'type' attribute.&lt;br /&gt;&lt;br /&gt;For example,&amp;nbsp;&lt;span class="Apple-style-span" style="color: red;"&gt;type = "number"&lt;/span&gt; specifies that the input tag expects a number. In general this is great as it permits client side validation, but it can have some side effects in some cases.&lt;br /&gt;&lt;br /&gt;The specific case that is causing me problems occurs in the Google Chrome browser when it handles integers entered into an input element with&amp;nbsp;&lt;span class="Apple-style-span" style="color: red;"&gt;type = "number"&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Rather than simple displaying the integer, Chrome inserts commas into the number.&lt;br /&gt;&lt;br /&gt;For example, 123456789 becomes 123,456,789&lt;br /&gt;&lt;br /&gt;The commas are not included when the form is submitted but they are there if I cut and paste the text.&lt;br /&gt;&lt;br /&gt;I don't want these - if I give it an integer all I want to see if the integer. But there is no readily accessible option in Chrome to disable this feature.&lt;br /&gt;&lt;br /&gt;The workaround is to explicitly set the type to text (&lt;span class="Apple-style-span" style="color: red;"&gt;type = "text"&lt;/span&gt;). You lose the client side validation but you avoid the commas.&lt;br /&gt;&lt;br /&gt;Now,&amp;nbsp;I write Rails applications and use the simple_form gem to help create forms. This knows about the types of input each form input is going to accept and so it liberally uses the 'type' attrbutes. Fortunately you can override these as follows:&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;lt;%= f.input :myinteger, :input_html =&amp;gt; { :type =&amp;gt; 'text'} %&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;The real solution, in my opinion, is for the browser to act very conservatively in interpreting user input. If the server wants the user to see commas then it should tell the browser explicitly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-6913515003753762972?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/6913515003753762972/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=6913515003753762972' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/6913515003753762972'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/6913515003753762972'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/06/google-chrome-browser-integers-and.html' title='Google Chrome Browser, Integers and HTML5 forms'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-2995828745597312198</id><published>2011-06-03T10:07:00.000-07:00</published><updated>2011-06-03T10:07:07.861-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='chrome rails login'/><title type='text'>Distinct Logins to a Rails App using Google Chrome Browser</title><content type='html'>If you are developing a Rails app that requires user login, then it can be really helpful to have more than one browser window open at a time, with a separate user logged into each.&lt;br /&gt;&lt;br /&gt;For example, I typically have an Administrator user with special privileges as well as regular users. I want to test my app from both perspectives at the same time.&lt;br /&gt;&lt;br /&gt;But because my app uses cookies to handle session information, I can't simply have two logins from the same browser. Until now I've dealt with this by having one user in Firefox and one in Safari, or Chrome.&lt;br /&gt;&lt;br /&gt;Google Chrome allows you open Incognito Windows that store cookies, history, etc. in a sandbox that is destroyed when you close the window. This allows me to manage two active logins from Chrome.&lt;br /&gt;&lt;br /&gt;Open up your first account in a normal window, then open an Incognito window and login as the second user... Simple!&lt;br /&gt;&lt;br /&gt;Cookies, etc are shared between all Incognito windows and so you only get to have two active users, but even so this is really useful.&lt;br /&gt;&lt;br /&gt;Firefox and other browsers have similar modes - Firefox has 'private browsing' - these may well give you similar functionality.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-2995828745597312198?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/2995828745597312198/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=2995828745597312198' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/2995828745597312198'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/2995828745597312198'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/06/distinct-logins-to-rails-app-using.html' title='Distinct Logins to a Rails App using Google Chrome Browser'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-3907726636304877725</id><published>2011-06-01T13:52:00.000-07:00</published><updated>2011-06-01T14:12:05.090-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='biotechnology'/><category scheme='http://www.blogger.com/atom/ns#' term='antibody'/><category scheme='http://www.blogger.com/atom/ns#' term='database'/><title type='text'>Craic Therapeutic Antibodies Database</title><content type='html'>Craic Computing LLC is pleased to announce the launch of the &lt;a href="http://tabs.craic.com"&gt;Tabs Therapeutic Antibody Database&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Tabs is a unique database focused solely on Therapeutic Abs under development by the Biotechnology industry.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As of 1st June 2011, Tabs contains data on more than 950+ antibodies, targeting 400+ antigens, being developed by 300+ companies.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Antibody records are linked to a wide range of associated data including:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Patents&lt;/li&gt;&lt;li&gt;Papers&lt;/li&gt;&lt;li&gt;Clinical Trials&lt;/li&gt;&lt;li&gt;Antigens&lt;/li&gt;&lt;li&gt;Companies&lt;/li&gt;&lt;li&gt;Conditions/Indications&lt;/li&gt;&lt;li&gt;Regulatory Actions&lt;/li&gt;&lt;li&gt;Protein Sequences&lt;/li&gt;&lt;li&gt;Protein Structures&lt;/li&gt;&lt;li&gt;Press Releases&lt;/li&gt;&lt;li&gt;Development Timelines&lt;/li&gt;&lt;li&gt;Conference Abstracts&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;The database is intended for Biotechnology industry staff - especially those in R&amp;amp;D and in Business Development.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Research staff have direct access to relevant patents and papers for each antibody.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;BizDev staff can see the big picture of developments against a target antigen across companies.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Users can define custom Antibody Sets and download data in to Excel, bioinformatics software and popular Reference management tools. Whenever new data related to Antibody Sets are added to the database, users can be alerted by email.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Tabs is offered as a web based subscription service to biotech companies. The annual subscription offers unlimited access to unlimited users for a given site. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Tabs can be evaluated with a 30 day Free Trial. Sign up for an account &lt;a href="http://tabs.craic.com/"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-3907726636304877725?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/3907726636304877725/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=3907726636304877725' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3907726636304877725'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3907726636304877725'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/06/craic-therapeutic-antibodies-database.html' title='Craic Therapeutic Antibodies Database'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-8528311670239515835</id><published>2011-04-01T13:15:00.001-07:00</published><updated>2011-04-01T13:37:41.159-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Win XP'/><category scheme='http://www.blogger.com/atom/ns#' term='console'/><title type='text'>Tips for poking around a Win XP machine</title><content type='html'>Thankfully I encounter Win XP PCs rarely enough that I forget how to find my way around them. &lt;br /&gt;&lt;br /&gt;Here are few of the tricks that I am using as I try and recover a heavily infected PC for my in-laws.&lt;br /&gt;&lt;br /&gt;1. Reboot the PC while holding down the F8 key will let you select Safe Mode, Safe Mode with Network and other non-standard boot modes.&lt;br /&gt;&lt;br /&gt;2. Windows hides a lot of files from regular users. To reveal everything go to a Folder and then Tools, Folder Options and View.&lt;br /&gt;In the list of options that are shown, you want to Check 'Hidden files and filders' -&amp;gt; 'Show hidden files and folders' and 'Display the contents of system folders' and you want to UnCheck 'Hide protected operating system files'&lt;br /&gt;&lt;br /&gt;3. Start up a Command Shell either by the Start Menu -&amp;gt; Accessories -&amp;gt; Command Prompt, or Start Menu -&amp;gt; Run and enter cmd.exe.&lt;br /&gt;&lt;br /&gt;The cmd shell is a basic DOS (yes, really) shell. Type 'help' for options. 'dir' lists the contents of a directory, 'cd' moves you around. 'del' deletes a file.&lt;br /&gt;&lt;br /&gt;'cd' has a pseudo-auto-complete function. Enter 'cd "' (cd space double quote) and then tab will cycle through the options.&lt;br /&gt;&lt;br /&gt;4. From the command shell:&lt;br /&gt;'ipconfig' shows your IP address etc.&lt;br /&gt;'netstat -am' shows the network services in use.&lt;br /&gt;&lt;br /&gt;5. Ctrl-Alt-Del brings up a window with the running applications and processes, which is useful for spotting rogue processes.&lt;br /&gt;&lt;br /&gt;I really hope that you, and more importantly I, never have to use this knowledge again...&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-8528311670239515835?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/8528311670239515835/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=8528311670239515835' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/8528311670239515835'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/8528311670239515835'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/04/tips-for-poking-around-win-xp-machine.html' title='Tips for poking around a Win XP machine'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-4334856685073479748</id><published>2011-04-01T07:57:00.000-07:00</published><updated>2011-04-01T08:08:41.482-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='antivirus'/><category scheme='http://www.blogger.com/atom/ns#' term='mcafee'/><category scheme='http://www.blogger.com/atom/ns#' term='Win XP'/><title type='text'>Getting rid of McAfee antivirus products on a Win XP PC</title><content type='html'>McAfee antivirus products are widely installed on PCs. I'm sure they work fine but they have a reputation of being intrusive when you let your subscription lapse. The company is not alone in this. With a number of products you will get intrusive popups and warnings if you let your subscription lapse.&lt;br /&gt;&lt;br /&gt;What you should be able to do is go to 'Add/Remove Programs' in your Control Panel and uninstall the software - just like most other professional software allows you to do.&lt;br /&gt;&lt;br /&gt;For some reason, at least in their older products, McAfee has chosen to make this difficult. In order to remove most (not all) traces of McAfee from your system you should get the MPCR.exe program from McAfee and run it.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://download.mcafee.com/products/licensed/cust_support_patches/MCPR.exe"&gt;http://download.mcafee.com/products/licensed/cust_support_patches/MCPR.exe&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Download this onto your PC and run it - it will take a while and it will popup black 'command prompt' windows while it runs, each with cryptic text indicating the individual scripts that are being executed. Just let it do it's thing.&lt;br /&gt;&lt;br /&gt;Restart you machine when it is done.&lt;br /&gt;&lt;br /&gt;When you are trying to fix an infected PC, these remnants of old antivirus software clutter up your PC's registry and other directories.&lt;br /&gt;&lt;br /&gt;Hope this helps&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-4334856685073479748?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/4334856685073479748/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=4334856685073479748' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/4334856685073479748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/4334856685073479748'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/04/getting-rid-of-mcafee-antivirus.html' title='Getting rid of McAfee antivirus products on a Win XP PC'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-3764338022817222963</id><published>2011-04-01T07:42:00.000-07:00</published><updated>2011-04-01T07:55:56.170-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='malware'/><category scheme='http://www.blogger.com/atom/ns#' term='viruses'/><category scheme='http://www.blogger.com/atom/ns#' term='browser hijack'/><category scheme='http://www.blogger.com/atom/ns#' term='Win XP'/><title type='text'>Most efficient way to remove the XP Home Security Malware from a PC</title><content type='html'>My in-laws Win XP PC became infected with malware about a week ago. It was the XP Home Security malware that pops up windows warning you about being infected and appears to scan real files on your PC that it says are infected. In addition the browsers on the machine were hijacked such that you could get to Google OK but when you clicked on any other link you would be redirected to another seemingly random sites. It was a mess...&lt;br /&gt;&lt;br /&gt;Over the past week I've put in at least 11 hours work on the problem and run up 50 miles of driving back and forth to their house. I still don't have a complete fix... I'm going to post a few insights here over the next few days but I wanted to start out with my advice if you have the same problem.&lt;br /&gt;&lt;br /&gt;1: Unplug the PC's network cable&lt;br /&gt;2: Reboot the machine and hold down the F8 key in oder to see the boot options menu&lt;br /&gt;3: Select Safe Mode, or Safe Mode with Networking&lt;br /&gt;4: Pull off your user files onto a USB flash drive or disk drive&lt;br /&gt;5: Turn the machine off&lt;br /&gt;6: Go out and buy a Mac&lt;br /&gt;&lt;br /&gt;I'm not trying to be funny (even though it is April 1st) - this is really the most effective way of dealing with this problem. &lt;br /&gt;&lt;br /&gt;The time and frustration involved in sorting out a mess like this is simply not worth it. &lt;br /&gt;&lt;br /&gt;Cut your losses, go buy a nice new Mac - you'll love it and you won't that these problems&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-3764338022817222963?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/3764338022817222963/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=3764338022817222963' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3764338022817222963'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3764338022817222963'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/04/most-efficient-way-to-remove-xp-home.html' title='Most efficient way to remove the XP Home Security Malware from a PC'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-6452984711547476750</id><published>2011-03-25T15:12:00.000-07:00</published><updated>2011-03-25T15:31:01.323-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ActionMailer'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails 3'/><title type='text'>Rails 3 ActionMailer - defining default host</title><content type='html'>In Rails 3 ActionMailer is really easy to set up and use. Ryan Bates has a great &lt;a href="http://railscasts.com/episodes/206-action-mailer-in-rails-3"&gt;Railscast&lt;/a&gt; on the topic that you should check out.&lt;br /&gt;&lt;br /&gt;But I ran into one issue when creating emails that contain links back to my server.&lt;br /&gt;&lt;br /&gt;Because you are sending an email to a remote machine, you need to include absolute URLs in your links.&lt;br /&gt;&lt;br /&gt;You can define that in a config file but the example given in the Railscast is now deprecated, plus when I first tried it, my app was not picking it up and all my links were still relative.&lt;br /&gt;&lt;br /&gt;You two things for this to work:&lt;br /&gt;&lt;br /&gt;1: In your application.rb or environments/development.rb add a line like this in the configuration block, replacing craic.com with your domain&lt;br /&gt;&lt;pre class="brush: ruby"&gt;    config.action_mailer.default_url_options = { :host =&gt; "craic.com" }&lt;br /&gt;&lt;/pre&gt;The application.rb file applies to all environments. Putting this in development.rb or production.rb lets you use different hosts for each environment.&lt;br /&gt;&lt;br /&gt;2: There are several ways to specify a url to pass into a link_to call in Rails - but only one seems to work.&lt;br /&gt;Specify the urls for your links using &amp;lt;your_model&amp;gt;_url(&amp;lt;your_object&amp;gt;) - &lt;span style="color: rgb(255, 0, 0);"&gt;not&lt;/span&gt; &amp;lt;your_model&amp;gt;_path(&amp;lt;your_object&amp;gt;) and &lt;span style="color: rgb(255, 0, 0);"&gt;not&lt;/span&gt; url_for(...). I tend to use mymodel_path in links in regular web pages so I can't just cut and paste code into a mailer view.&lt;br /&gt;&lt;br /&gt;Here is an example that works:&lt;br /&gt;&lt;pre class="brush: ruby"&gt;&lt;%= link_to object.name, mymodel_url(object) %&gt;&lt;br /&gt;&lt;br /&gt;...produces...&lt;br /&gt;&lt;br /&gt;&amp;lt;a href="http://craic.com/mymodels/1"&amp;gt;My Object&amp;lt;/a&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-6452984711547476750?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/6452984711547476750/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=6452984711547476750' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/6452984711547476750'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/6452984711547476750'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/03/rails-3-actionmailer-defining-default.html' title='Rails 3 ActionMailer - defining default host'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-1916903834961617988</id><published>2011-03-18T16:04:00.000-07:00</published><updated>2011-03-18T16:12:34.927-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='select menu'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><title type='text'>Tandem Select jQuery Plugin</title><content type='html'>&lt;p&gt; A standard HTML multiple Select menu allows the user to select multiple options using Command-Click.  But when the list of options is long, requiring the user to scroll, it becomes cumbersome and prone to errors. &lt;/p&gt;  &lt;p&gt; An effective solution is to use two select menus in tandem, with buttons allowing options to be swapped   between the two.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;I'm pleased to announce the release of a new &lt;a href="http://jquery.com"&gt;jQuery&lt;/a&gt; plugin that makes tandem selects simple to set up and easy to customize.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Tandem Select consists of a JavaScript function that leverages the jQuery library, a CSS file and template HTML code.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;More information and live demos can be found on the &lt;a href="http://craic.github.com/tandem_select_jquery_plugin/"&gt;Project Page&lt;/a&gt; and the software can be downloaded from the &lt;a href="https://github.com/craic/tandem_select_jquery_plugin"&gt;GitHub repository&lt;/a&gt;.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-1916903834961617988?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/1916903834961617988/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=1916903834961617988' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/1916903834961617988'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/1916903834961617988'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/03/tandem-select-jquery-plugin.html' title='Tandem Select jQuery Plugin'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-8428530283002239133</id><published>2011-03-14T17:00:00.001-07:00</published><updated>2011-03-14T17:18:58.894-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='Adobe'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>Adobe AIR Application Installer running flat out on MacBook</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-iPRTONjmo8Q/TX6sPizjs0I/AAAAAAAAAAM/2vFRQtsevNk/s1600/Adobe_air_installer.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 71px;" src="http://2.bp.blogspot.com/-iPRTONjmo8Q/TX6sPizjs0I/AAAAAAAAAAM/2vFRQtsevNk/s320/Adobe_air_installer.png" alt="" id="BLOGGER_PHOTO_ID_5584089971027063618" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;My MacBook (model 5,1 - few years old) running Mac OS X 10.6.5 has had a few incidents recently where it's responsiveness takes a nosedive. That typically means that some process is pegging the cpu at 100%.&lt;br /&gt;&lt;br /&gt;I run into fairly frequent problems with Firefox, especially if a browser window is running Flash - say, for a video feed or an advert. Depending on the level of ambient noise in my office, I can even hear the fan and/or disk in the laptop running at full speed.&lt;br /&gt;&lt;br /&gt;You can use the UNIX 'top' command in a shell to find out who the culprit is, plus other tools like 'lsof', etc. But I find the Apple desktop utility 'Activity Monitor' (in your Applications -&gt; Utilities folder) is more useful. Open it up and select 'All Processes' in the select menu at the top of the window. Then click on the CPU tab down below and then on the cpu column to sort the processes in descending order based on % cpu utilization. Look for something that is up near 100 %.&lt;br /&gt;&lt;br /&gt;If there is nothing striking then look for something with very high Real Mem and Virt Mem and check out the DiskActivity tab as you might have a process that is so memory hungry that it has to page data out to disk.&lt;br /&gt;&lt;br /&gt;The example in the screenshot shown above is a straightforward CPU hog. It is the Adobe AIR Application Installer. I figure this is involved in installing the Adobe AIR runtime libraries that are used by Flash.&lt;br /&gt;&lt;br /&gt;I have no idea why this is running in the first place - and why is it using 100% of my cpu? Flash and associated technologies can be great but they do seem to be around when I have problems...&lt;br /&gt;&lt;br /&gt;If you have the same issue, just select the AIR Installer line in Activity Monitor and click the big red 'Quit Process' button.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-8428530283002239133?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/8428530283002239133/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=8428530283002239133' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/8428530283002239133'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/8428530283002239133'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/03/adobe-air-application-installer-running.html' title='Adobe AIR Application Installer running flat out on MacBook'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-iPRTONjmo8Q/TX6sPizjs0I/AAAAAAAAAAM/2vFRQtsevNk/s72-c/Adobe_air_installer.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-7237570534203796385</id><published>2011-03-14T14:39:00.000-07:00</published><updated>2011-03-14T15:13:25.965-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='date ruby rails'/><title type='text'>Sorting Dates and Times in Ruby</title><content type='html'>Sorting an array of objects on a field that represents a time or date can be a bit tricky. &lt;br /&gt;&lt;br /&gt;Take an example of a Rails ActiveRecord object with a standard 'created_at' column.&lt;br /&gt;&lt;br /&gt;You can sort these with code like this:&lt;br /&gt;&lt;pre class="brush: ruby"&gt;myobjs.sort_by{|a| a.created_at}&lt;/pre&gt;This works but it is really sorting on the String representation of those dates. That may be good enough for some uses but not if you want to sort down to the minute and second and in particular, if you want to sort in correct descending order.&lt;br /&gt;&lt;br /&gt;The best approach is to convert the date or time to the number of seconds since the epoch, which is an integer, and do a numeric sort on that.&lt;br /&gt;&lt;br /&gt;A 'created_at' column has the class 'ActiveSupport::TimeWithZone' and this will output a String under most uses. Convert this to an integer with 'myobj.created_at.to_i' and then sort on that.&lt;br /&gt;&lt;pre class="brush: ruby"&gt;myobjs.sort_by{|a| a.created_at.to_i}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you are working with Ruby Date objects, such as 'Date.today' this will not work. In most uses the Data will be converted to a string like this "Mon, 14 Mar 2011". If you try to convert the Date object directly to an integer with 'to_i' you will get an 'undefined method' error.&lt;br /&gt;&lt;br /&gt;Here you need to explicitly convert to the epoch seconds format using 'strftime' and THEN convert that to an integer.&lt;br /&gt;&lt;pre class="brush: ruby"&gt;&amp;gt; today = Date.today&lt;br /&gt; =&amp;gt; Mon, 14 Mar 2011&lt;br /&gt;&amp;gt; today.strftime("%s").to_i&lt;br /&gt; =&amp;gt; 1300060800&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you only have date strings, such as '2011-03-14', then you will need to convert these to Date objects using 'Date.parse' and then convert those to integers.&lt;br /&gt;&lt;br /&gt;Working with dates and times can get messy but converting to integers is the best way to avoid complications.&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-7237570534203796385?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/7237570534203796385/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=7237570534203796385' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/7237570534203796385'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/7237570534203796385'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/03/sorting-dates-and-times-in-ruby.html' title='Sorting Dates and Times in Ruby'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-9169124250556348458</id><published>2011-03-04T15:14:00.000-08:00</published><updated>2011-03-04T15:28:10.787-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='simple-tooltip'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><category scheme='http://www.blogger.com/atom/ns#' term='gem'/><title type='text'>simple-tooltip Ruby Gem for tooltip help</title><content type='html'>I'm pleased to announce the release of my first Ruby Gem: &lt;a href="https://rubygems.org/gems/simple-tooltip"&gt;simple-tooltip&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Simple Tooltip helps you make tooltip help available in your Rails 3 applications. &lt;br /&gt;&lt;br /&gt;This is often done using a JavaScript plugin which produces a small popup window containing a short text string. That works great in many applications but often the help content that you want to provide is more extensive and you many want to include richer formatting, such as links to other web pages.&lt;br /&gt;&lt;br /&gt;Simple Tooltip acts as a Rails Generator which will create a Tooltip model in your application along with a database table, a controller and views. You create help records using a web interface using plain text, html, Textile or Markdown formatting. The help records are stored in the database and retrieved using the unique, informative titles that you give them.&lt;br /&gt;&lt;br /&gt;In your web pages you include a Tooltip helper that refers to the title of the relevant tooltip. Depending on how you set it up, when you hover over a tooltip icon or click on it, a popup window will appear displaying your help.&lt;br /&gt;&lt;br /&gt;This is much richer and more flexible than the basic solutions available from JavaScript alone.&lt;br /&gt;&lt;br /&gt;More than that, if the audience for your application is not just English-speaking, you can create multiple instances of each tooltip with content in each target language, identified by a two letter locale string. If a user has a non-English locale defined in your application, Simple Tooltip will look for content in the matching locale and display that. For content longer than single sentences, this is a more practical internationalization solution than I18n functionality built into Rails 3, which is more focused on shorter strings.&lt;br /&gt;&lt;br /&gt;The gem is available at &lt;a href="https://rubygems.org/gems/simple-tooltip"&gt;https://rubygems.org/gems/simple-tooltip&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The code is available at &lt;a href="https://github.com/craic/simple_tooltip"&gt;https://github.com/craic/simple_tooltip&lt;/a&gt; and is made freely available under the MIT license.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-9169124250556348458?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/9169124250556348458/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=9169124250556348458' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/9169124250556348458'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/9169124250556348458'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/03/simple-tooltip-ruby-gem-for-tooltip.html' title='simple-tooltip Ruby Gem for tooltip help'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-283251854597925546</id><published>2011-03-01T14:22:00.000-08:00</published><updated>2011-03-01T14:27:43.596-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='environment variables'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='nginx'/><title type='text'>Passing Environment Variables to the nginx web server</title><content type='html'>I need to write this down for future reference...&lt;br /&gt;&lt;br /&gt;With the Apache web server you can pass environment variables to Rails applications, etc by specifying them using SetEnv in your configuration file. But with &lt;a href="http://wiki.nginx.org"&gt;nginx&lt;/a&gt; you don't do this - or at least you don't need to.&lt;br /&gt;&lt;br /&gt;When you fire up the server, simply tell sudo to preserve your environment. Without that, sudo will reset all your variables. With it, they are available to nginx and your applications - nice and simple...&lt;br /&gt;&lt;pre class="brush: shell"&gt;$ sudo -E /usr/local/sbin/nginx&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-283251854597925546?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/283251854597925546/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=283251854597925546' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/283251854597925546'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/283251854597925546'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/03/passing-environment-variables-to-nginx.html' title='Passing Environment Variables to the nginx web server'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-8416130659221761906</id><published>2011-02-24T14:59:00.000-08:00</published><updated>2011-02-24T15:55:45.998-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='utf-8'/><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='Heroku'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><title type='text'>Rails, UTF-8 and Heroku</title><content type='html'>I've had problems with Ruby character encodings over the years, especially when pulling text with non-ASCII characters in from remote sites. I thought I had it mostly sorted but the past few days showed me that was not the case.&lt;br /&gt;&lt;br /&gt;I have a MySQL database on my local machine and a Rails 3 app that pulls in text from remote sources, stores it in the database and does stuff with it. I am deploying the application on &lt;a href="http://heroku.com"&gt;Heroku&lt;/a&gt; prior to public release. Heroku uses PostgreSQL exclusively.&lt;br /&gt;&lt;br /&gt;I was under the belief that all the components in my system were set up to use UTF-8 encoding and therefore moving text with non-ASCII characters around should be fine. But in practice that was not the case - characters like 'α' that looked fine on my local machine showed up as 'Î±' on Heroku, etc. So clearly I was doing something wrong. Rather than go into all the gory details, this is the way to do it right...&lt;br /&gt;&lt;br /&gt;Bottom-line: Make everything use UTF-8 explicitly ... EVERYTHING&lt;br /&gt;&lt;br /&gt;0: Backup your current database!&lt;br /&gt;&lt;br /&gt;1: MySQL&lt;br /&gt;Here are the contents of my /etc/my.cnf file:&lt;br /&gt;&lt;pre class="brush: plain"&gt;[mysqld]&lt;br /&gt;datadir=/usr/local/mysql/data&lt;br /&gt;bind-address = 127.0.0.1&lt;br /&gt;character-set-server = utf8&lt;br /&gt;max_allowed_packet = 32M&lt;br /&gt;[client]&lt;br /&gt;default-character-set = utf8&lt;br /&gt;[mysql]&lt;br /&gt;max_allowed_packet = 32M&lt;/pre&gt;&lt;br /&gt;Even if your tables are held in utf8, you should add these lines. You want the following mysql command to look as shown:&lt;br /&gt;&lt;pre class="brush: sql"&gt;mysql&amp;gt; SHOW VARIABLES LIKE 'character\_set\_%';&lt;br /&gt;+--------------------------+--------+&lt;br /&gt;| Variable_name            | Value  |&lt;br /&gt;+--------------------------+--------+&lt;br /&gt;| character_set_client     | utf8   |&lt;br /&gt;| character_set_connection | utf8   |&lt;br /&gt;| character_set_database   | utf8   |&lt;br /&gt;| character_set_filesystem | binary |&lt;br /&gt;| character_set_results    | utf8   |&lt;br /&gt;| character_set_server     | utf8   |&lt;br /&gt;| character_set_system     | utf8   |&lt;br /&gt;+--------------------------+--------+&lt;/pre&gt;&lt;br /&gt;2: Rails&lt;br /&gt;I'm using Rails 3 - can't tell you how this works in Rails 2.x&lt;br /&gt;a: In config/application.rb make sure this line is uncommented:&lt;br /&gt;&lt;pre class="brush: ruby"&gt;    # Configure the default encoding used in templates for Ruby 1.9.&lt;br /&gt;    config.encoding = "utf-8"&lt;/pre&gt;MySQL and Rails use different variants of utf8/utf-8 - make sure you are using the right one. And note the comment above this line - this sets up utf-8 encoding for templates ONLY.&lt;br /&gt;b: In your database.yml, specify the encoding for the databases - for example:&lt;br /&gt;&lt;pre class="brush: ruby"&gt;development:&lt;br /&gt;  adapter:  mysql2&lt;br /&gt;  host:     localhost&lt;br /&gt;  encoding: utf8&lt;br /&gt;  [...]&lt;/pre&gt;Here you are telling the database adapter that the database uses utf-8. &lt;br /&gt;c: mysql2&lt;br /&gt;Notice that I am using the &lt;a href="https://github.com/brianmario/mysql2"&gt;mysql2&lt;/a&gt; adapter instead of mysql. At this point (Feb 2011) the mysql gem is NOT encoding aware. Replace mysql with mysql2 in your Gemfile and run bundle.&lt;br /&gt;d: In each Model that uses text add this line at the very top of the file:&lt;br /&gt;&lt;pre class="brush: ruby"&gt;# encoding: UTF-8&lt;/pre&gt;This tells Ruby that we're using utf-8 in this model. I don't see a way to set this at the application level so you have to have to add it in all relevant model .rb file. I also don't like defining something with a comment line. I can't see how to define this in, say, an irb interactive session.&lt;br /&gt;&lt;br /&gt;With all those components in place, you should be all set. Try entering non-ASCII characters into a form - such as accented characters or greek/math symbols. These should be displayed correctly in the browser and in the mysql command line client.&lt;br /&gt;&lt;br /&gt;With regards to Heroku, assuming you have your app already set up, you should be able to do a 'heroku db:push' to copy the database into PostgreSQL on Heroku and the characters should display correctly on the remote pages. You will see reference to using 'heroku db:push' with explicit database URLs that include an encoding option, such as '?encoding=utf8'. If your MySQL is set up correctly then this should be unnecessary.&lt;br /&gt;&lt;br /&gt;A critical part of running apps on Heroku is the ability to pull the database back to your local database using 'heroku db:pull'. Before getting all my components set up with utf-8, this step failed for me. With everything using utf-8, and after adding the 'max_allowed_packet' lines to my my.cnf file, this process works fine.&lt;br /&gt;&lt;br /&gt;But because I was working with data in before everything was truly utf-8, I had some instances of text in the database that had been incorrectly encoded - and thereby effectively corrupted. I could see what the 'corrupt' characters looked like and I knew what the correct versions should be. Because everything is now using utf-8 I could simply do a substitution on the text. For example:&lt;br /&gt;&lt;pre class="brush: ruby"&gt;str.sub!(/ÃŸ/, 'β')&lt;/pre&gt;I gathered up the character mappings that I needed (which were not may in my case) and wrote up a class method that I cloned in each model with the issue. I then ran those in the Rails console to correct the bad characters. The method is:&lt;br /&gt;&lt;pre class="brush: ruby"&gt;  def self.make_utf8_clean&lt;br /&gt;    mappings = [  ['Î±', 'α'],&lt;br /&gt;                  ['ÃŸ', 'β'],&lt;br /&gt;                  ['Î²', 'β'],&lt;br /&gt;                  ['â€™', '’'],&lt;br /&gt;                  ['â€œ', '“'],&lt;br /&gt;                  ['â€\u009D;', '”'],&lt;br /&gt;                  ['â€', '”'],            &lt;br /&gt;                  ['Ã¶', 'ö'],&lt;br /&gt;                  ['Â®', '®']&lt;br /&gt;              ]&lt;br /&gt;    # Get the list of String columns&lt;br /&gt;    columns = Array.new&lt;br /&gt;    self.columns.each do |column|&lt;br /&gt;      if column.type.to_s == 'string'&lt;br /&gt;        columns &amp;lt;&amp;lt; column&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;    # Go through each object -&gt; column against all mappings&lt;br /&gt;    self.all.each do |obj|&lt;br /&gt;      columns.each do |column|&lt;br /&gt;        mappings.each do |mapping|&lt;br /&gt;          value = obj.attributes[column.name]&lt;br /&gt;          if value =~ /#{mapping[0]}/&lt;br /&gt;            s = value.gsub(/#{mapping[0]}/, "#{mapping[1]}")&lt;br /&gt;            obj.update_attribute(column.name.to_sym, s)&lt;br /&gt;          end      &lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;  end&lt;/pre&gt;This looks at your model and figures out which columns are of type String. It goes through all records and all character mappings, replacing text and updating the database as needed. Your mappings array could be much larger. There may be a better source of these, but this is a start.&lt;br /&gt;You run this in a rails console like this:&lt;br /&gt;&lt;pre class="brush: ruby"&gt;Loading development environment (Rails 3.0.4)&lt;br /&gt;ruby-1.9.2-p0 &amp;gt; YourModel.make_utf8_clean&lt;/pre&gt;It's a hack but it helped my 'fix' quite a few records that would have been a pain to recreate.&lt;br /&gt;&lt;br /&gt;Character encodings are HARD - Yehuda Katz wrote a &lt;a href="http://yehudakatz.com/2010/05/05/ruby-1-9-encodings-a-primer-and-the-solution-for-rails/"&gt;nice article&lt;/a&gt; on the issues. For most purposes (unless you work with Japanese text) UTF-8 is your best choice for encoding and so I'm using it exclusively. Java and Python both made the same choice and things are probably easier to set up in those worlds. Ruby has it's roots in Japan and so it is not surprising that it could not go down that path. &lt;br /&gt;&lt;br /&gt;From now on, I'm going to make sure everything I touch is configured for UTF-8. There are fews reasons not to at this stage and it allows you to handle most languages.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-8416130659221761906?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/8416130659221761906/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=8416130659221761906' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/8416130659221761906'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/8416130659221761906'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/02/rails-utf-8-and-heroku.html' title='Rails, UTF-8 and Heroku'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-2266229957721437783</id><published>2011-02-23T10:39:00.000-08:00</published><updated>2011-02-23T10:44:44.288-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><title type='text'>Tables named with reserved words in MySQL</title><content type='html'>Trying to fix a string encoding issue in a MySQL database I realized that one of my tables was called the same as a MySQL reserved word - specifically I have a table called 'references'.&lt;br /&gt;&lt;br /&gt;This was created from a Rails app and I have been using this with no problems for a few months, so you can use reserved words, or at least that one.&lt;br /&gt;&lt;br /&gt;Problem is that direct SQL statements in the MySQL client like this don't work:&lt;br /&gt;&lt;pre class="brush: sql"&gt;mysql&amp;gt; describe references;&lt;br /&gt;ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that &lt;br /&gt;corresponds to your MySQL server version for the right syntax to use near 'references' at line 1&lt;/pre&gt;The solution is to prefix the table name with the database name like this:&lt;br /&gt;&lt;pre class="brush: sql"&gt;mysql&amp;gt; describe mydb.references;&lt;br /&gt;+------------------+--------------+------+-----+---------+----------------+&lt;br /&gt;| Field            | Type         | Null | Key | Default | Extra          |&lt;br /&gt;+------------------+--------------+------+-----+---------+----------------+&lt;br /&gt;| id               | int(11)      | NO   | PRI | NULL    | auto_increment |&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-2266229957721437783?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/2266229957721437783/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=2266229957721437783' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/2266229957721437783'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/2266229957721437783'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/02/tables-named-with-reserved-words-in.html' title='Tables named with reserved words in MySQL'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-9027387442368445891</id><published>2011-02-22T08:50:00.000-08:00</published><updated>2011-02-22T09:40:26.882-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='PostgreSQL'/><category scheme='http://www.blogger.com/atom/ns#' term='&quot;Mac OS X&quot;'/><title type='text'>Setting up PostgreSQL on Mac OS X 10.6</title><content type='html'>I needed to set up &lt;a href="http://postgresql.org"&gt;PostgreSQL&lt;/a&gt; on my Mac in order to troubleshoot a problem with a Rails application.&lt;br /&gt;&lt;br /&gt;Here are the steps that I followed:&lt;br /&gt;&lt;br /&gt;1: Using Homebrew, install and build PostgreSQL&lt;br /&gt;Homebrew will give you commands to create a Launch Agent that starts the server on a reboot&lt;br /&gt;&lt;pre class="brush: shell"&gt;$ brew install postgresql&lt;br /&gt;$ cp /usr/local/Cellar/postgresql/9.0.3/org.postgresql.postgres.plist ~/Library/LaunchAgents&lt;br /&gt;$ launchctl load -w ~/Library/LaunchAgents/org.postgresql.postgres.plist&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;2: Setup PostgreSQL&lt;br /&gt;You should look into setting administration user - I skipped that for my purposes&lt;br /&gt;&lt;pre class="brush: shell"&gt;$ initdb /usr/local/var/postgres&lt;br /&gt;The files belonging to this database system will be owned by user "jones".&lt;br /&gt;This user must also own the server process.&lt;br /&gt;[...]&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;3: Create a specific database and verify that it is running&lt;br /&gt;&lt;pre class="brush: shell"&gt;$ createdb mydb&lt;br /&gt;$ psql mydb&lt;br /&gt;mydb-# select version();&lt;br /&gt;mydb-# \h&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;4: Install the PostgreSQL ruby gem&lt;br /&gt;You'll see different names for this gem - just use 'pg'. Using the ARCHFLAGS env variable is important. I did not need to specify the explicit path to the Homebrew installation of the PostgreSQL software.&lt;br /&gt;&lt;pre class="brush: shell"&gt;$ env ARCHFLAGS="-arch x86_64" gem install pg&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-9027387442368445891?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/9027387442368445891/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=9027387442368445891' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/9027387442368445891'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/9027387442368445891'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/02/setting-up-postgresql-on-mac-os-x-106.html' title='Setting up PostgreSQL on Mac OS X 10.6'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-2034876621851975456</id><published>2011-02-21T15:59:00.000-08:00</published><updated>2011-02-21T16:23:11.161-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails heroku homebrew gem taps sqlite3'/><title type='text'>Problem with sqlite when installing the taps ruby gem on Mac OS X</title><content type='html'>Just worked my way through one of those installation problems where trying to install A fails because B is missing and trying to install B fails because... and so on.&lt;br /&gt;&lt;br /&gt;1: Trying to push a database to the Heroku hosting service failed because I did not have the 'taps' gem installed&lt;br /&gt;2: 'gem install taps' failed because it couldn't compile a component that interacts with sqlite databases. I'm not using sqlite but there is no way to skip this part of the code - hmm...&lt;br /&gt;3: Mac OS X has sqlite installed by default (or at least with Xcode installed)&lt;br /&gt;4: Explicitly telling taps where to find the lib and include files didn't fix it&lt;br /&gt;&lt;br /&gt;So the problem lay in my sqlite installation&lt;br /&gt;&lt;br /&gt;Lots of mentions of the issue on Google - some of which said to install a new version with MacPorts&lt;br /&gt;&lt;br /&gt;In the past I have found MacPorts to be a very frustrating experience - just wanting to install a single library has led to literally hours of watching it fetching and installing all sorts of apparent dependencies. So I tend to just get the source code for whatever I want and compile it manually, but that can be a pain in and of itself.&lt;br /&gt;&lt;br /&gt;I've heard very good things about &lt;a href="http://mxcl.github.com/homebrew/"&gt;Homebrew&lt;/a&gt; as a MacPorts replacement so I figured I should take a look. &lt;br /&gt;&lt;br /&gt;1. Set up a 'staff' group so that you can install code without having to sudo everything&lt;br /&gt;2. Get Homebrew&lt;br /&gt;3. Install your library&lt;br /&gt;&lt;pre class="brush: shell"&gt;$ sudo dscl /Local/Default -append /Groups/staff GroupMembership $USER&lt;br /&gt;$ ruby -e "$(curl -fsSL https://gist.github.com/raw/323731/install_homebrew.rb)"&lt;br /&gt;$ brew install sqlite&lt;/pre&gt;Simple... Brilliant... I'm sold...&lt;br /&gt;&lt;br /&gt;Homebrew installs code in /usr/local/Cellar by default so I need to tell the ruby gems where to find that - and somewhere along the line I saw a sqlite ruby gem. So I figured I should install that first as a check that things are working before trying 'taps'.&lt;br /&gt;&lt;pre class="brush: shell"&gt;$ gem install sqlite3 -- --with-sqlite3-include=/usr/local/Cellar/sqlite/3.7.5/include \&lt;br /&gt;                                            --with-sqlite3-lib=/usr/local/Cellar/sqlite/3.7.5/lib&lt;br /&gt;$ gem install taps&lt;/pre&gt;It worked...&lt;br /&gt;You may see mention of a sqlite3-ruby gem. That is now called sqlite3 - it's the same thing.&lt;br /&gt;&lt;br /&gt;And finally I can run '$ heroku db:push' and send my database to my Heroku app.&lt;br /&gt;&lt;br /&gt;Phew...&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-2034876621851975456?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/2034876621851975456/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=2034876621851975456' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/2034876621851975456'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/2034876621851975456'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/02/problem-with-sqlite-when-installing.html' title='Problem with sqlite when installing the taps ruby gem on Mac OS X'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-4052265188093489766</id><published>2011-02-18T14:50:00.000-08:00</published><updated>2011-02-18T15:35:43.925-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails devise authentication'/><title type='text'>Rails, Devise and custom User models</title><content type='html'>&lt;a href="https://github.com/plataformatec/devise"&gt;Devise&lt;/a&gt; is an excellent solution for user authentication in a Rails application.&lt;br /&gt;&lt;br /&gt;Ryan Bates has done two great &lt;a href="http://railscasts.com/"&gt;Railscasts&lt;/a&gt; episodes on Devise - &lt;a href="http://railscasts.com/episodes/209-introducing-devise"&gt;#209 Introducing Devise&lt;/a&gt; and &lt;a href="http://railscasts.com/episodes/210-customizing-devise"&gt;#210 Customizing Devise&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The default Devise configuration uses a simple sign up process - you give it an email address, a password and password confirmation. Follow the installation instructions and it should just all work.&lt;br /&gt;&lt;br /&gt;But in my current application I need a bit more. I want the user to enter their first and last names, I want to assign a role and I want to link that individual user to a company account. Devise is capable of handling all this but the README on github doesn't really explain how and I, for one, get a bit nervous messing with the code of my authentication solution.&lt;br /&gt;&lt;br /&gt;It turns out to be incredibly easy as long as you don't try and be too clever.&lt;br /&gt;&lt;br /&gt;Be going into the steps given below, I recommend trying out a basic off the shelf Devise installation in a test application first just so you know that it works on your machine and you can see what files it creates, etc.&lt;br /&gt;&lt;br /&gt;In these steps I'm going to use Devise with a User model that contains some custom fields.&lt;br /&gt;&lt;br /&gt;1. Before creating your own User model, do a basic Devise installation into your app&lt;br /&gt;&lt;pre class="brush: shell;"&gt;$ gem install devise  # or in Rails 3 add it to your Gemfile, and 'bundle'&lt;br /&gt;$ rails generate devise:install  # follow the instructions given&lt;br /&gt;$ rails generate devise User&lt;br /&gt;$ rails generate devise:views # this generates sign_in, etc views under 'app/views/devise' - not user!&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;2. Modify your User model by adding custom fields to attr_accessible&lt;br /&gt;Here I'm adding :first_name, :last_name, :active, :role&lt;br /&gt;&lt;pre class="brush: ruby;"&gt;attr_accessible :email, :password, :password_confirmation, :remember_me,&lt;br /&gt;        :first_name, :last_name, :active, :role&lt;/pre&gt;&lt;br /&gt;Add your own validations, etc to the model. For testing, at least, require the presence of at least on of your custom fields.&lt;br /&gt;&lt;br /&gt;3. Modify your Migration for the User table and run the migration&lt;br /&gt;In my case I added these lines:&lt;br /&gt; &lt;pre class="brush: ruby;"&gt;     t.string :first_name&lt;br /&gt;      t.string :last_name&lt;br /&gt;      t.boolean :active, :default =&gt; true&lt;br /&gt;      t.string :role, :default =&gt; 'user'&lt;/pre&gt;&lt;br /&gt;Run the migration with 'rake db:migrate'&lt;br /&gt;&lt;br /&gt;4. Modify your Sign_up form&lt;br /&gt;This lives in app/views/devise/registrations/new.html.erb&lt;br /&gt;NOTE: You can have Devise install its views under app/views/user but I prefer to keep Devise specific views in their own directory&lt;br /&gt;Add fields to the form for your custom fields e.g. &lt;br /&gt;&lt;pre class="brush: ruby;"&gt;&amp;lt;%= f.text_field :first_name %&amp;gt;&lt;br /&gt;etc. &lt;/pre&gt;&lt;br /&gt;5. Try it out - sign up a new user&lt;br /&gt;Go to the URL /users/sign_up&lt;br /&gt;Your input to the custom fields should go into the database and any validations against custom fields which fail should give you the proper error messages and highlighting in the sign_up form&lt;br /&gt;In my experience this 'just worked'&lt;br /&gt;&lt;br /&gt;6. But the whole reason you want custom fields in the User model is to work directly with them...&lt;br /&gt;&lt;br /&gt;For this you need a User controller and views. Devise does not give you either of these.&lt;br /&gt;Either run a scaffold generator and skip the model or copy over another controller and set of views.&lt;br /&gt;Now you have the regular set of actions for your model.&lt;br /&gt;Go to /users and you should see the user(s) that you added, /users/1 will show you that user with whatever columns you choose to display.&lt;br /&gt;&lt;br /&gt;In my case I display my custom fields and the email in my show and index actions and just ignore the rest of the Devise specific fields.&lt;br /&gt;&lt;br /&gt;You want to be careful with the User new/create/edit/update actions. If you create a new user via that path then they will have no password, etc so you might want to remove new/create. The edit/update actions are useful if a user want to change their name and other 'profile' information, but don't mess with the Devise-specific fields via this route.&lt;br /&gt;&lt;br /&gt;Basically, the Devise side of things and your custom User model can coexist quite happily. Make sure you don't mess with the fields that Devise requires and don't use the same column names.&lt;br /&gt;&lt;br /&gt;I would also avoid using virtual attributes in the custom fields. I tried this and couldn't get it to work. Not a big deal for my case.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;When I started integrating Devise into my app I had a sinking feeling that the custom fields would be a real problem. Quite the opposite - this turned out to be really easy. &lt;br /&gt;&lt;br /&gt;Great kudos to the folks at &lt;a href="http://plataformatec.com.br/"&gt;Platforma Tec&lt;/a&gt; - Jose Valim and colleagues for a really nice piece of work.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-4052265188093489766?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/4052265188093489766/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=4052265188093489766' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/4052265188093489766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/4052265188093489766'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/02/rails-devise-and-custom-user-models.html' title='Rails, Devise and custom User models'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-3865778063131277286</id><published>2011-02-18T08:17:00.001-08:00</published><updated>2011-02-18T08:27:21.456-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jQuery image rollover'/><title type='text'>Basic image rollover effect in jQuery</title><content type='html'>There are so many fancy image effects that you can write in &lt;a href="http://jquery.org"&gt;jQuery&lt;/a&gt; that it is easy to overlook the basics. Here is basic image rollover script.&lt;br /&gt;&lt;br /&gt;I have two images 'logo.png' and 'logo_highlight.png'. I want to display 'logo' by default and then replace it with 'logo_highlight' when I roll the mouse over it.&lt;br /&gt;&lt;br /&gt;Here is my image tag in the html:&lt;br /&gt;&lt;pre class="brush: plain"&gt;&amp;lt;img id="logo" src="images/logo.png" alt="Logo" /&amp;gt;&lt;/pre&gt;&lt;br /&gt;And here is the script (assuming that you have the jQuery loaded)&lt;br /&gt;&lt;pre class="brush: js"&gt;&lt;br /&gt;&amp;lt;script&amp;gt;&lt;br /&gt;$(document).ready(function() {&lt;br /&gt;    $('#logo').hover(function(e) { &lt;br /&gt;  this.src = this.src.replace('logo', 'logo_highlight');&lt;br /&gt; },&lt;br /&gt;    function(e) { &lt;br /&gt;  this.src = this.src.replace('logo_highlight', 'logo');&lt;br /&gt; });&lt;br /&gt;});&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;br /&gt;The script attaches a 'hover' event handler to the DOM element with ID 'logo'. This has two functions that are applied when the mouse enters and leaves the element respectively.&lt;br /&gt;&lt;br /&gt;On entry, the image 'src' attribute is updated. The new one is derived by replacing the string 'logo' in the filename of the original image with 'logo_highlight' in the new version. In other words, the image tag now sources the 'logo_highlight' image.&lt;br /&gt;&lt;br /&gt;When the mouse leaves the element, the second function is executed and that replaces the highlighted image with the original.&lt;br /&gt;&lt;br /&gt;Short and sweet...&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-3865778063131277286?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/3865778063131277286/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=3865778063131277286' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3865778063131277286'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3865778063131277286'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/02/basic-image-rollover-effect-in-jquery.html' title='Basic image rollover effect in jQuery'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-2102131983694360671</id><published>2011-02-16T09:22:00.000-08:00</published><updated>2011-02-16T10:04:48.289-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mongo ruby mongoid authentication'/><title type='text'>Authentication in Mongo and Mongoid</title><content type='html'>&lt;a href="http://mongodb.org"&gt;Mongo&lt;/a&gt; has primitive authentication - just basic user/password authentication per database.&lt;br /&gt;&lt;br /&gt;It's preferred mode of operation is no authentication in a trusted environment. That's fine, but it's not always possible. I want to run mongo on a Amazon EC2 node and access it from remote clients so I need to use authentication. On top of that, I already have the database running without authentication on a node. &lt;br /&gt;&lt;br /&gt;Here are the steps you need to make the migration to a server with authentication...&lt;br /&gt;&lt;br /&gt;1. Create an admin user on the database&lt;br /&gt;Open up a mongo shell on the machine running the server&lt;br /&gt;&lt;pre class="brush: js;"&gt;$ mongo&lt;br /&gt;&gt; use admin&lt;br /&gt;&gt; db.addUser("your_admin_user", "your_password")&lt;br /&gt;&gt; exit&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;2. Restart your Mongo server with --auth&lt;br /&gt;It is CRITICAL that you restart with the --auth option. Users and passwords are simply ignored without this option. &lt;br /&gt;&lt;pre class="brush: bash;"&gt;$ mongod --auth&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;3. Set up database specific users&lt;br /&gt;&lt;pre class="brush: js;"&gt;$ mongo&lt;br /&gt;&gt; use admin&lt;br /&gt;&gt; db.auth("your_admin_user", "your_password")&lt;br /&gt;&gt; show dbs&lt;br /&gt;&gt; use your_db&lt;br /&gt;&gt; db.addUser("your_db_user", "your_password")&lt;br /&gt;&gt; db.system.users.find()&lt;br /&gt;&gt; exit&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;4. Set up authenticated access from your application&lt;br /&gt;I work in Ruby and use Mongoid as the Object Document Mapper to access Mongo. Mongoid, in turn uses the Ruby Mongo Driver. If you are using Mongoid outside of Rails then you will need a configuration block along the lines of this;&lt;br /&gt;&lt;pre class="brush: ruby;"&gt;&lt;br /&gt;Mongoid.configure do |config|&lt;br /&gt;  name = "your_db"&lt;br /&gt;  config.database = Mongo::Connection.new.db(name)&lt;br /&gt;  config.database.authenticate("your_db_user", "your_password")&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Note that you are authenticating with the Ruby Mongo driver - not with Mongoid.&lt;br /&gt;&lt;br /&gt;If you are working with Rails then you'll need to add username and password into your config/database.yml file. I see that the Devise authentication gem can work with Mongo to handle authentication of individual users but I've not explored that yet.&lt;br /&gt;&lt;br /&gt;5. Clearly there is an issue having your password in plain text in your code&lt;br /&gt;The bottom line is that you probably don't want to trust Mongo authentication for critical data. In that case, you really need to set up Mongo access in a secure environment and perhaps handle interfacing this with the outside work through a separate gateway application, say a Sinatra app that handles all authentication itself.&lt;br /&gt;&lt;br /&gt;For my needs I have non-critical data - I just want to prevent access to arbitrary users (i.e. port scanning scripts) and only access from a few defined scripts on specific machines. So for now this will work for me.&lt;br /&gt;&lt;br /&gt;With mongo authentication in place, how do you handle backing up and restoring the database?&lt;br /&gt;&lt;br /&gt;On the machine hosting the server you can use these two variants of the dump and restore commands:&lt;br /&gt;&lt;pre class="brush: shell;"&gt;$ mongodump -d your_db -o . -u your_db_user -p your_password&lt;br /&gt;[...]&lt;br /&gt;$ mongorestore -u your_db_user -p your_password your_db&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;To work with all databases you would use the admin user&lt;br /&gt;&lt;br /&gt;In order for someone to break into your database someone has to &lt;br /&gt;1: Guess/crack your admin username and password&lt;br /&gt;or&lt;br /&gt;2: Guess/crack your specific database, your db username and password.&lt;br /&gt;&lt;br /&gt;You have to evaluate the chances of this along with the value of the data in the database before going down this path.&lt;br /&gt;You can also configure the database to use a non-standard port. There is no harm in this but it offers minimal to no additional security as many malicious scripts will scan across all ports on a machine looking for one that responds. &lt;br /&gt;&lt;br /&gt;Caveat emptor...&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-2102131983694360671?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/2102131983694360671/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=2102131983694360671' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/2102131983694360671'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/2102131983694360671'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/02/authentication-in-mongo-and-mongoid.html' title='Authentication in Mongo and Mongoid'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-7936013596445836190</id><published>2011-02-15T14:30:00.000-08:00</published><updated>2011-02-15T16:06:29.831-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby mongo mongoid mongomapper mysql'/><title type='text'>Always index columns that you want to sort on in Mongo</title><content type='html'>I'm using &lt;a href="http://mongodb.org"&gt;Mongo&lt;/a&gt; as a non-relational database for a few projects. In general it's working out great. MySQL would work too but I like not having to explicitly create a database or run migrations. Plus I figure you can't really understand the strengths and weaknesses of a technology unless you build a real application with it.&lt;br /&gt;&lt;br /&gt;I work in Ruby and use the MongoMapper and &lt;a href="http://mongoid.org"&gt;Mongoid&lt;/a&gt; Object Data Mappers to talk to Mongo.&lt;br /&gt;&lt;br /&gt;One issue that I do not like is the requirement that you explicitly create an index for every column that you think you will want to sort on. If you don't then all the data gets loaded into memory for the sort and you get an error like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: plain"&gt;[...]/gems/mongo-1.2.1/lib/mongo/cursor.rb:86:in `next_document': &lt;br /&gt;too much data for sort() with no index (Mongo::OperationFailure)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And if you want to sort on two columns then you need an index on the combination of the two.&lt;br /&gt;&lt;br /&gt;You can add indexes at any point - it takes some action but it's not that big a deal. But it doesn't 'just work'... in MySQL it does - an index might give you better performance but it doesn't blow up without one.&lt;br /&gt;&lt;br /&gt;You'll hear people claim that the NoSQL databases are schema-free, giving you a lot of flexibility. I don't really buy that argument - in most applications you want a clear schema.&lt;br /&gt;&lt;br /&gt;Where I do see the benefit is that, with NoSQL databases, your schema resides your Model - not in the DB itself - and that is where it belongs. When you want to change the schema you just change the Model - no database migrations - very flexible. &lt;br /&gt;&lt;br /&gt;But, with Mongo at least, if you have to define indexes ahead of time in order to sort even relatively small numbers of objects then that nullifies some of that benefit.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-7936013596445836190?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/7936013596445836190/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=7936013596445836190' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/7936013596445836190'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/7936013596445836190'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/02/always-index-columns-that-you-want-to.html' title='Always index columns that you want to sort on in Mongo'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-655135994071888163</id><published>2011-02-15T11:32:00.000-08:00</published><updated>2011-02-15T13:54:59.596-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby mongo mongoid mongomapper'/><title type='text'>Using Mongoid in Ruby applications outside of Rails</title><content type='html'>&lt;a href="http://mongoid.org/"&gt;Mongoid&lt;/a&gt; and &lt;a href="https://github.com/jnunemaker/mongomapper"&gt;MongoMapper&lt;/a&gt; are two Ruby ODM (Object Document Mapper) gems for the &lt;a href="http://www.mongodb.org/"&gt;Mongo&lt;/a&gt; database.&lt;br /&gt;&lt;br /&gt;I've used both to a limited extent and they seem comparable for my needs. Mongoid seems to be getting a bit more traction than MongoMapper and it certainly has better docs.&lt;br /&gt;&lt;br /&gt;My current project uses Mongo in a standalone Ruby application - no Rails in sight - but the docs are almost totally focused on Rails. Here is how you use Mongoid outside of Rails.&lt;br /&gt;&lt;br /&gt;I'm storing relevant RSS entries in the database. My model looks something like this (heavily truncated):&lt;br /&gt;&lt;pre class="brush: ruby;"&gt;&lt;br /&gt;class RssEntry&lt;br /&gt;  include Mongoid::Document&lt;br /&gt;&lt;br /&gt;  field :entry_id&lt;br /&gt;  field :title&lt;br /&gt;  field :authors, :type =&gt; Array&lt;br /&gt;  field :timestamp, :type =&gt; Time&lt;br /&gt;&lt;br /&gt;  index :timestamp&lt;br /&gt;  index :title&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Be sure and define your indexes carefully for fields that you want to search on, otherwise Mongo will run out of memory when searching even modest datasets. I see this as a weakness of the database. &lt;span style="color: red;"&gt;See important note on creating indexes below!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;and the application looks a bit like this (edited):&lt;br /&gt;&lt;pre class="brush: ruby;"&gt;&lt;br /&gt;#!/usr/bin/env ruby&lt;br /&gt;require 'mongoid'&lt;br /&gt;$:.unshift File.dirname(__FILE__)&lt;br /&gt;require 'mongoid_test_model'&lt;br /&gt;&lt;br /&gt;Mongoid.configure do |config|&lt;br /&gt;  name = "mongoid_test_db"&lt;br /&gt;  host = "localhost"&lt;br /&gt;  port = 27017&lt;br /&gt;  config.database = Mongo::Connection.new.db(name)&lt;br /&gt;end&lt;br /&gt;[...]&lt;br /&gt;entry = RssEntry.create({&lt;br /&gt;    :title =&gt; title,&lt;br /&gt;    :entry_id =&gt; id,&lt;br /&gt;    :authors =&gt; authors,&lt;br /&gt;    :timestamp = Time.new&lt;br /&gt;})&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And if you are using the defaults of localhost and 27017 then you can leave those definitions out.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: red;"&gt;NOTE:&lt;/span&gt; Simply defining an index in your model is NOT enough. You have to explicitly create the index. When you use Mongoid with Rails it sets up a rake task so you can run 'rake db:create_indexes' but outside of that environment you need to do this yourself.&lt;br /&gt;&lt;br /&gt;You'll want to write a simple script/rake task to set this up, in which you call create_indexes on EACH class in your model that uses Mongoid. For example:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: ruby"&gt;&lt;br /&gt;#!/usr/bin/env ruby&lt;br /&gt;require 'mongoid'&lt;br /&gt;$:.unshift File.dirname(__FILE__)&lt;br /&gt;require 'mongoid_test_model'&lt;br /&gt;&lt;br /&gt;Mongoid.configure do |config|&lt;br /&gt;  name = "mongoid_test"&lt;br /&gt;  host = "localhost"&lt;br /&gt;  port = 27017&lt;br /&gt;  config.database = Mongo::Connection.new.db(name)&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;# Call on each of the relevant models&lt;br /&gt;RssEntry.create_indexes()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Previously, you could specify auto-indexing within your models but this has now be deprecated or removed, so ignore any references to that.&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-655135994071888163?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/655135994071888163/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=655135994071888163' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/655135994071888163'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/655135994071888163'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/02/using-mongoid-in-ruby-applications.html' title='Using Mongoid in Ruby applications outside of Rails'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-3002783935930633423</id><published>2011-02-14T14:12:00.000-08:00</published><updated>2011-02-14T14:12:57.243-08:00</updated><title type='text'>Using Twitter for System Notifications</title><content type='html'>I finally figured out something that many, many people have been doing for quite a while - using Twitter as a way to deliver notification of system events.&lt;br /&gt;&lt;br /&gt;Twitter is a great way to deliver short messages to many people via many forms of media and devices. The default is that any message is available to anyone in the world. But you can also configure a Twitter account to be private, requiring the owner to explicitly allow access to other users. In the extreme case the owner can deny access to none but him or her self.&lt;br /&gt;&lt;br /&gt;Twitter handles all the messaging, all you need to do is have your server, web application or whatever, send a message to your private account whenever some event takes place. For example, I run long calculations on servers at work and I want to be notified when a job completes.&lt;br /&gt;&lt;br /&gt;You can find a load of UNIX command line twitter clients and libraries in all the main languages. So finding or building a suitable client is straightforward. &lt;br /&gt;&lt;br /&gt;I'll show you how to build a simple client in Ruby.&lt;br /&gt;&lt;br /&gt;If you want to send tweets to a private account then you will need proper authentication credentials. &lt;br /&gt;&lt;br /&gt;For this you need to use OAuth - username/password authentication has been deprecated.&lt;br /&gt;&lt;br /&gt;1: Sign in to Twitter as the owner of the private account&lt;br /&gt;2: Go to &lt;a href="http://dev.twitter.com/"&gt;http://dev.twitter.com&lt;/a&gt; - you'll still be signed in&lt;br /&gt;3: Click on 'Register an App' - now you're not really creating a new twitter application but pretend that you are  - give it a name - and you want to select that it is a 'client' application and that it should have 'read write' access to the account.&lt;br /&gt;4: Now go to 'your apps' and click on the new dummy app.&lt;br /&gt;5: Scroll down and get the 'Consumer key' and 'Consumer secret' - you'll need these in your code.&lt;br /&gt;6: Those are required for your application, but in addition you need a key and secret for the actual twitter account that you will want to write to.&lt;br /&gt;7: On your app settings page, on the right sidebar, click on 'My Access Token' and get 'Access Token (oauth_token)' and 'Access Token Secret (oauth_token_secret)'.&lt;br /&gt;&lt;br /&gt;Now we can write some code.&lt;br /&gt;&lt;br /&gt;8: Get the 'twitter' Ruby gem&lt;br /&gt;&lt;pre class="brush: bash;"&gt;$ gem install twitter&lt;/pre&gt;9: Write a small ruby app. This simple example takes a message on the command line, configures the client with the FOUR OAuth tokens/strings and then updates the private twitter account with the message:&lt;br /&gt;&lt;pre class="brush: ruby;"&gt;#!/usr/bin/env ruby&lt;br /&gt;require 'twitter'&lt;br /&gt;abort "Usage: #{$0} message" if ARGV.length == 0&lt;br /&gt;# Hard-wired to my private twitter account&lt;br /&gt;Twitter.configure do |config|&lt;br /&gt;  config.consumer_key = 'your-app_key'&lt;br /&gt;  config.consumer_secret = 'your_app_secret'&lt;br /&gt;  config.oauth_token = 'your_account_token'&lt;br /&gt;  config.oauth_token_secret = 'your_account_secret'&lt;br /&gt;end&lt;br /&gt;client.update(ARGV[0])&lt;br /&gt;&lt;/pre&gt;10: It's that simple...&lt;br /&gt;11: chmod a+x your script and run it with a message - check your private twitter account and you should see it.&lt;br /&gt;&lt;br /&gt;It's easy to think up (and code) custom notification scripts for this. As long as you have a network and as long as Twitter is up (OK, it has had some issues) then you don't need to worry about anything to do with distributing your messages. You can get them on your phone or your desktop, and you can leverage the work of others to display popup windows on your desktop, play tunes, flash lights, etc, etc.&lt;br /&gt;&lt;br /&gt;Just remember that when you create your private Twitter account that you go into the settings and make sure that it is indeed set to private.&lt;br /&gt;&lt;br /&gt;One extension that I've thought about is having my script take an optional URL, say pointing to the results from a computational run, and using a URL shorting service like &lt;a href="http://bit.ly/"&gt;http://bit.ly&lt;/a&gt; or &lt;a href="http://goo.gl/"&gt;http://goo.gl&lt;/a&gt; to let me include that in the tweet. Unfortunately none of the 'big name' services allow you to have private URLs so that might be a problem in some applications. But it's worth considering for some applications.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-3002783935930633423?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/3002783935930633423/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=3002783935930633423' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3002783935930633423'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3002783935930633423'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/02/using-twitter-for-system-notifications.html' title='Using Twitter for System Notifications'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/13582954721486542844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_f8EIq63pOsk/SdzN4VmaUoI/AAAAAAAAAAM/lS_mySaOTlQ/S220/craic_logo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-2219496234210937479</id><published>2011-02-14T11:36:00.000-08:00</published><updated>2011-02-14T12:00:53.745-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Heroku ruby sinatra PATSY'/><title type='text'>PATSY - a web service that makes patents easier to read</title><content type='html'>I've just launched &lt;a href="http://patsy.craic.com"&gt;PATSY&lt;/a&gt; - a new web service that reformats US patents to make them much easier to read than their original format.&lt;br /&gt;&lt;br /&gt;The text of patents is typically very dense and difficult to read.&lt;br /&gt;&lt;br /&gt;They are written as legal documents and inevitably this results in verbose and sometimes arcane text. Every component of invention will have all possible variants enumerated and this can result in sentences of ridiculous length with these variants delimited by commas. On top of that, the US patent office still prints patents as two narrow columns of text of each page - a format that might work in newspapers but which in technical patents is nonsensical.&lt;br /&gt;&lt;br /&gt;The underlying problem is that the patent offices should define and enforce a modern way of text formatting that is both easy to read and easy to parse in software.&lt;br /&gt;&lt;br /&gt;But as this is not likely to happen any time soon, I decided to write an application that reformats the text of patents into something more palatable.&lt;br /&gt;&lt;br /&gt;You enter a patent number into PATSY and it fetches the web page from the US patent office web site. It scans the text and splits up paragraphs into component sentences. Furthermore it splits sub-sentences by punctuation such as semi-colons. Simply adding this spacing makes a big difference.&lt;br /&gt;&lt;br /&gt;But PATSY goes much further. It highlights a series of phrases that are typically of interest - such as 'preferred embodiment' and 'SEQ ID NO'. It recognizes references to other patents and hyperlinks these to either their patent office site or to PATSY directly. In some cases, references to scientific publications can be identified and links are added that will take the user to the NIH PubMed site of abstracts, and from there the original publication can be accessed in most cases.&lt;br /&gt;&lt;br /&gt;PATSY only works with US patents right now and some of its features are geared towards biotechnology patents. The text parsing is not perfect but even at this early stage in its development, it can really make dense blocks of text much easier to read. In cases where the result is unclear, you can click the head of each text block to see the original text before any processing.&lt;br /&gt;&lt;br /&gt;While it is in this early stage, PATSY is completely free. If it turns out to be useful to a lot of people then I may offer it via subscription to heavy users, while retaining free access to occasional users.&lt;br /&gt;&lt;br /&gt;Please try &lt;a href="http://patsy.craic.com"&gt;PATSY&lt;/a&gt; out and send me feedback at info @ craic.com.&lt;br /&gt;&lt;br /&gt;Technical aspects:&lt;br /&gt;&lt;br /&gt;PATSY is written in Ruby using &lt;a href="http://www.sinatrarb.com"&gt;Sinatra&lt;/a&gt; as a lightweight web application framework. It runs on &lt;a href="http://heroku.com"&gt;Heroku&lt;/a&gt; which is a hosting service for Ruby web applications that sits atop Amazon web services. My steps involved in setting it up are &lt;a href="http://craiccomputing.blogspot.com/2011/02/running-ruby-19-sinatra-app-on-heroku.html"&gt;described here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;My experience with Heroku for this application thus far has been great. They allow you to set up applications with limited resources at no charge. If and when PATSY starts to get some traction then I can scale it up by adding more of what they call 'dynos'. That will incur some cost but there is no commitment or up front payment, plus the process of scaling is incredibly easy.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-2219496234210937479?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/2219496234210937479/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=2219496234210937479' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/2219496234210937479'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/2219496234210937479'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/02/patsy-web-service-that-makes-patents.html' title='PATSY - a web service that makes patents easier to read'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-8302880929641995265</id><published>2011-02-11T10:37:00.000-08:00</published><updated>2011-02-14T13:24:21.608-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='popup'/><category scheme='http://www.blogger.com/atom/ns#' term='open'/><category scheme='http://www.blogger.com/atom/ns#' term='window'/><title type='text'>JavaScript Bookmarklet that can create a New Window</title><content type='html'>The popup-blocking features of current browsers can be a problem if you are writing a JavaScript Bookmarklet that wants to open a new window. For example, I want to select text in an arbitrary window and then have a remote server operate on the text and return its results to a separate window, or tab. A bookmarklet is a great way to do this.&lt;br /&gt;&lt;br /&gt;One approach to writing these is to make the bookmarklet simply call a JavaScript script on a remote server, which does the real work. This results in a simple bookmarklet and lets you perform arbitrary operations in the remote script.&lt;br /&gt;&lt;br /&gt;But when the end result is the creation of a new browser window this approach will fail...&lt;br /&gt;&lt;br /&gt;Modern browsers view this a potential exploit and will only allow the creation of new windows as the result of &lt;span style="font-style:italic;"&gt;direct user interaction&lt;/span&gt; - i.e. the user clicks something.&lt;br /&gt;&lt;br /&gt;All is not lost - it just means that you need to put all your code in the bookmarklet itself. This is messy but for many scripts this should not be a problem.&lt;br /&gt;&lt;br /&gt;Here is my example. It gets the currently selected text and adds that to the URL of a remote service. It opens that URL in a new browser tab or window, depending on the specific parameters. If no text has been selected then it prompts to user to enter some. This first version will open the new page as a new tab in most browsers.&lt;br /&gt;&lt;pre class="brush: js; ruler: true"&gt;&amp;lt;a href="javascript:(function(){&lt;br /&gt;// Get the current selection&lt;br /&gt;var s = ''; &lt;br /&gt;if (window.getSelection) { &lt;br /&gt;s = window.getSelection(); &lt;br /&gt;} else if (document.getSelection) { &lt;br /&gt;s = document.getSelection(); &lt;br /&gt;} else if (document.selection) { &lt;br /&gt;s = document.selection.createRange().text; &lt;br /&gt;} &lt;br /&gt;// Prompt for input if no text selected&lt;br /&gt;if (s == '') {&lt;br /&gt;s = prompt('Enter your text:');&lt;br /&gt;}&lt;br /&gt;// Open the target URL in a new tab&lt;br /&gt;if ((s != '') &amp;&amp; (s != null)) {&lt;br /&gt;window.open('http://example.com/yourapp?id=' + s);&lt;br /&gt;}&lt;br /&gt;})();"&amp;gt;BOOKMARKLET&amp;lt;/a&amp;gt;&lt;/pre&gt;You would want to remove the comments from the bookmarklet, but you don't need to strip the newlines or minify the code.&lt;br /&gt;&lt;br /&gt;The default of most current browsers is to create new tabs instead of new windows. Users can set their preferences to override this but most will not. &lt;br /&gt;&lt;br /&gt;You may want to force the creation of a separate window. Think this through carefully - it may annoy some users if you start generating loads of windows. In some cases it is appropriate. It used to be that you could force this by passing '_blank' as the name of the new window but this does not appear to work in all browsers. Instead you need to explicitly specify one or more window properties, like width and height. &lt;br /&gt;&lt;br /&gt;This is a messy solution but it works. In my application I just replaced the window.open call with this form:&lt;pre class="brush: js; ruler: true"&gt;window.open('http://patsy.craic.com/patsy?id=' + s, '_blank', &lt;br /&gt;'height=600,width=1024,status=1,toolbar=1,directories=1,menubar=1,location=1');&lt;br /&gt;&lt;/pre&gt;The options string in the third argument specifies what the new window should look like. You may need to experiment with these. With Google Chrome on the Mac these do not give me the expected result - the address is not editable and there is no bookmarks bar. I also found that simply using 'status,toolbar,etc' without the '=1' did not work, although you will see this listed as a valid syntax.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-8302880929641995265?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/8302880929641995265/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=8302880929641995265' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/8302880929641995265'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/8302880929641995265'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/02/javascript-bookmarklet-that-can-create.html' title='JavaScript Bookmarklet that can create a New Window'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-9130276310574659660</id><published>2011-02-04T12:39:00.000-08:00</published><updated>2011-02-04T13:02:05.591-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby 1.9 Sinatra Heroku'/><title type='text'>Running a Ruby 1.9 Sinatra app on Heroku</title><content type='html'>I just got my first significant application running on &lt;a href="http://heroku.com/"&gt;Heroku&lt;/a&gt;. It uses &lt;a href="http://www.sinatrarb.com/"&gt;Sinatra&lt;/a&gt; instead of Rails and uses Ruby 1.9 - as a result the steps to get the application up and running were slightly different from the Heroku Quickstart Guide, which is tailored towards Rails apps.&lt;br /&gt;&lt;br /&gt;1. Setup&lt;br /&gt;Setup a Heroku account and set up the SSH keys&lt;br /&gt;Create your app and make sure it runs correctly on your local machine.&lt;br /&gt;Make sure that all paths are relative to the application root. &lt;br /&gt;Run the Sinatra app from a config.ru file.&lt;br /&gt;&lt;br /&gt;2. Setup Bundler&lt;br /&gt;I had an issue with this originally but this is what worked. I only need the sinatra gem so my Gemfile is:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;source :gemcutter&lt;br /&gt;gem 'sinatra'&lt;/code&gt;&lt;/pre&gt;and my config.ru file is:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;require 'bundler'&lt;br /&gt;Bundler.require&lt;br /&gt;require 'sinatra'&lt;br /&gt;require './my_app.rb'&lt;br /&gt;run MyApp.new&lt;/code&gt;&lt;/pre&gt;Note that although you need to have the heroku gem installed on your system in order to upload to Heroku, you do not 'require' it in your app.&lt;br /&gt;&lt;br /&gt;3. Setup git and commit the project.&lt;br /&gt;&lt;br /&gt;4. Create the Heroku app&lt;br /&gt;You want to specify an application name, otherwise Heroku will give you an arbitrary one. You also want to specify the run environment at Heroku that will be used. They refer to this as the '&lt;a href="http://docs.heroku.com/stack"&gt;stack&lt;/a&gt;' and for Ruby 1.9 you want to specify this directly and currently the correct option is '&lt;a href="http://docs.heroku.com/stack"&gt;bamboo-mri-1.9.2&lt;/a&gt;'. The create command is:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ heroku create my_app_name --stack bamboo-mri-1.9.2&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;5. Push the git repository to Heroku with:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ git push heroku master&lt;/code&gt;&lt;/pre&gt;The messages that follow should look something like this (some lines removed):&lt;br /&gt;&lt;pre&gt;&lt;code&gt;-----&amp;gt; Heroku receiving push&lt;br /&gt;-----&amp;gt; Sinatra app detected&lt;br /&gt;-----&amp;gt; Gemfile detected, running Bundler version 1.0.7&lt;br /&gt;       Unresolved dependencies detected; Installing...&lt;br /&gt;       Fetching source index for http://rubygems.org/&lt;br /&gt;       Installing rack (1.2.1) &lt;br /&gt;       Installing tilt (1.2.2) &lt;br /&gt;       Installing sinatra (1.1.2) &lt;br /&gt;       Using bundler (1.0.7) &lt;br /&gt;       Your bundle is complete! It was installed into ./.bundle/gems/&lt;br /&gt;       Compiled slug size is 500K&lt;br /&gt;-----&amp;gt; Launching... done&lt;br /&gt;       http://my_app_name.heroku.com deployed to Heroku&lt;/code&gt;&lt;/pre&gt;Now go to that URL and your app should be running.&lt;br /&gt;&lt;br /&gt;If there was a problem and the app failed to start then look at the logs:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ heroku logs -n 100&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You can set up apps with minimal (or no) database storage for free on Heroku. This is a great service as it lets you experiment to your heart's content.&lt;br /&gt;&lt;br /&gt;The idea behind Heroku is to remove from you the burden of server configuration. For my simple application this seems to work remarkably well.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-9130276310574659660?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/9130276310574659660/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=9130276310574659660' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/9130276310574659660'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/9130276310574659660'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/02/running-ruby-19-sinatra-app-on-heroku.html' title='Running a Ruby 1.9 Sinatra app on Heroku'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-3129714977931897090</id><published>2011-02-01T13:53:00.000-08:00</published><updated>2011-02-01T14:00:04.008-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby utf-8 character encodings'/><title type='text'>Ruby 1.9 and incompatible character encodings</title><content type='html'>I run into issues pulling remote text data into a Ruby 1.9 / Rails 3 app, which is using utf-8 encoding by default. The problem apparently comes from non-Ascii characters in binary or so-called ASCII-8BIT encoded text. I don't have a proper way to translate the offending characters as yet but my workaround is to strip them out and/or replace them with an ASCII character. &lt;br /&gt;&lt;br /&gt;This regex implements the workaround. Be sure to use the 'n' modifier on the regex. This specifies that the encoding of the text should be ignored and thus multibyte characters are treated as separate bytes.&lt;br /&gt;&lt;pre&gt;    str.gsub!(/[^\x00-\x7F]/n,'?')&lt;/pre&gt;&lt;br /&gt;Far from perfect, but it gets the job for me right now.&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-3129714977931897090?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/3129714977931897090/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=3129714977931897090' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3129714977931897090'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3129714977931897090'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/02/ruby-19-and-incompatible-character.html' title='Ruby 1.9 and incompatible character encodings'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-6377830812112261800</id><published>2011-01-04T15:27:00.000-08:00</published><updated>2011-01-04T15:34:59.442-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby rvm shell script'/><title type='text'>rvm and shell scripts</title><content type='html'>If you want to use a specific version of Ruby via &lt;a href="http://rvm.beginrescueend.com"&gt;RVM&lt;/a&gt; inside a shell script then you need to make sure that the environment is setup correctly.&lt;br /&gt;&lt;br /&gt;The RVM site addresses that &lt;a href="http://rvm.beginrescueend.com/workflow/scripting/"&gt;HERE&lt;/a&gt; for the case where RVM is installed in a user's home directory.&lt;br /&gt;&lt;br /&gt;But on my server I have a &lt;a href="http://craiccomputing.blogspot.com/2010/12/system-wide-rvm-install-on-ubuntu.html"&gt;system-wide installation&lt;/a&gt;. In that case you should have a /etc/rvmrc file with a default setup and you need to source this.&lt;br /&gt;&lt;br /&gt;Your scripts should look something like this:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;#!/bin/bash                                                                                                                                                 &lt;br /&gt;source "/etc/rvmrc"&lt;br /&gt;&lt;br /&gt;rvm use 1.9.2&lt;br /&gt;&lt;br /&gt;# mycommands_go_here&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-6377830812112261800?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/6377830812112261800/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=6377830812112261800' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/6377830812112261800'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/6377830812112261800'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2011/01/rvm-and-shell-scripts.html' title='rvm and shell scripts'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-8514119680134977391</id><published>2010-12-21T11:20:00.000-08:00</published><updated>2010-12-21T11:39:47.851-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='plugins'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><title type='text'>Per Page Inclusion of JavaScript in Rails view pages</title><content type='html'>I use various jQuery plugins in my Rails views but I don't want to download all that code in pages that don't use them. Furthermore I want to minimize the chance of namespace conflicts between different blocks of code.&lt;br /&gt;&lt;br /&gt;A simple way to do this is to add these lines to your application.html.erb file after the main JS includes:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;%= yield :custom_javascript_includes %&amp;gt;&lt;/code&gt;&lt;/pre&gt;and then add a block similar to this in each view template that needs custom JS.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;% content_for :custom_javascript_includes do %&gt;&lt;br /&gt;  &amp;lt;%= javascript_include_tag "your_custom_plugin.js" %&amp;gt;&lt;br /&gt;  &amp;lt;script type="text/javascript"&amp;gt;&lt;br /&gt;    // Your custom JavaScript code&lt;br /&gt;  &amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;% end %&amp;gt;&lt;/code&gt;&lt;/pre&gt;In this example I'm including a specific file from the public/javascripts directory and then adding some custom JS code that might define some events or trigger some action on page load.&lt;br /&gt;&lt;br /&gt;Here is a real example that uses the &lt;a href="http://chriswanstrath.com/facebox/"&gt;facebox jQuery plugin&lt;/a&gt; which provides 'light box' functionality. This code is placed at the top of my 'show' template.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;% content_for :custom_javascript_includes do %&gt;&lt;br /&gt;  &amp;lt;%= javascript_include_tag "facebox.js" %&amp;gt;&lt;br /&gt;  &amp;lt;script type="text/javascript"&amp;gt;&lt;br /&gt; jQuery(document).ready(function($) {&lt;br /&gt;       $('a[rel*=facebox]').facebox({&lt;br /&gt;         loadingImage : '/images/facebox_loading.gif',&lt;br /&gt;         closeImage   : '/images/facebox_closelabel.gif'&lt;br /&gt;       });&lt;br /&gt; });&lt;br /&gt;  &amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;% end %&amp;gt;&lt;/code&gt;&lt;/pre&gt;You can take this further by also including custom stylesheets linked to these plugins in the same block. That can result CSS and JS includes being interspersed in the resulting HTML file which some people may not like, but I don't think there are any practical drawbacks to it.&lt;br /&gt;&lt;br /&gt;The big win is that you keep your custom JS code right there in the same file as your HTML. If that JS code is substantial you could move it into a partial that resides in your views directory, as opposed to having it separated in the public/javascripts directory.&lt;br /&gt;&lt;br /&gt;For high performance production sites you should weigh the benefits of this approach in terms of clarity with the performance benefit of stashing all your JS code in a single file and minifying it. &lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-8514119680134977391?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/8514119680134977391/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=8514119680134977391' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/8514119680134977391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/8514119680134977391'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/12/per-page-inclusion-of-javascript-in.html' title='Per Page Inclusion of JavaScript in Rails view pages'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-2830009994115543880</id><published>2010-12-14T14:58:00.000-08:00</published><updated>2010-12-14T15:11:38.406-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MySQL import export'/><title type='text'>MySQL Data export/import probelm with SQL SECURITY DEFINER</title><content type='html'>Importing a MySQL database dump from a client into my system I got this error:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ mysql -u root -p  example_db &amp;lt; example_db_dump.sql &lt;br /&gt;Enter password: &lt;br /&gt;ERROR 1449 (HY000) at line 5172: The user specified as a definer ('smith'@'localhost') does not exist&lt;/code&gt;&lt;/pre&gt;Running 'grep' for that user turned up a bunch of lines like this:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;/*!50013 DEFINER=`smith`@`localhost` SQL SECURITY DEFINER */&lt;/code&gt;&lt;/pre&gt;These are created on the 'donor' MySQL system when creating one or more views of the data. That user does not exist on my system and so MySQL complains.&lt;br /&gt;&lt;br /&gt;I don't care about those views so the easiest way to deal with this issue is to remove these '50013' lines. You can do that with 'sed':&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ sed '/\*\!50013 DEFINER/d' example_db_dump.sql &amp;gt; example_db_dump_clean.sql&lt;/code&gt;&lt;/pre&gt;You need to drop the new database as the import process partially worked, re-create it and then you can reimport:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ mysqladmin -u root -p drop example_db&lt;br /&gt;$ mysqladmin -u root -p create example_db&lt;br /&gt;$ mysql -u root -p example_db &amp;lt; example_db_dump_clean.sql&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now, if you need to use the Views in your copy of the database then you need to either create that user locally and leave the lines, or change the user in those lines to one that does exist locally.&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-2830009994115543880?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/2830009994115543880/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=2830009994115543880' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/2830009994115543880'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/2830009994115543880'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/12/mysql-data-exportimport-probelm-with.html' title='MySQL Data export/import probelm with SQL SECURITY DEFINER'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-5308806179251392264</id><published>2010-12-12T10:06:00.000-08:00</published><updated>2010-12-12T10:11:39.466-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AWS ec2 ubuntu'/><title type='text'>Installing Amazon EC2 tools on Ubuntu 10.04</title><content type='html'>The Amazon EC2 ami and api tool packages are not found by apt-get using the default sources list. You need to add 'multiverse' to the list. Here is how you install the tools:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ sudo perl -pi -e 's%(universe)$%$1 multiverse%'  /etc/apt/sources.list&lt;br /&gt;$ sudo apt-get update&lt;br /&gt;$ sudo apt-get install ec2-ami-tools&lt;/code&gt;&lt;/pre&gt;Of course, you also need to set up your environment variables as per usual so that the tools can access your keys.&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-5308806179251392264?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/5308806179251392264/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=5308806179251392264' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5308806179251392264'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5308806179251392264'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/12/installing-amazon-ec2-tools-on-ubuntu.html' title='Installing Amazon EC2 tools on Ubuntu 10.04'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-6324090335127980402</id><published>2010-12-05T10:28:00.000-08:00</published><updated>2010-12-05T10:46:44.832-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby  bundler'/><title type='text'>Using Bundler with a non-Rails Ruby project</title><content type='html'>&lt;a href="http://gembundler.com/"&gt;Bundler&lt;/a&gt; is a Ruby Gem to help you manage the various gem dependencies in your application.&lt;br /&gt;&lt;br /&gt;It has gotten a lot of attention as it is ,er, bundled with Rails3 and represents a welcome addition to that framework. But you can use Bundler in any Ruby application to help make deployments go smoothly.&lt;br /&gt;&lt;br /&gt;For a regular Ruby application the steps involved are simple:&lt;br /&gt;&lt;br /&gt;1: Install Bundler on your system&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ gem install bundler&lt;/code&gt;&lt;/pre&gt;2: Create a file called 'GemFile' at the top level of your application directory&lt;br /&gt;Add gem sources to this and each gem that your application relies on. This example includes the main gem sources and a single gem&lt;br /&gt;&lt;pre&gt;&lt;code&gt;source :rubygems&lt;br /&gt;source :rubyforge&lt;br /&gt;source :gemcutter&lt;br /&gt;&lt;br /&gt;gem "json"&lt;/code&gt;&lt;/pre&gt;3: Run 'bundle install'&lt;br /&gt;This will now install any missing gems. It does harm to run it more than once.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ bundle install&lt;br /&gt;Fetching source index for http://rubygems.org/&lt;br /&gt;Fetching source index for http://rubygems.org/&lt;br /&gt;Fetching source index for http://rubygems.org/&lt;br /&gt;Using json (1.4.6)&lt;br /&gt;Using bundler (1.0.3)&lt;br /&gt;Your bundle is complete! It was installed into /Users/jones/.rvm/gems/ruby-1.9.2-p0&lt;/code&gt;&lt;/pre&gt;If you look in your application directory you will see a new file called Gemfile.lock. Bundler uses this and you want to keep it, adding it to your git repository (or equivalent). You can also find a .bundle directory containing a config file. I guess you can use this for fancier configurations, but a basic app you can ignore it.&lt;br /&gt;&lt;br /&gt;4: Deploy your app&lt;br /&gt;Now when you deploy your app in a new location (with the bundler gem installed) you can simply run 'bundle install' in your app directory and you'll be good to go.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-6324090335127980402?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/6324090335127980402/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=6324090335127980402' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/6324090335127980402'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/6324090335127980402'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/12/using-bundler-with-non-rails-ruby.html' title='Using Bundler with a non-Rails Ruby project'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-3827117000459527620</id><published>2010-12-05T09:21:00.000-08:00</published><updated>2010-12-05T09:28:11.680-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unix shell'/><title type='text'>Deleteing a file with a name that starts with a hyphen</title><content type='html'>Here's a simple fix to a tricky problem (simple with hindsight, of course)...&lt;br /&gt;&lt;br /&gt;By accident I created a file called '--latest' and wanted to delete it. But unix thinks that '--' signifies a program option. Escaping the hyphens didn't work either.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ rm '--latest'&lt;br /&gt;rm: illegal option -- -&lt;br /&gt;usage: rm [-f | -i] [-dPRrvW] file ...&lt;br /&gt;       unlink file&lt;br /&gt;$ rm '\-\-latest'&lt;br /&gt;rm: \-\-latest: No such file or directory&lt;br /&gt;$ rm "\-\-latest"&lt;br /&gt;rm: \-\-latest: No such file or directory&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The simple solution is to give a more complete path specification that avoids having the hyphens as the first characters.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ rm ./--latest&lt;/code&gt;&lt;/pre&gt;Problem solved!&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-3827117000459527620?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/3827117000459527620/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=3827117000459527620' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3827117000459527620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3827117000459527620'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/12/deleteing-file-with-name-that-starts.html' title='Deleteing a file with a name that starts with a hyphen'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-1699567816385267918</id><published>2010-12-03T15:54:00.000-08:00</published><updated>2010-12-03T16:56:33.964-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='chef aws ec2 ubuntu ruby'/><title type='text'>Using Opscode Chef to start up a node on AWS EC2 - A Simple Example</title><content type='html'>&lt;a href="http://opscode.com/chef/"&gt;Chef from opscode.com&lt;/a&gt; is a suite of tools for managing computing infrastructure, from spinning up new nodes to installing Ruby gems to any custom operation you care to code up. It gets great reviews from those who manage numbers of unix (and other) systems and it has support for Amazon AWS and other cloud vendors baked right in.&lt;br /&gt;&lt;br /&gt;I'm just getting started with it and am eager to go further but, like many projects, the documentation is far from clear. It has a lot of options and that typically means complexity. Perhaps because they are targeting folks who do systems administration for a living, their docs skim over some of the crucial basics.&lt;br /&gt;&lt;br /&gt;My main interest in Chef is using it to spin up AWS EC2 nodes, configure them to my tastes and then spin them down as needed.&lt;br /&gt;&lt;br /&gt;Here are the steps I took to get a node up and running:&lt;br /&gt;&lt;br /&gt;0: I'm assuming you know how to fire up EC2 nodes from the management console or the command line on your desktop machine, that you have a keypair set up and that you are familiar with AMIs and the other terminology. If not, then get comfortable with EC2 before going any further.&lt;br /&gt;&lt;br /&gt;1: I'm also assuming that you have a basic chef setup on your desktop and an account on Opscode's chef server (it's free for up to 5 nodes) and that you have written and tested a simple recipe on your desktop. If not, get comfortable with that before going further.&lt;br /&gt;&lt;br /&gt;2: Add your AWS credentials to your knife.rb file (typically in ~/.chef)&lt;br /&gt;The docs say to enter them in this format, which is different from the other configuration parameters that are generated from the opscode server... I don't know why... but this works:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;# EC2 access keys&lt;br /&gt;knife[:aws_access_key_id]     = "&amp;lt;your access key id&amp;gt;"&lt;br /&gt;knife[:aws_secret_access_key] = "&amp;lt;your secret access key&amp;gt;"&lt;/code&gt;&lt;/pre&gt;3: Figure out your EC2 parameters for the node you want to spin up.&lt;br /&gt;&lt;br /&gt;The AMI ID - I'm using a 32 bit Ubuntu AMI (ami-480df921)&lt;br /&gt;&lt;br /&gt;The Instance Type - I'm testing with a Micro instance (t1.micro)&lt;br /&gt;&lt;br /&gt;The Keypair name (mine is called 'craic-ec2-keypair') and the location of the SSH identity file that is linked with this (mine is in ~/.ssh/craic-ec2-keypair.pem).&lt;br /&gt;&lt;br /&gt;The User that you (and chef) will ssh in to the node with (Ubuntu 10.04 wants me to use 'ubuntu' instead of 'root')&lt;br /&gt;&lt;br /&gt;The Security Group for the server (I just use 'default' which is what I set up when I first started with EC2)&lt;br /&gt;&lt;br /&gt;The Chef Recipe(s) and/or Role(s) that you want to run on the new EC2 server (I'm just going to run a simple one that I created called 'craic_test' that writes a file in /tmp) - Make sure this works on a non-EC2 client first!&lt;br /&gt;&lt;br /&gt;4: Let's do it...&lt;br /&gt;The chef command that you use is 'knife' with some EC2 specific options. You can find more information &lt;a href="http://help.opscode.com/faqs/chefbasics/knife"&gt;HERE&lt;/a&gt; in their FAQs, which is MUCH more complete than their Wiki documentation on knife...&lt;br /&gt;&lt;br /&gt;The command will be 'knife ec2 server create' followed by a bunch of options. That's pretty self explanatory - but then we get into the options... Here is the full command I used split across multiple lines, which I shall explain below:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ knife ec2 server create "recipe[craic_test]" \&lt;br /&gt;      -i ami-480df921 \&lt;br /&gt;      -f t1.micro \&lt;br /&gt;      -x ubuntu \&lt;br /&gt;      -S craic-ec2-keypair \&lt;br /&gt;      -I ~/.ssh/craic-ec2-keypair.pem \&lt;br /&gt;      -G default&lt;/code&gt;&lt;/pre&gt;The first line is the command itself followed by the recipes and/roles in the standard chef format ("recipe[craic_test]").&lt;br /&gt;&lt;br /&gt;The EC2 AMI is specified with the &lt;span style="color: rgb(255, 0, 0);"&gt;-i &lt;/span&gt;option, then the Instance Type is specified with the &lt;span style="color: rgb(255, 0, 0);"&gt;-f&lt;/span&gt; option (aka &lt;span style="color: rgb(255, 0, 0);"&gt;--flavor&lt;/span&gt; - I don't know why they chose that...). &lt;br /&gt;&lt;br /&gt;Next comes the ssh user with the &lt;span style="color: rgb(255, 0, 0);"&gt;-x&lt;/span&gt; option, the SSH Keypair name with &lt;span style="color: rgb(255, 0, 0);"&gt;-S&lt;/span&gt; (upper case S) and the location of the matching identity file with the &lt;span style="color: rgb(255, 0, 0);"&gt;-I&lt;/span&gt; option (upper case I) - then finally the security group with the &lt;span style="color: rgb(255, 0, 0);"&gt;-G&lt;/span&gt; option (upper case G).&lt;br /&gt;&lt;br /&gt;I am really hoping that there is some way to store some of these options in knife.rb or someplace convenient as most of these will not change for my uses.&lt;br /&gt;&lt;br /&gt;All being well, what happens next is that the node gets spun up on EC2, chef installs the prerequisites it needs to run on the node and downloads the chef client over there. Chef will create the new node record on the chef server, download your recipes and then execute them.&lt;br /&gt;&lt;br /&gt;What you will see is a TON of output as everything runs. I won't subject you to all of that here, but the first few line will look like this:&lt;br /&gt;&lt;pre&gt;Instance ID: i-08da8865&lt;br /&gt;Flavor: t1.micro&lt;br /&gt;Image: ami-480df921&lt;br /&gt;Availability Zone: us-east-1b&lt;br /&gt;Security Groups: default&lt;br /&gt;SSH Key: craic-ec2-keypair&lt;br /&gt;&lt;br /&gt;Waiting for server............&lt;br /&gt;Public DNS Name: ec2-184-72-190-66.compute-1.amazonaws.com&lt;br /&gt;Public IP Address: 184.72.190.66&lt;br /&gt;Private DNS Name: domU-12-31-39-0F-29-E8.compute-1.internal&lt;br /&gt;Private IP Address: 10.193.42.22&lt;br /&gt;&lt;br /&gt;Waiting for sshddone&lt;br /&gt;INFO: Bootstrapping Chef on&lt;br /&gt;0% [Working]90-66.compute-1.amazonaws.com&lt;br /&gt;[...]&lt;/pre&gt;This shows the IP info, etc for your new instance and is followed by pages of messages reporting the downloading and installation of all the prerequisites for Chef. At the end you should see your recipes being run and finally a summary once again of the instance information:&lt;br /&gt;&lt;pre&gt;Instance ID: i-08da8865&lt;br /&gt;Flavor: t1.micro&lt;br /&gt;Image: ami-480df921&lt;br /&gt;Availability Zone: us-east-1b&lt;br /&gt;Security Groups: default&lt;br /&gt;SSH Key: craic-ec2-keypair&lt;br /&gt;Public DNS Name: ec2-184-72-190-66.compute-1.amazonaws.com&lt;br /&gt;Public IP Address: 184.72.190.66&lt;br /&gt;Private DNS Name: domU-12-31-39-0F-29-E8.compute-1.internal&lt;br /&gt;Private IP Address: 10.193.42.22&lt;br /&gt;Run List: recipe[craic_test]&lt;/pre&gt;&lt;br /&gt;5: Now you can ssh into your node and you should see that your recipes have run and done whatever you asked of them.&lt;br /&gt;&lt;br /&gt;One good thing about all the prerequisites getting installed, for an Ubuntu system at least, is that you now have a node with a lot of development libraries and tools already in place (especially if you work in Ruby).&lt;br /&gt;&lt;br /&gt;That's it for the basic installation.&lt;br /&gt;&lt;br /&gt;Remember to terminate your node when you are finished as you are being charged for it AND remove any test nodes from your Opscode server account as they will count against your account limit.&lt;br /&gt;&lt;br /&gt;There is obviously a lot more that you can, and need to, do to set up your nodes but this walk through gets you to a functioning node.&lt;br /&gt;&lt;br /&gt;Happy cooking&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-1699567816385267918?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/1699567816385267918/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=1699567816385267918' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/1699567816385267918'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/1699567816385267918'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/12/using-opscode-chef-to-start-up-node-on.html' title='Using Opscode Chef to start up a node on AWS EC2 - A Simple Example'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-6180984738294628488</id><published>2010-12-03T11:37:00.000-08:00</published><updated>2010-12-03T14:19:10.925-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu rvm ruby'/><title type='text'>System-wide rvm install on Ubuntu</title><content type='html'>Here are the steps I used to install &lt;a href="http://rvm.beginrescueend.com"&gt;RVM&lt;/a&gt; system wide on a Ubuntu 10.04.1 LTS node on Amazon EC2, using one of the Canonical AMIs. These set up the primary user as 'ubuntu', requiring you to sudo for system commands. I could install rvm under that user but installing System-Wide is recommended.&lt;br /&gt;&lt;br /&gt;This HOWTO is based on the  RVM page &lt;a href="http://rvm.beginrescueend.com/deployment/system-wide/"&gt;http://rvm.beginrescueend.com/deployment/system-wide/&lt;/a&gt;. But I find the RVM site documentation makes a few assumptions with regard to commands.&lt;br /&gt;&lt;br /&gt;1: Install git if you don't already have it&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ sudo apt-get install git-core&lt;/pre&gt;&lt;/code&gt;2: Download RVM&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ sudo bash &amp;lt; &amp;lt;( curl -L http://bit.ly/rvm-install-system-wide )&lt;/pre&gt;&lt;/code&gt;This creates /usr/local/rvm and the group 'rvm'&lt;br /&gt;&lt;br /&gt;3: Add each user to group rvm&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ sudo usermod -aG rvm ubuntu&lt;/pre&gt;&lt;/code&gt;4: Add startup lines to each user's .profile&lt;br /&gt;&lt;pre&gt;&lt;code&gt;[[ -s '/usr/local/lib/rvm' ]] &amp;&amp; source '/usr/local/lib/rvm'&lt;/pre&gt;&lt;/code&gt;5: Add this line to /etc/rvmrc (may not be necessary)&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ echo "export rvm_path=/usr/local/rvm" &amp;gt; /etc/rvmrc&lt;/pre&gt;&lt;/code&gt;6: Use rvm as a user - best to logout/login first to make sure you get all the paths etc setup&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ rvm list&lt;br /&gt;$ rvm package install zlib   ( I needed this to get install to work )&lt;br /&gt;$ rvm install 1.9.2 --with-zlib-dir=/usr/local/rvm/usr&lt;/pre&gt;&lt;/code&gt;Note that you use rvm as a regular user, not via sudo, even though this is a system wide install.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-6180984738294628488?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/6180984738294628488/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=6180984738294628488' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/6180984738294628488'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/6180984738294628488'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/12/system-wide-rvm-install-on-ubuntu.html' title='System-wide rvm install on Ubuntu'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-3938435443085987050</id><published>2010-11-12T13:31:00.000-08:00</published><updated>2010-11-12T14:04:24.038-08:00</updated><title type='text'>Extracting Text from PDF documents on Mac OS X</title><content type='html'>There are various ways to extract the text from a PDF document. In Mac OS X there are two effective ways that cost nothing.&lt;br /&gt;&lt;br /&gt;1: Open the PDF in Preview or Adobe Acrobat Reader, select all the text, copy and paste into your editor of choice.&lt;br /&gt;&lt;br /&gt;This is a quick and easy solution for one or a few documents. But for a large number of documents it would quickly become tedious.&lt;br /&gt;&lt;br /&gt;Neither application allows you to Save As Text from the menu, which is unfortunate.&lt;br /&gt;&lt;br /&gt;I also see a significant difference between the pasted text when the original PDF has columns of text. Compare the same original text copied from Acrobat Reader:&lt;br /&gt;&lt;pre&gt;MOLECULAR FORMULA C6492H10060N1724O2028S42&lt;br /&gt;MOLECULAR WEIGHT 146.0 kDa&lt;br /&gt;TRADEMARK None as yet&lt;br /&gt;MANUFACTURER MedImmune&lt;br /&gt;CODE DESIGNATION MEDI-563&lt;br /&gt;CAS REGISTRY NUMBER 1044511-01-4&lt;/pre&gt;and Mac OS X Preview:&lt;pre&gt;MOLECULAR FORMULA MOLECULAR WEIGHT TRADEMARK MANUFACTURER CODE DESIGNATION CAS REGISTRY NUMBER&lt;br /&gt;C6492H10060N1724O2028S42 146.0 kDa None as yet MedImmune&lt;br /&gt;MEDI-563 1044511-01-4&lt;/pre&gt;The first version is the right one. So copying from Acrobat Reader is the better solution.&lt;br /&gt;&lt;br /&gt;2. To handle many documents you want a script of some sort that just extracts the text. You can do this with the Mac OS X Automator application. I'd not used this before but it gives you access to a whole load of functions/services. Well worth checking out. You'll find Automator in your applications folder. Open it up and...&lt;br /&gt;&lt;br /&gt;- Select Application in the template window that appears on opening.&lt;br /&gt;- In the Automator window you have two vertical panels on the left and a grey workspace on the right. Click the 'Actions' button in the top left.&lt;br /&gt;- In the left hand column, under Library, click 'PDFs' to bring up a list of PDF related actions in the second column.&lt;br /&gt;- Select, drag and drop 'Extract PDF Text' onto the workspace. A dialog will appear.&lt;br /&gt;- Select the appropriate options - plain text or RTF, folder in which to output the text, etc.&lt;br /&gt;- Save As... and give your new app a suitable name&lt;br /&gt;- Quit Automator&lt;br /&gt;- Drag and drop a PDF onto the icon for the app and it will extract the text and output that in a file in the directory you configured in the app&lt;br /&gt;&lt;br /&gt;Simple! Now you can just drag and drop PDFs and they will be converted automatically.&lt;br /&gt;&lt;br /&gt;Automator can do a whole lot more than this, especially if you have a series of steps that must applied to files (e.g. image processing). If you are into scripting, take a look at the way this all works. Right click on the app icon and 'Show Package Contents'.&lt;br /&gt;&lt;br /&gt;You can also learn about this via &lt;a href="http://mathiasbynens.be/notes/shell-script-mac-apps"&gt;this article by Mathias Bynens&lt;/a&gt; on a simple way to convert UNIX scripts into apps ... it's the same mechanism.&lt;br /&gt;&lt;br /&gt;So now I've got an automated way to extract text... BUT... the script uses Preview for the extraction, and that still gives me the incorrect ordering of text that I showed in the above example... dang it... not a deal breaker but frustrating all the same&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-3938435443085987050?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/3938435443085987050/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=3938435443085987050' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3938435443085987050'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3938435443085987050'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/11/extracting-text-from-pdf-documents-on.html' title='Extracting Text from PDF documents on Mac OS X'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-8183760688067176431</id><published>2010-11-12T08:28:00.000-08:00</published><updated>2010-11-12T09:15:32.411-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript date browsers Mac'/><title type='text'>Javascript Date.parse browser compatibility issue</title><content type='html'>Just got burned with a Javascript incompatibility between Firefox and Safari on the Mac...&lt;br /&gt;&lt;br /&gt;&lt;a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/parse"&gt;Date.parse()&lt;/a&gt; takes a string representation of a Date and return the number of milliseconds since the epoch. It has always been able to take dates in IETF format, such as "Jan 1, 2010" but as of Javascript 1.8.5 it can handle ISO8601 format as well, such as "2010-01-01".&lt;br /&gt;&lt;br /&gt;I use ISO8601 in all my applications and in Firefox 3.6.12 (on the Mac) this works fine:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;gt; Date.parse("Jan 1, 2010 GMT");&lt;br /&gt;1262304000000&lt;br /&gt;&amp;gt; Date.parse("2010-01-01");&lt;br /&gt;1262304000000&lt;/code&gt;&lt;/pre&gt;Note that the ISO8601 form assumes the GMT timezone, but the IETF form assumes local timezone unless you specify GMT.&lt;br /&gt;&lt;br /&gt;The problem for me arose in Safari (5.0.2) on the Mac:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;gt; Date.parse("Jan 1, 2010 GMT");&lt;br /&gt;1262304000000&lt;br /&gt;Date.parse("2010-01-01");&lt;br /&gt;NaN&lt;/code&gt;&lt;/pre&gt;Hmm...&lt;br /&gt;&lt;br /&gt;And just to muddy the waters further, here is the output on Google Chrome 7.0.517.44:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;gt; Date.parse("Jan 1, 2010 GMT");&lt;br /&gt;1262304000000&lt;br /&gt;Date.parse("2010-01-01");&lt;br /&gt;1262332800000&lt;/code&gt;&lt;/pre&gt;The ISO8601 date is handled OK but is returned in the local timezone.&lt;br /&gt;&lt;br /&gt;I need a fail safe way to parse ISO8601 dates - what to do...? Here's what I came up with:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;var date_str = '2010-01-01';&lt;br /&gt;var iso8601_regex = /(\d{4})[\/-](\d{2})[\/-](\d{2})/;&lt;br /&gt;var match = iso8601_regex.exec(date_str);&lt;br /&gt;var date = new Date(match[1], match[2] - 1, match[3]);&lt;br /&gt;var milliseconds = Date.parse(date);    // -&amp;gt; 1262332800000 (local time)&lt;br /&gt;milliseconds = Date.UTC(match[1], match[2] - 1, match[3], 0, 0, 0);  // -&amp;gt; 1262304000000 (UTC/GMT)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Note the '- 1' with the month (match[2]) - the first month is 0 - go figure.&lt;br /&gt;This produces the same results in Mac Firefox, Safari and Chrome - consistent behaviour - yes, really!&lt;br /&gt;&lt;br /&gt;What a palaver... &lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-8183760688067176431?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/8183760688067176431/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=8183760688067176431' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/8183760688067176431'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/8183760688067176431'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/11/javascript-dateparse-browser.html' title='Javascript Date.parse browser compatibility issue'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-110708823317675617</id><published>2010-11-09T13:06:00.000-08:00</published><updated>2010-11-09T13:43:21.900-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails has_many through testing simple_form'/><title type='text'>Rails has_many :through associations and edit/update actions</title><content type='html'>Consider a basic has_many :through association&lt;br /&gt;&lt;pre&gt;&lt;code&gt;class Drug &amp;lt; ActiveRecord::Base&lt;br /&gt;  has_many :indications&lt;br /&gt;  has_many :diseases, :through =&amp;gt; :indications, :uniq =&amp;gt; true&lt;/code&gt;&lt;/pre&gt;Here a drug can be used to treat multiple diseases and any disease can be treated with multiple drugs (that side of the association is not shown). The 'indications' is a basic linking table with drug_id and disease_id.&lt;br /&gt;&lt;br /&gt;In the drug#new and drug#edit forms you might use a select menu that allows you to select multiple diseases. I use the 'simple_form' gem for my forms and the 'association' method makes this trivial.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;%= f.association :diseases,&lt;br /&gt;           :collection =&amp;gt; Disease.all(:order =&amp;gt; 'name') %&amp;gt;&lt;/code&gt;&lt;/pre&gt;In order for this to work you need to add an attr_accessible called :disease_ids to your model. With that, simple form should handle all details needed to create and update the association.&lt;br /&gt;&lt;br /&gt;But there is a problem with the edit/update actions when you want to deselect ALL diseases. If you do this in the form then no disease_ids parameter will get passed to your controller and so this column will not get updated. It is a classic issue with HTML form updates and applies to checkboxes as well.&lt;br /&gt;&lt;br /&gt;The solution is to add a line to the updater action in your controller that sets the disease_ids parameter to an empty array if it does not exist:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;  def update&lt;br /&gt;    params[:drug][:disease_ids] ||= []&lt;br /&gt;    @drug = Drug.find(params[:id])&lt;br /&gt;    [...]&lt;/code&gt;&lt;/pre&gt;This works fine - adds a bit of clutter to the controller but there you go...&lt;br /&gt;&lt;br /&gt;However, this will break a basic functional test for the update action and you will get an error similar to this:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;test_update_valid(DrugsControllerTest):&lt;br /&gt;NoMethodError: You have a nil object when you didn't expect it!&lt;br /&gt;You might have expected an instance of Array.&lt;br /&gt;The error occurred while evaluating nil.[]&lt;/code&gt;&lt;/pre&gt;The problem stems from the basic stub for your object not passing a params[:drug] hash. Now, I'm not an expert on stubs/mocking so there may be a much cleaner way of fixing this, but I fix this by explicitly creating the needed parameters and passing them in the 'put' method.&lt;br /&gt;&lt;br /&gt;Here is an example of a basic update test&lt;br /&gt;&lt;pre&gt;&lt;code&gt;  def test_update_valid&lt;br /&gt;    Drug.any_instance.stubs(:valid?).returns(true)&lt;br /&gt;    put :update, :id =&amp;gt; Drug.first&lt;br /&gt;    assert_redirected_to drug_url(assigns(:drug))&lt;br /&gt;  end&lt;/code&gt;&lt;/pre&gt;and here is the modified one that will work&lt;br /&gt;&lt;pre&gt;&lt;code&gt;  def test_update_valid&lt;br /&gt;    Drug.any_instance.stubs(:valid?).returns(true)&lt;br /&gt;    put :update, { :id =&amp;gt; Drug.first, :drug =&amp;gt; { :disease_ids =&amp;gt [] } }&lt;br /&gt;    assert_redirected_to drug_url(assigns(:drug))&lt;br /&gt;  end&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Of course I should be building out the tests to provide truly useful tests, but if you can't get beyond this step, the others don't really matter.&lt;br /&gt;&lt;br /&gt;Hope this helps....&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-110708823317675617?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/110708823317675617/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=110708823317675617' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/110708823317675617'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/110708823317675617'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/11/rails-hasmany-through-associations-and.html' title='Rails has_many :through associations and edit/update actions'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-5946682217961609178</id><published>2010-11-09T07:56:00.001-08:00</published><updated>2010-11-09T08:19:01.694-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='html5 textarea spellcheck'/><title type='text'>Disabling spell check in HTML forms</title><content type='html'>I work with DNA and protein sequences and I often have HTML forms with a textarea for entering sequence. Unfortunately my browser sees that text (e.g. 'agctagagctcgatagc') and decides that this is misspelled and underlines all the sequence text with a red dotted line... ugly...&lt;br /&gt;&lt;br /&gt;In HTML5 you can now disable spell checking on textarea and text inputs using the option 'spellcheck' = 'false' - EASY!&lt;br /&gt;&lt;br /&gt;Note that this is a HTML attribute, NOT CSS - so you have to set it in the form itself.&lt;br /&gt;&lt;br /&gt;Browser support for the feature may vary. It works on Firefox and Safari on the Mac for sure.&lt;br /&gt;&lt;br /&gt;A related attribute is 'contenteditable' that allows you to control whether specific parts of a textarea's content can be modified - like 'readonly' but with much more control.&lt;br /&gt;&lt;br/&gt; &amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-5946682217961609178?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/5946682217961609178/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=5946682217961609178' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5946682217961609178'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5946682217961609178'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/11/disabling-spell-check-in-html-forms.html' title='Disabling spell check in HTML forms'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-976823477415116154</id><published>2010-11-02T08:11:00.000-07:00</published><updated>2010-11-09T12:59:40.292-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails testing machinist factory_girl'/><title type='text'>Rails, Factory_girl and Bioinformatics - a gotcha</title><content type='html'>I've been using &lt;a href="http://github.com/thoughtbot/factory_girl"&gt;factory girl&lt;/a&gt; as a replacement for Fixtures in a new Rails application. It has been working well but I just stumbled across a BIG gotcha for my application. &lt;br /&gt;&lt;br /&gt;I work on bioinformatics applications with DNA and Protein sequences and having a model with a column called 'sequence' is a natural choice.&lt;br /&gt;&lt;br /&gt;The problem is that Factory Girl allows you to create objects in which a specific field is given a sequential id. For example 'user_1', 'user_2', etc. You set that up in your Factory definition like this:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;Factory.define :mymodel do |f|&lt;br /&gt;  f.sequence(:name) {|n| "name_#{n}" }&lt;br /&gt;end&lt;/code&gt;&lt;/pre&gt;When you have a model with a field called sequence you would define that like this:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;Factory.define :mymodel do |f|&lt;br /&gt;  f.sequence(:name) {|n| "name_#{n}" }&lt;br /&gt;  f.sequence 'acgtacgtacgt'&lt;br /&gt;end&lt;/code&gt;&lt;/pre&gt;You see the problem... Running a test with this in it brings up an error message like this:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;  1) Error:&lt;br /&gt;test: A Sequence instance should be valid. (SequenceTest):&lt;br /&gt;NoMethodError: undefined method `call' for nil:NilClass&lt;br /&gt;    /Users/jones/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.1/lib/active_support/whiny_nil.rb:48:in `method_missing'&lt;/code&gt;&lt;/pre&gt;The same problem will arise if you have a column called 'association'. &lt;br /&gt;&lt;br /&gt;This is a bad design choice to mix up field names and methods. A better choice would have been to use a 'verb' such as f.generate_sequence(:name), which is much less likely to be used as a column name.&lt;br /&gt;&lt;br /&gt;I can't see a way around this other than changing the name of the column in my model, which I am very reluctant to do.&lt;br /&gt;&lt;a href="http://github.com/notahat/machinist"&gt;Machinist&lt;/a&gt; is an alternative to Factory Girl, so that might be a solution - or hacking the factory_girl gem to change the name of the methods... &lt;br /&gt;&lt;br /&gt;UPDATE: Factory Girl will allow alternate syntaxes - see the &lt;a href="http://github.com/thoughtbot/factory_girl"&gt;"Alternate Syntaxes" section&lt;/a&gt;. Not sure if its the best path for me but might get me over the immediate hurdle.&lt;br /&gt;&lt;br /&gt;UPDATE 2: Just tried Machinist and that solves the first problem... however it fails if you have a column called 'alias' in a blueprint - the trick here is to precede the column name with 'self', i.e. 'self/alias' works.&lt;br /&gt; &lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-976823477415116154?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/976823477415116154/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=976823477415116154' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/976823477415116154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/976823477415116154'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/11/rails-factorygirl-and-bioinformatics.html' title='Rails, Factory_girl and Bioinformatics - a gotcha'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-2595669195159199461</id><published>2010-10-27T15:13:00.000-07:00</published><updated>2010-10-27T15:42:20.218-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Rails3'/><category scheme='http://www.blogger.com/atom/ns#' term='searchlogic'/><category scheme='http://www.blogger.com/atom/ns#' term='metasearch'/><title type='text'>Searchlogic versus MetaSearch and Rails3</title><content type='html'>&lt;a href="http://github.com/binarylogic/searchlogic"&gt;Searchlogic&lt;/a&gt; is a great Rails gem for basic searching of your tables. I've used it for quite a while now. Problem is that at the time of writing (October 2010) it does not work with Rails3.&lt;br /&gt;&lt;br /&gt;You can install it just fine but starting up your server will produce and error like this:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;/Users/jones/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.1/lib/active_support/core_ext/module/aliasing.rb:31:in `alias_method': undefined method `merge_joins' for class `Class' (NameError)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;What to do? Well there is an alternative search gem called &lt;a href="http://github.com/ernie/meta_search"&gt;MetaSearch&lt;/a&gt; that has a very similar interface to Searchlogic and which does work with Rails3. In fact it may be a little better.&lt;br /&gt;&lt;br /&gt;In my code I have search code in three places - the index action of my controllers, a search form at the top of my index view pages and column headers on my index view pages that will reorder the matching rows when I click on them.&lt;br /&gt;&lt;br /&gt;So here are the three code blocks in Searchlogic and then MetaSearch (with a very simple model where I'm simple searching the name column). Note that I'm using will_paginate in both cases.&lt;br /&gt;&lt;br /&gt;Controller Index Action&lt;br /&gt;&lt;br /&gt;Searchlogic&lt;br /&gt;&lt;pre&gt;&lt;code&gt;  def index&lt;br /&gt;    @search = Product.search(params[:search])&lt;br /&gt;    @search.order ||= :ascend_by_name&lt;br /&gt;    @products = @search.all.paginate :page =&amp;gt; params[:page], :per_page =&gt; 20&lt;br /&gt;  end&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;MetaSearch&lt;br /&gt;&lt;pre&gt;&lt;code&gt;  def index&lt;br /&gt;    @search = Product.search(params[:search])&lt;br /&gt;    @search.meta_sort ||= 'name.asc'&lt;br /&gt;    @products = @search.all.paginate :page =&amp;gt; params[:page], :per_page =&gt; 20&lt;br /&gt;  end&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;View Index Page Search Form (omitting some of the html formatting)&lt;br /&gt;&lt;br /&gt;Searchlogic&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;% form_for @search do |f| %&amp;gt;&lt;br /&gt;&amp;lt;p&amp;gt;SEARCH&amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;p&amp;gt;&amp;lt;%= f.label :name_like, 'Name' %&amp;gt;&lt;br /&gt;&amp;lt;%= f.text_field :title_like, :size =&amp;gt; 15 %&amp;gt;&lt;br /&gt;&amp;lt;%= f.submit "SEARCH" %&amp;gt;&lt;br /&gt;&amp;lt;%= @search.count %&amp;gt;Matches&amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;% end %&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;MetaSearch - NO CHANGE!&lt;br /&gt;&lt;br /&gt;View Index Page Column Headers (just showing a single column header)&lt;br /&gt;&lt;br /&gt;Searchlogic&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;%= order @search, :by =&gt; 'name', :as =&gt; 'name'.humanize %&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;MetaSearch&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;%= sort_link @search, 'name', 'name'.upcase %&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;All in all, a pretty straightforward replacement.&lt;br /&gt;&lt;br /&gt;But there is at least on additional bonus, over and about working with Rails3. 'attr_searchable' and 'assoc_searchable' allow you to specify in your models exactly which fields can and cannot be searched. Searching in either Searchlogic or MetaSearch uses GET requests which display the search parameters in the URL in the browser. That opens the door to people trying out other likely field names and searching otherwise private data. This mechanism provides a way to limit that problem.&lt;br /&gt;&lt;br /&gt;I have no doubt that searchlogic will get updated soon, as so many people use it. But until then MetaSearch is the way to go.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-2595669195159199461?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/2595669195159199461/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=2595669195159199461' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/2595669195159199461'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/2595669195159199461'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/10/searchlogic-versus-metasearch-and.html' title='Searchlogic versus MetaSearch and Rails3'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-5640867810059685062</id><published>2010-10-22T11:14:00.000-07:00</published><updated>2011-02-14T13:31:20.942-08:00</updated><title type='text'>Passenger 3, nginx and rvm on Mac OS X 10.6</title><content type='html'>I wanted to set up the web server &lt;a href="http://nginx.org/"&gt;nginx&lt;/a&gt;, an alternative to Apache, along with &lt;a href="http://www.modrails.com/"&gt;Phusion Passenger&lt;/a&gt; on my Mac. I've become a convert to &lt;a href="http://rvm.beginrescueend.com/"&gt;RVM&lt;/a&gt; as a way to manage multiple versions of Ruby so I needed to setup Passenger (a Ruby gem) through RVM. Whenever you have a combination like that you can run into installation problems. &lt;br /&gt;&lt;br /&gt;Here are the steps that I used (after a couple of false starts):&lt;br /&gt;&lt;br /&gt;1. Make sure your rvm setup is working correctly. In particular I've found it best to ignore your system Ruby installation completely and in fact I install the system version (currently 1.8.7) separately under rvm and make that my rvm default. You have to reinstall your gems, a pain, but I think it the way to go - everything lives under rvm.&lt;br /&gt;&lt;br /&gt;2. Do not install nginx! Passenger will do that for you. If you already have an installation then rename it or just ignore it.&lt;br /&gt;&lt;br /&gt;3. Turn off Apache or Nginx if you have either of them running. &lt;br /&gt;&lt;br /&gt;4. Put yourself into your default Ruby and install the Passenger gem&lt;br /&gt;&lt;pre class="brush: bash;"&gt;$ rvm default&lt;br /&gt;$ gem install passenger&lt;/pre&gt;&lt;br /&gt;5. Run passenger-install-nginx-module with rvmsudo&lt;br /&gt;&lt;br /&gt;Very important - don't use regular sudo - if you do it will complain about not finding the current gemset.&lt;br /&gt;&lt;pre class="brush: bash;"&gt;$ rvmsudo passenger-install-nginx-module&lt;/pre&gt;The script will ask you if you want a default installation or a custom/advanced on. I just did the default (option 1).&lt;br /&gt;&lt;br /&gt;The script downloads and compiles nginx. It will ask you where you want it installed. I suggest /usr/local/nginx. Don't just say /usr/local as that will create conf, html and logs directory right in /usr/local. You really want these in a nginx specific directory.&lt;br /&gt;&lt;br /&gt;All being well the compilation and installation will go smoothly and your fresh installation of nginx will be modified for use with passenger.&lt;br /&gt;&lt;br /&gt;If I remember the installation correctly it actually fires up nginx and leaves it running. Check that with 'ps ax | grep nginx'&lt;br /&gt;&lt;br /&gt;6. Go to your browser. &lt;br /&gt;'http://localhost' should give a 'welcome to nginx' page. Look in /usr/local/nginx/logs/ for logging output.&lt;br /&gt;&lt;br /&gt;7. Configuration&lt;br /&gt;&lt;br /&gt;I set up a symlink in /usr/local/sbin to the nginx binary so that it can be found in my regular PATH&lt;br /&gt;&lt;pre class="brush: bash;"&gt;$ sudo ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/nginx&lt;/pre&gt;&lt;br /&gt;You start nginx with 'sudo nginx' and shut it down with 'sudo killall nginx'. It needs to be run via sudo. &lt;br /&gt;&lt;br /&gt;Configuring nginx is done in /usr/local/nginx/conf/nginx.conf and if you are used to Apache config files this will be a breath of fresh air. The main changes I made from the default was to set myself as the 'user' and set the worker_processes to 2.&lt;br /&gt;&lt;br /&gt;To set up a Rails application simply add a server block like this:&lt;br /&gt;&lt;pre class="brush: plain;"&gt;server {&lt;br /&gt;listen 80;&lt;br /&gt;server_name myapp.local;&lt;br /&gt;root /Users/jones/Documents/myapp/public;&lt;br /&gt;passenger_enabled on;&lt;br /&gt;rails_env development;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Be sure to set the rails_env unless you are in production (the default) otherwise it will not work. Restart nginx and with any luck you'll be able to access your application.&lt;br /&gt;&lt;br /&gt;I made a few missteps doing my installation - such as thinking I needed to install nginx myself - but overall this went very smoothly.&lt;br /&gt;&lt;br /&gt;8. Extra credit&lt;br /&gt;&lt;br /&gt;If you want to use rvm and passenger to run multiple apps with multiple versions of Ruby then you will want to look at this post by Phusion:&lt;br /&gt;&lt;a href="http://blog.phusion.nl/2010/09/21/phusion-passenger-running-multiple-ruby-versions/"&gt;http://blog.phusion.nl/2010/09/21/phusion-passenger-running-multiple-ruby-versions/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As you see it can get really complicated, but as a way to migrate a Rails app from 2.x to 3.x and/or Ruby 1.8.x to 1.9.x, this seems like the way to go.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-5640867810059685062?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/5640867810059685062/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=5640867810059685062' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5640867810059685062'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5640867810059685062'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/10/passenger-3-nginx-and-rvm-on-mac-os-x.html' title='Passenger 3, nginx and rvm on Mac OS X 10.6'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-4813941937285551954</id><published>2010-10-21T08:20:00.000-07:00</published><updated>2010-10-21T08:35:35.237-07:00</updated><title type='text'>Setting Environment Variables for Sudo on Mac OS X</title><content type='html'>On Mac OS X you typically set up Unix environment variables in your ~/.bashrc or ~/.bash_profile files. To perform actions that need Root privileges you use 'sudo' instead of 'su'.&lt;br /&gt;&lt;br /&gt;But when you 'sudo' a command your environment does not pick up your entire user environment and can cause problems in some cases.&lt;br /&gt;&lt;br /&gt;To illustrate the issue, compare the output of these two commands in a Terminal (Unix shell):&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ printenv&lt;br /&gt;$ sudo printenv&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;So how do you make a custom Environment variable visible to sudo? Rather than trying to modify system wide files like /etc/profile (which may not work anyway...) you want to modify the file /etc/sudoers.&lt;br /&gt;&lt;br /&gt;Now, to modify this file you want to use the special command 'visudo', which as you can surmise, is a version of the editor 'vi'. Specifically it knows which file to edit and how to set the permissions on it. NOTE: If you don't know how to edit a file with 'vi' then learn the basics BEFORE you try the following steps!&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ sudo visudo&lt;/pre&gt;&lt;/code&gt; will bring the editor with the file opened. Look for this section:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;# Defaults specification&lt;br /&gt;Defaults        env_reset&lt;br /&gt;Defaults        env_keep += "BLOCKSIZE"&lt;br /&gt;Defaults        env_keep += "COLORFGBG COLORTERM"&lt;br /&gt;[...]&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;The env_keep lines indicate that the named environment variable should be made available to sudo. So you want to add your custom variable to this list by adding lines like this at the end of this section:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;Defaults        env_keep += "APXS2"&lt;/pre&gt;&lt;/code&gt;And I would suggest adding a comment line (preceded by a # character) that makes it clear that this is a custom change. Save the file and look at the output of sudo printenv:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ sudo printenv&lt;br /&gt;[...]&lt;br /&gt;APXS2=/usr/sbin/apxs&lt;/pre&gt;&lt;/code&gt;Your custom environment variable should now be available.&lt;br /&gt;&lt;br/&gt; &amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-4813941937285551954?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/4813941937285551954/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=4813941937285551954' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/4813941937285551954'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/4813941937285551954'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/10/setting-environment-variables-for-sudo.html' title='Setting Environment Variables for Sudo on Mac OS X'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-5096494476252727438</id><published>2010-10-20T14:55:00.000-07:00</published><updated>2010-10-20T14:59:22.109-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby Jruby 1.5.3'/><title type='text'>Backtick operator in Jruby 1.5.3 not working</title><content type='html'>The backtick operator in Ruby (e.g. `date`) executes a system command.&lt;br /&gt;&lt;br /&gt;In Jruby 1.5.3 this is not working and in my example caused some odd side effects. This is a known issue (&lt;a href="http://jira.codehaus.org/browse/JRUBY-5133"&gt;http://jira.codehaus.org/browse/JRUBY-5133&lt;/a&gt;) that I'm sure will be fixed in the next release.&lt;br /&gt;&lt;br /&gt;For now, use Jruby 1.4.1 as backticks seem to work fine here.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-5096494476252727438?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/5096494476252727438/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=5096494476252727438' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5096494476252727438'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5096494476252727438'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/10/backtick-operator-in-jruby-153-not.html' title='Backtick operator in Jruby 1.5.3 not working'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-2561123496342585691</id><published>2010-10-20T09:09:00.000-07:00</published><updated>2010-10-21T14:57:40.277-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby rvm gem rails'/><title type='text'>rvm on Mac OS X Snow Leopard</title><content type='html'>&lt;a href="http://rvm.beginrescueend.com/"&gt;rvm, the Ruby Version Manager&lt;/a&gt;, is a great way to manage multiple Ruby versions. The documentation is extensive but I find it to be fragmented, such that if you do run into problems you have to look in multiple locations on the site to find relevant guidance.&lt;br /&gt;&lt;br /&gt;On Mac OS X 10.6 (Snow Leopard) I had not problem installing rvm or ruby 1.9.2 but it blew up on my when I tried to list the gems under 1.9.2. The solution was to install zlib under the rvm tree:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ ruby -v&lt;br /&gt;ruby 1.8.7 (2009-06-12 patchlevel 174) [i686-darwin10.2.0]&lt;br /&gt;&lt;br /&gt;$ rvm package install zlib&lt;br /&gt;$ rvm install 1.9.2 -C --with-zlib-dir=$HOME/.rvm/usr&lt;br /&gt;&lt;br /&gt;$ rvm use 1.9.2&lt;br /&gt;$ gem list&lt;br /&gt;$ gem install rails --pre&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I had a similar problem when installing ruby 1.8.7 under rvm. This time it was the readline library that was the problem. Again, if you poke around in the docs you can find a fix:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ rvm package install readline&lt;br /&gt;$ rvm install 1.8.7 -C --with-readline-dir=$HOME/.rvm/usr&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Although rvm makes it easy to switch back to your system ruby (with 'rvm system') I would strongly suggest that you do not use this. Instead, install the same release as your system ruby under rvm (1.8.7 in my case) and make that the default ('rvm --default 1.8.7').&lt;br /&gt;&lt;br /&gt;You will have to reinstall gems under that ruby installation, which is a pain, but once you have all your rubies under rvm then you should have no issues with confusion over where specific libraries are located, which has been an issue for me more than once. &lt;br /&gt;&lt;br /&gt;rvm also has a notion of gemsets, which I have not explored as yet, which allow you to isolate specific gem versions for specific applications. This could be extremely useful in migrating Rails applications to newer versions of Rails.&lt;br /&gt;&lt;br /&gt;One area where I have not yet been successful is getting rvm and passenger to work. The rvm docs explain how to do this - but no luck for me as yet.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-2561123496342585691?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/2561123496342585691/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=2561123496342585691' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/2561123496342585691'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/2561123496342585691'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/10/rvm-on-mac-os-x-snow-leopard.html' title='rvm on Mac OS X Snow Leopard'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-3078274698333580129</id><published>2010-10-19T15:45:00.000-07:00</published><updated>2010-10-19T15:53:36.858-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby logical operators'/><title type='text'>!! in Ruby</title><content type='html'>I noticed this odd looking construct in Rick Olsen's &lt;a href="http://github.com/technoweenie/restful-authentication"&gt;restful_authentication plugin&lt;/a&gt; a while back:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;!!current_user&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;At face value it appears to be a 'double not' operation on the variable current_user. But that didn't make much sense to me at the time. I wondered if it was some special Ruby operator, but I could find no reference to it.&lt;br /&gt;&lt;br /&gt;After a couple of experiments I see now that it is indeed a double not operator. It serves here as a very concise way to return true or false depending on whether the variable is nil or not. Here is how it works in an irb shell:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; foo = nil&lt;br /&gt;=&amp;gt;&amp;gt; nil&lt;br /&gt;&amp;gt;&amp;gt; !foo&lt;br /&gt;=&amp;gt;&amp;gt; true&lt;br /&gt;&amp;gt;&amp;gt; !!foo&lt;br /&gt;=&amp;gt;&amp;gt; false&lt;br /&gt;&amp;gt;&amp;gt; foo = 1&lt;br /&gt;=&amp;gt;&amp;gt; 1&lt;br /&gt;&amp;gt;&amp;gt; !foo&lt;br /&gt;=&amp;gt;&amp;gt; false&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; !!foo&lt;br /&gt;=&amp;gt;&amp;gt; true&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Concise is good, but not at the cost of being unclear. I'm on the fence about this one.&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-3078274698333580129?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/3078274698333580129/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=3078274698333580129' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3078274698333580129'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3078274698333580129'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/10/in-ruby.html' title='!! in Ruby'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-3053660282946556214</id><published>2010-10-13T12:32:00.002-07:00</published><updated>2010-10-13T12:37:14.911-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby regex'/><title type='text'>Stripping non-ASCII characters from text in Ruby</title><content type='html'>I need to get rid of occasional non-ASCII characters in otherwise plain ASCII text, such as 'curly quotes' like “ and ”. I don't know the real encoding of my source text but I can tell that the characters are encoded as hexadecimal characters such as \x94&lt;br /&gt;&lt;br /&gt;Here is the regular expression I use to remove them:&lt;br /&gt;&lt;pre&gt;str.gsub!(/[\x80-\xff]/, '')&lt;/pre&gt;&lt;br /&gt;I'm sure this won't work in many cases but with my text it does the job just fine.&lt;br /&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-3053660282946556214?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/3053660282946556214/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=3053660282946556214' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3053660282946556214'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3053660282946556214'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/10/stripping-non-ascii-characters-from.html' title='Stripping non-ASCII characters from text in Ruby'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-2124384892587773864</id><published>2010-10-11T09:49:00.000-07:00</published><updated>2010-10-11T09:57:56.029-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unix'/><category scheme='http://www.blogger.com/atom/ns#' term='path'/><category scheme='http://www.blogger.com/atom/ns#' term='&apos;mac os x&apos;'/><title type='text'>/etc/paths.d as a way to configure Paths in Mac OS X</title><content type='html'>Just found out about a simple way to manage paths to installed software in Mac OS X&lt;br /&gt;&lt;br /&gt;As well as, or instead of, setting PATH environment variables in startup files, you can simply add a path as a file to the directory /etc/paths.d&lt;br /&gt;&lt;br /&gt;For example, here is a command that sets up a path to a custom installation of MongoDB&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ sudo sh -c 'echo "/Users/jones/Documents/mypath/mongodb/bin" &amp;gt; /etc/paths.d/mongodb'&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Start up a new shell and you will find that path added to your PATH environment variable. &lt;br /&gt;&lt;br /&gt;Note that this is a system wide setting and so it gets set early in the process of shell creation. If you need to override PATH settings for specific users then you still need to set paths in .bashrc, etc. I don't know the order in which /etc/path.d files are sourced but I would assume alphabetical.&lt;br /&gt;&lt;br /&gt;Also note that you need the 'sh -c ' construct in order to create the file as shown above. Simple 'sudo echo' will not work.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-2124384892587773864?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/2124384892587773864/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=2124384892587773864' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/2124384892587773864'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/2124384892587773864'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/10/etcpathsd-as-way-to-configure-paths-in.html' title='/etc/paths.d as a way to configure Paths in Mac OS X'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-7954583769139814012</id><published>2010-09-08T07:26:00.000-07:00</published><updated>2010-09-08T07:41:25.601-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MacPymol'/><category scheme='http://www.blogger.com/atom/ns#' term='&quot;Mac OS X&quot;'/><category scheme='http://www.blogger.com/atom/ns#' term='trackball'/><title type='text'>Mouse and Trackball Setup with MacPymol</title><content type='html'>I was having problems configuring a Kensington Expert Mouse Trackball to work correctly with the &lt;a href="http://pymol.org/"&gt;MacPymol protein modeling software&lt;/a&gt; on a Mac OS X 10.6.3 Intel Mac.&lt;br /&gt;&lt;br /&gt;The Kensington mouse drivers (and specifically their &lt;a href="http://www.apple.com/downloads/macosx/drivers/kensingtonmouseworks.html"&gt;MouseWorks software&lt;/a&gt;) has not been updated for several years and they are not supporting the trackball on Mac OS X Snow Leopard. But in fact the software works... MouseWorks is a 32bit version of a Preference Pane and so Preferences will have to shift to that version before you can interact with it.&lt;br /&gt;&lt;br /&gt;But with just the trackball on that machine I was not able to configure the buttons correctly. That was the only mouse I had on that machine.&lt;br /&gt;&lt;br /&gt;I noticed references in the MacPymol docs saying that the Apple Mighty Mouse with the little ball works well with the software. Even though I don't like that mouse, I did have one lying around so I plugged that it and configured it. With following setup it works as expected with MacPymol:&lt;br /&gt;&lt;br /&gt;Left Button = Primary Button&lt;br /&gt;Ball Button = Button 3&lt;br /&gt;Right Button = Secondary Button&lt;br /&gt;&lt;br /&gt;In 3-Button Viewing Mode this setup gives you Rotation on Left Button down and drag, Zoom on Right Button down and drag and XY translation on Ball Button down and drag.&lt;br /&gt;&lt;br /&gt;Interestingly, once I had the Mighty Mouse setup like this, I could then get the Trackball working correctly. In Kensington MouseWOrks I have it set up as follows:&lt;br /&gt;Left Lower button = Click&lt;br /&gt;Right Lower Button = Right-Click&lt;br /&gt;Left Upper Button = Middle-Click&lt;br /&gt;&lt;br /&gt;MouseWorks knows about MacPymol (somehow) and you can setup MacPymol application settings - but I don't have this figured out. Unfortunately I'm not finding any more info in the MacPymol docs/wiki.&lt;br /&gt;&lt;br /&gt;Hope this is useful&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-7954583769139814012?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/7954583769139814012/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=7954583769139814012' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/7954583769139814012'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/7954583769139814012'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/09/mouse-and-trackball-setup-with-macpymol.html' title='Mouse and Trackball Setup with MacPymol'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-1826953120995957029</id><published>2010-08-26T12:14:00.000-07:00</published><updated>2010-08-26T12:25:46.137-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby terminal ANSI escape codes'/><title type='text'>Printing Colored Text in UNIX Terminals from Ruby</title><content type='html'>Outputting text in color in a UNIX console/Xterminal is kind of old school - some might say obsolete - but once in a while it is very useful. One example is the Red/Green coloring of test results. You don't get a lot of options but enough to highlight relevant text.&lt;br /&gt;&lt;br /&gt;The cryptic escape codes are explained in &lt;a href="http://en.wikipedia.org/wiki/ANSI_escape_code"&gt;this Wiki page&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;This Ruby script outputs fore and background colors and a couple of the other useful modifiers.&lt;pre&gt;&lt;code&gt;#!/usr/bin/ruby&lt;br /&gt;&lt;br /&gt;puts "\033[1mForeground Colors...\033[0m\n"&lt;br /&gt;puts "   \033[30mBlack (30)\033[0m\n"&lt;br /&gt;puts "   \033[31mRed (31)\033[0m\n"&lt;br /&gt;puts "   \033[32mGreen (32)\033[0m\n"&lt;br /&gt;puts "   \033[33mYellow (33)\033[0m\n"&lt;br /&gt;puts "   \033[34mBlue (34)\033[0m\n"&lt;br /&gt;puts "   \033[35mMagenta (35)\033[0m\n"&lt;br /&gt;puts "   \033[36mCyan (36)\033[0m\n"&lt;br /&gt;puts "   \033[37mWhite (37)\033[0m\n"&lt;br /&gt;puts ''&lt;br /&gt;&lt;br /&gt;puts "\033[1mBackground Colors...\033[0m\n"&lt;br /&gt;puts "   \033[40m\033[37mBlack (40), White Text\033[0m\n"&lt;br /&gt;puts "   \033[41mRed (41)\033[0m\n"&lt;br /&gt;puts "   \033[42mGreen (42)\033[0m\n"&lt;br /&gt;puts "   \033[43mYellow (43)\033[0m\n"&lt;br /&gt;puts "   \033[44mBlue (44)\033[0m\n"&lt;br /&gt;puts "   \033[45mMagenta (45)\033[0m\n"&lt;br /&gt;puts "   \033[46mCyan (46)\033[0m\n"&lt;br /&gt;puts "   \033[47mWhite (47)\033[0m\n"&lt;br /&gt;puts ''&lt;br /&gt;puts "\033[1mModifiers...\033[0m\n"&lt;br /&gt;puts "   Reset (0)"&lt;br /&gt;puts "   \033[1mBold (1)\033[0m\n"&lt;br /&gt;puts "   \033[4mUnderlined (4)\033[0m\n"&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Note that the exact colors will vary between different terminals. So try it and see.&lt;br /&gt;&lt;br /&gt;The script will show you enough to create your own colored terminal output. But what if you sometimes want your output to go to a terminal (TTY) and other times to a file? In the latter, all the escape codes will give you garbage characters when you view the file. The trick here is to test whether our not your script is writing to a TTY with 'STDOUT.tty?'. If so then add the escape codes, if not then leave them out.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-1826953120995957029?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/1826953120995957029/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=1826953120995957029' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/1826953120995957029'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/1826953120995957029'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/08/printing-colored-text-in-unix-terminals.html' title='Printing Colored Text in UNIX Terminals from Ruby'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-2964046241304148099</id><published>2010-08-11T10:06:00.000-07:00</published><updated>2010-08-11T10:37:27.287-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Apache SSL Certificates'/><title type='text'>SSL Certificates and Apache2</title><content type='html'>The process of generating a new or renewal SSL certificate for a web site can appear quite daunting given the terminology involved. In reality it is pretty simple. Here are the steps I used for renewing a Wildcard SSL cert, using rapidssl.com as the vendor. &lt;br /&gt;&lt;br /&gt;A wildcard certificate costs more than an single fully qualified domain name, but it lets me secure any FQDN under my main domain.&lt;br /&gt;&lt;br /&gt;The basics steps are:&lt;br /&gt;1: Generate a Key&lt;br /&gt;2: Generate a CSR (Certificate Signing Request)&lt;br /&gt;3: Send that the vendor and give them some money&lt;br /&gt;4: Receive an SSL Certificate back via email&lt;br /&gt;5: Paste that into a file on your host&lt;br /&gt;6: Restart Apache and verify operation&lt;br /&gt;&lt;br /&gt;In Detail, here are my specific steps:&lt;br /&gt;&lt;br /&gt;1: Start the new or renewal certificate process on the vendor's web site&lt;br /&gt;&lt;br /&gt;2: Create a SSL Key&lt;br /&gt;You should only need to do this once and then you can reuse it multiple times.&lt;br /&gt;Create a directory in which to create and save your SSL files. For the purposes of this tutorial I'm using 'example.com as the domain. You can put the key into any file but give it one that makes sense, i.e. example.com.key&lt;br /&gt;&lt;pre&gt;&lt;code&gt;# openssl genrsa 1024 &amp;gt; example.com.key&lt;br /&gt;Generating RSA private key, 1024 bit long modulus&lt;br /&gt;.................................++++++&lt;br /&gt;.........++++++&lt;br /&gt;e is 65537 (0x10001)&lt;/code&gt;&lt;/pre&gt;If you want to protect the key with a passphrase then add the -des3 option to the command. If you do then you need to enter the passphrase whenever your server starts up. if you do NOT then set the permissions on your files correctly (see below).&lt;br /&gt;&lt;br /&gt;3: Create a CSR (Certificate Signing Request)&lt;br /&gt;This process will ask you several questions, of which the MOST IMPORTANT is the COMMON NAME. This the Domain Name that you want the certificate for. For a single domain this might be www.example.com. For a Wildcard certificate use an asterisk in the name like *.example.com.&lt;br /&gt;&lt;br /&gt;The prompt from the openssl program is unclear when it asks for YOUR name - it wants the domain name. Clear on that, right?&lt;br /&gt;&lt;br /&gt;It also asks for a challenge password - with rapidssl.com this wasn't used, so don't worry about it. Enter the other info as appropriate for your organization.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;# openssl req -new -key ./example.com.key &amp;gt; example.com.csr&lt;br /&gt;You are about to be asked to enter information that will be incorporated&lt;br /&gt;into your certificate request.&lt;br /&gt;What you are about to enter is what is called a Distinguished Name or a DN.&lt;br /&gt;There are quite a few fields but you can leave some blank&lt;br /&gt;For some fields there will be a default value,&lt;br /&gt;If you enter '.', the field will be left blank.&lt;br /&gt;-----&lt;br /&gt;Country Name (2 letter code) [AU]:US&lt;br /&gt;State or Province Name (full name) [Some-State]:Washington&lt;br /&gt;Locality Name (eg, city) []:Seattle&lt;br /&gt;Organization Name (eg, company) [Internet Widgits Pty Ltd]:Craic Computing LLC&lt;br /&gt;Organizational Unit Name (eg, section) []:&lt;br /&gt;Common Name (eg, YOUR name) []:*.example.com&lt;br /&gt;Email Address []:youraddress@example.com&lt;br /&gt;&lt;br /&gt;Please enter the following 'extra' attributes&lt;br /&gt;to be sent with your certificate request&lt;br /&gt;A challenge password []: &lt;br /&gt;An optional company name []:&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;4: Send the CSR to your Vendor&lt;br /&gt;Cut and paste the contents of the file in full into the Vendor's web form. With rapidssl.com there is a phone verification process that you have to go through after they receive it. Basically an automated call comes through and you have to enter a confirmation code that they put on their web site. Plus you need to do the whole credit card and contact information thing on their site. It all ends with several emails back from them, one of which includes the Certificate.&lt;br /&gt;&lt;br /&gt;5: Paste the certificate into a file on your host&lt;br /&gt;Once again, choose an appropriate name, e.g. example.com.crt&lt;br /&gt;Verify the contents of the certificate file with:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;# openssl x509 -text -in example.com.crt&lt;/code&gt;&lt;/pre&gt; You will see all sorts of information.&lt;br /&gt;&lt;br /&gt;6: CHANGE THE FILE PERMISSIONS - CHANGE THEM NOW!&lt;br /&gt;&lt;pre&gt;&lt;code&gt;# chmod 400 example.com.key&lt;br /&gt;# chmod a-w example.com.crt&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;7: Setup Apache2&lt;br /&gt;Modify your configuration files so that Apache knows where to find the certificate. In my case I'm using something like this:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;  ServerName www.example.com&lt;br /&gt;  ServerAlias *.example.com&lt;br /&gt;  DocumentRoot "/path/to/my/site"&lt;br /&gt;  SSLEngine on&lt;br /&gt;  SSLOptions +StrictRequire&lt;br /&gt;  SSLCertificateFile /mnt/ssl_certs/example.com.crt&lt;br /&gt;  SSLCertificateKeyFile /mnt/ssl_certs/example.com.key&lt;br /&gt;&amp;lt;/VirtualHost&amp;gt;&lt;/code&gt;&lt;/pre&gt;You can put the certificate and key in any files you want, you just need to tell Apache where they. Your Apache configuration might be different from this.&lt;br /&gt;&lt;br /&gt;Restart apache!&lt;br /&gt;&lt;br /&gt;8: Test it out&lt;br /&gt;Go to the site in your browser. You should see a lock icon. Click on that and view the certificate details. It should all be good.&lt;br /&gt;&lt;br /&gt;9: COPY THE KEY AND CERTIFICATE FILES TO A BACKUP MACHINE - COPY THEM NOW!&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-2964046241304148099?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/2964046241304148099/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=2964046241304148099' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/2964046241304148099'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/2964046241304148099'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/08/ssl-certificates-and-apache2.html' title='SSL Certificates and Apache2'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-4035384896661184999</id><published>2010-08-06T14:10:00.000-07:00</published><updated>2010-08-06T14:11:34.778-07:00</updated><title type='text'>Maximum Fixnum value in Ruby</title><content type='html'>The Maximum Fixnum value that can be represented in Ruby is calculated as: (2**(0.size * 8 -2) -1)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-4035384896661184999?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/4035384896661184999/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=4035384896661184999' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/4035384896661184999'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/4035384896661184999'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/08/maximum-fixnum-value-in-ruby.html' title='Maximum Fixnum value in Ruby'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-5713321910940850066</id><published>2010-06-30T14:54:00.000-07:00</published><updated>2010-06-30T15:20:57.785-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails routes'/><title type='text'>Rails Routes and Models with 'Uncountable' Names</title><content type='html'>Rails follows the convention of using singular and plural forms of model names for various purposes. For example user.rb for a Model name and users_controller.rb for the controller.&lt;br /&gt;&lt;br /&gt;Every once in a while you need a model where the singular and plural forms are the same. I just ran into that with a model called 'species'. This can cause you all sorts of hurt but here is a way round it.&lt;br /&gt;&lt;br /&gt;First of all, decide if you &lt;span style="font-weight:bold;"&gt;really&lt;/span&gt; need to use that name. If you can figure out an equivalent where singular and plural forms are different then use it - much simpler... but if like me there is no good alternative then you do this:&lt;br /&gt;&lt;br /&gt;1: Tell the built-in pluralization functions to skip your name.&lt;br /&gt;&lt;br /&gt;In config/initializers/inflections.rb add this:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;ActiveSupport::Inflector.inflections do |inflect|&lt;br /&gt;  inflect.uncountable %w( species )&lt;br /&gt;end&lt;/pre&gt;&lt;/code&gt;2: Create your model, controller, table etc in the normal way using 'species' as the model name.&lt;br /&gt;&lt;br /&gt;3: In your routes.rb give the :species resource an artificial singular form:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;ActionController::Routing::Routes.draw do |map|&lt;br /&gt;  map.resources :species, :singular =&amp;gt; :species_instance&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;Doing this allows the routing magic to distinguish between singular and plural. But the downside is that you need to change a bunch of controller and view paths.&lt;br /&gt;&lt;br /&gt;4: run 'rake routes' to see what Rails expects your new routes to look like.&lt;br /&gt;&lt;br /&gt;5: In your controller, change any 'redirect_to @species' lines to 'redirect_to species_instance_path(@species)' (Should be just create and update actions).&lt;br /&gt;&lt;br /&gt;6: In your index.html.erb view change: &lt;br /&gt;&lt;code&gt;&lt;pre&gt;link_to "Show", species&lt;br /&gt;to&lt;br /&gt;link_to "Show", species_instance_path(species)&lt;/pre&gt;&lt;/code&gt;In doing so you make it explicit that you want the singular form.&lt;br /&gt;Similarly, change the following:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;"Edit", edit_species_path(species)&lt;br /&gt;becomes&lt;br /&gt;"Edit", edit_species_instance_path(species)&lt;br /&gt;&lt;br /&gt;link_to "Destroy", species ...&lt;br /&gt;becomes&lt;br /&gt;link_to "Destroy", species_instance_path(species) ...&lt;br /&gt;&lt;br /&gt;and finally&lt;br /&gt;link_to "New Species", new_species_path&lt;br /&gt;becomes&lt;br /&gt;link_to "New Species", new_species_instance_path&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;7: In your show, new and edit view pages, make similar changes. Links back to the index page can stay as 'species_path' but edit, delete and new links should be updated as shown above.&lt;br /&gt;&lt;br /&gt;It's messy, for sure, but it solves the problem and allows you to retain 'natural' names in the user interface and in the URLs that users will see.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-5713321910940850066?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/5713321910940850066/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=5713321910940850066' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5713321910940850066'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5713321910940850066'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/06/rails-routes-and-models-with.html' title='Rails Routes and Models with &apos;Uncountable&apos; Names'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-947459360275519709</id><published>2010-05-11T13:58:00.000-07:00</published><updated>2010-05-11T14:06:34.184-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ghostscript'/><category scheme='http://www.blogger.com/atom/ns#' term='x86_64'/><category scheme='http://www.blogger.com/atom/ns#' term='&apos;mac os x&apos;'/><title type='text'>Compiling Ghostscript on Intel 64 bit Mac OS X</title><content type='html'>Ran into problems getting Ghostscript to compile on an Intel Mac running Snow Leopard. &lt;br /&gt;&lt;br /&gt;The error messages were telling me it was trying to compile a 32 executable, and then after fixing that it complained that libraries in /opt/local/lib were compiled for 32 bit. The thing is, except for some old mac ports stuff, I don't use /opt/local!&lt;br /&gt;&lt;br /&gt;I was able to fix compile successfully with three steps.&lt;br /&gt;&lt;br /&gt;1: Take the old /opt/local/lib code out of the picture by renaming the directory to a temporary name. I can bring it back if it turns out something actually relies on it.&lt;br /&gt;&lt;br /&gt;2: Rub ./configure with CFLAGS and LDFLAGS defined. These end up getting passed to 'make'&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ ./configure CFLAGS='-arch x86_64' LDFLAGS='-arch x86_64'&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;3: Compile it 'make' (with no flags) and install with 'sudo make install'&lt;br /&gt;&lt;br /&gt;Not sure yet if it can pick up all the fonts that it needs - we'll soon see...&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-947459360275519709?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/947459360275519709/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=947459360275519709' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/947459360275519709'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/947459360275519709'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/05/compiling-ghostscript-on-intel-64-bit.html' title='Compiling Ghostscript on Intel 64 bit Mac OS X'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-5015866736498335434</id><published>2010-05-11T11:14:00.000-07:00</published><updated>2010-05-11T11:32:03.981-07:00</updated><title type='text'>Image Resizing with Rails Paperclip and ImageMagick</title><content type='html'>The &lt;a href="http://github.com/thoughtbot/paperclip"&gt;Rails Paperclip plugin&lt;/a&gt; uses &lt;a href="http://www.imagemagick.org"&gt;ImageMagick&lt;/a&gt; for creating thumbnail images, etc.&lt;br /&gt;&lt;br /&gt;You specify the size of images using ImageMagick's Geometry syntax which can be a little confusing. Here are the aspects of that which are most useful for Paperclip users.&lt;br /&gt;&lt;br /&gt;The basic specification is &amp;lt;width&amp;gt;x&amp;lt;height&amp;gt; in pixels, optionally followed by a modifier. In some cases you can omit either width or height.&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;256x256&lt;/li&gt;&lt;br /&gt;This specifies the Maximum dimensions for the image, while preserving the aspect ratio of the image. So if your image were actually 512x256 it would be resized to 256x128 in order to fit inside the specified size.&lt;br /&gt;&lt;br /&gt;&lt;li&gt;256x256!&lt;/li&gt;&lt;br /&gt;This specifies the Exact image size, so a 512x256 image would be changed into 256x256, losing the aspect ratio.&lt;br /&gt;&lt;br /&gt;&lt;li&gt;256x&lt;/li&gt;&lt;br /&gt;This specifies the desired width of the target image, leaving the height to be set so as to preserve the aspect ratio.&lt;br /&gt;&lt;br /&gt;&lt;li&gt;x256&lt;/li&gt;&lt;br /&gt;This specifies the desired height of the target image, while preserving the aspect ratio.&lt;br /&gt;&lt;br /&gt;&lt;li&gt;256x256^&lt;/li&gt;&lt;br /&gt;This specifies the Minimum size for the target image, so the resized image may be larger than these dimensions.&lt;br /&gt;&lt;br /&gt;&lt;li&gt;256x256&amp;gt;&lt;/li&gt;&lt;br /&gt;This specifies that the image will be resized only if it is Larger than the dimensions.&lt;br /&gt;&lt;br /&gt;&lt;li&gt;256x256&amp;lt;&lt;/li&gt;&lt;br /&gt;This specifies that the image will be resized only if it is Smaller than the dimensions.&lt;br /&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Other options exist within the syntax. See the &lt;a href="http://www.imagemagick.org/RMagick/doc/imusage.html"&gt;ImageMagick docs&lt;/a&gt; for more details.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-5015866736498335434?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/5015866736498335434/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=5015866736498335434' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5015866736498335434'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5015866736498335434'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/05/image-resizing-with-rails-paperclip-and.html' title='Image Resizing with Rails Paperclip and ImageMagick'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-4975863533027761966</id><published>2010-05-10T16:37:00.000-07:00</published><updated>2010-05-10T16:46:01.384-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='paperclip'/><category scheme='http://www.blogger.com/atom/ns#' term='passenger'/><category scheme='http://www.blogger.com/atom/ns#' term='imagemagick'/><title type='text'>Rails, Paperclip and ImageMagick</title><content type='html'>Ran into trouble generating Thumbnail images using the &lt;a href="http://github.com/thoughtbot/paperclip"&gt;Paperclip&lt;/a&gt; plugin, which delegates the image manipulation to ImageMagick.&lt;br /&gt;&lt;br /&gt;The error was "Paperclip::NotIdentifiedByImageMagickError: /tmp/stream,33194,0.jpg is not recognized by the 'identify' command".&lt;br /&gt;&lt;br /&gt;A LOT of people have run into this - here is my solution.&lt;br /&gt;&lt;br /&gt;In my setup I'm on MacOSX with a binary download of ImageMagick in /usr/local/ImageMagick-6.6.1/bin and I'm running Rails under Apache/Passenger. I've got Paperclip installed as a plugin.&lt;br /&gt;&lt;br /&gt;There are 3 steps needed to get this working:&lt;br /&gt;&lt;br /&gt;1: Make sure you have ImageMagick working at the UNIX command line level. This involves adding it to your path and exporting these environment variables (pointing to your ImageMagick installation, of course)&lt;br /&gt;&lt;pre&gt;&lt;code&gt;MAGICK_HOME=/usr/local/ImageMagick-6.6.1&lt;br /&gt;DYLD_LIBRARY_PATH=/usr/local/ImageMagick-6.6.1/lib&lt;/code&gt;&lt;/pre&gt;Check that identify works with your images at the command line level. If not then fix those problems first.&lt;br /&gt;&lt;br /&gt;2: Tell Paperclip where to find the ImageMagick executables&lt;br /&gt;In config/environment.rb add this at the bottom of the file&lt;br /&gt;&lt;pre&gt;&lt;code&gt;Paperclip.options[:command_path] = "/usr/local/ImageMagick-6.6.1/bin"&lt;/code&gt;&lt;/pre&gt;At this point, after restarting Passenger, you would see that 'identify' is run from within Paperclip but is not able to identify the file...  the final step is...&lt;br /&gt;&lt;br /&gt;3: Identify needs those two exported environment variables - and Apache/Passenger (or other web servers probably) does not pass those through by default!&lt;br /&gt;In your passenger vhost file add these lines:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;SetEnv MAGICK_HOME /usr/local/ImageMagick-6.6.1&lt;br /&gt;SetEnv DYLD_LIBRARY_PATH /usr/local/ImageMagick-6.6.1/lib&lt;/code&gt;&lt;/pre&gt;Restart apache/passenger and it should work fine.&lt;br /&gt;&lt;br /&gt;For me, the binary installation of ImageMagick has worked fine so far. Compiling it yourself is a real pain (make sure you compile for x86-64 if you are on an Intel Mac) - but you don't need to do it. Likewise, you do not need the Rmagick gem if you are using Paperclip, at least for basic image resizing, etc.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&amp;nbsp;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-4975863533027761966?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/4975863533027761966/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=4975863533027761966' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/4975863533027761966'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/4975863533027761966'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/05/rails-paperclip-and-imagemagick.html' title='Rails, Paperclip and ImageMagick'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-499515039945623989</id><published>2010-04-20T09:13:00.000-07:00</published><updated>2010-04-20T09:28:35.961-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby erb rails'/><title type='text'>Suppressing newlines in Ruby ERB documents outside of Rails</title><content type='html'>In ERB files the standard &amp;lt;% ... %&amp;gt; tag pair will result in a newline being added to the output.&lt;br /&gt;&lt;br /&gt;In Rails you can add a minus sign before the closing tag to suppress this:&lt;br /&gt;&lt;br /&gt;&amp;lt;% ... -%&amp;gt;&lt;br /&gt;&lt;br /&gt;But if you use ERB outside of Rails, this will produce an ERB compile error.&lt;br /&gt;&lt;br /&gt;The way to handle this is to leave out the minus signs and instead specify the &lt;span style="color: rgb(255, 0, 0);"&gt;trim_mode&lt;/span&gt; when you create a new ERB object. There are 3 options for this parameter:&lt;br /&gt;&lt;pre&gt;    %  enables Ruby code processing for lines beginning with %&lt;br /&gt;   &amp;lt;&amp;gt; omit newline for lines starting with &amp;lt;% and ending in %&gt;&lt;br /&gt;   &amp;gt;  omit newline for lines ending in %&amp;gt;&lt;/pre&gt;&lt;br /&gt;Setting the &lt;span style="color: rgb(255, 0, 0);"&gt;trim_mode&lt;/span&gt; requires that you also set a &lt;span style="color: rgb(255, 0, 0);"&gt;safe_level&lt;/span&gt;, but this is normally set to 0. So to suppress newlines on all lines with ERB tag pairs create the ERB object like this:&lt;pre&gt;erb = ERB.new(template_file, 0, '&gt;')&lt;/pre&gt;&lt;br /&gt;This solves the newline issue for me but it would be nicer to have the per-line option available in Rails.&lt;br /&gt;&lt;br /&gt;You can also set the global trim_mode in Rails if you want to. in environment.rb:&lt;pre&gt;config.action_view.erb_trim_mode = "&amp;gt;"&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-499515039945623989?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/499515039945623989/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=499515039945623989' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/499515039945623989'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/499515039945623989'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/04/suppressing-newlines-in-ruby-erb.html' title='Suppressing newlines in Ruby ERB documents outside of Rails'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-5163926229103746842</id><published>2010-03-31T11:04:00.000-07:00</published><updated>2010-03-31T11:21:29.766-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='git'/><title type='text'>Script aliases in the style of git</title><content type='html'>The &lt;a href="http://git-scm.com/"&gt;Git&lt;/a&gt; version control software lets you run its commands either through as a single program name followed by the command as an argument (such as &lt;span style="font-family: courier new; color: rgb(255, 0, 0);"&gt;git status&lt;/span&gt;), or as individual scripts (such as &lt;span style="color: rgb(255, 0, 0); font-family: courier new;"&gt;git-status&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;The advantage of the second form is that you can use the text completion feature of your shell to save you some typing. It's a personal preference...&lt;br /&gt;&lt;br /&gt;It is implemented by a series of symlinks from the longer command names to a single git executable. git itself gets the name of the executable it was called as and breaks that down to get the name of the command.&lt;br /&gt;&lt;br /&gt;It is easy to create your own version of this. Here it is in Ruby...&lt;br /&gt;&lt;br /&gt;The 'primary' script is called myscript.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;#!/usr/bin/env ruby&lt;br /&gt;script = File.basename($0)&lt;br /&gt;if script =~ /^\S+?_(.*)$/&lt;br /&gt;  command = $1&lt;br /&gt;else&lt;br /&gt;  command = ARGV.shift&lt;br /&gt;end&lt;br /&gt;puts "command #{command}"&lt;br /&gt;&lt;br /&gt;if ARGV.length &gt; 0&lt;br /&gt;  puts "args  #{ARGV.join(', ')}"&lt;br /&gt;end&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Create an alias to it by adding a suffix (the sub command name), separated by some delimiter and symlinking this to the primary script:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ ln -s myscript myscript_cmd_0&lt;br /&gt;$ ln -s myscript myscript_cmd_1&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The script looks at how it was called ($0 in Ruby) and sees if it can split off a command. If it does then it takes any other arguments as they are presented. If you call the script as the primary script followed by a separate command then it shifts ARGV to get the command. These examples show how it works.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ ./myscript_cmd_0 foo bar&lt;br /&gt;command cmd_0&lt;br /&gt;args  foo, bar&lt;br /&gt;$ ./myscript_cmd_1 foo bar&lt;br /&gt;command cmd_1&lt;br /&gt;args  foo, bar&lt;br /&gt;$ ./myscript cmd_1 foo bar&lt;br /&gt;command cmd_1&lt;br /&gt;args  foo, bar&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You don't want to use a technique like this all the time - you end up with loads of symlinks in your bin directory, but in the right situation it can be very useful.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-5163926229103746842?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/5163926229103746842/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=5163926229103746842' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5163926229103746842'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5163926229103746842'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/03/script-aliases-in-style-of-git.html' title='Script aliases in the style of git'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-5965901521214734920</id><published>2010-03-18T12:51:00.000-07:00</published><updated>2010-03-18T13:06:50.202-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='&apos;Mac OS X&apos; PDF Preview &quot;Snow Leopard&quot;'/><title type='text'>Merging PDF Documents in Preview on Mac OS X Snow Leopard</title><content type='html'>Preview in Mac OS X is not only a viewer for PDF (and other) documents, it allows you to merge multiple PDF documents into one. This is useful for a lot of reasons, especially when you have scanned several pages of a documents into individual files and you want to combine them.&lt;br /&gt;&lt;br /&gt;In Snow Leopard the way this works has changed and, as there is no menu item for merging, it can be a little confusing.&lt;br /&gt;&lt;br /&gt;Open your first 'page' or document in Preview and open up the sidebar.&lt;br /&gt;&lt;br /&gt;If you drag a new document into the sidebar and drop it in a &lt;span style="color: rgb(255, 0, 0);"&gt;blank region&lt;/span&gt; you will see that appear in the viewing window. But this has &lt;span style="color: rgb(255, 0, 0);"&gt;not&lt;/span&gt; added this page to the first. Preview is simply allowing you to view two separate documents.&lt;br /&gt;&lt;br /&gt;To combine pages, drag and drop the second page &lt;span style="color: rgb(255, 0, 0);"&gt;on top of the first&lt;/span&gt;. The second page will appear as thumbnail in the sidebar below the first AND the two pages will appear in the same document in the main viewing window.&lt;br /&gt;&lt;br /&gt;This is confusing as both scenarios look the same in the sidebar. You can see the true document structure in the sidebar by picking one of the pages and moving it slightly as though you were reordering it. All pages in the same document will become surrounded with a border and shaded background.&lt;br /&gt;&lt;br /&gt;You can reorder pages within a document by dragging and dropping as needed and 'Save As' will save the merged document as a single file.&lt;br /&gt;&lt;br /&gt;It is a great feature of Preview but the user interface means that it is effectively hidden unless you know about it.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-5965901521214734920?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/5965901521214734920/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=5965901521214734920' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5965901521214734920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5965901521214734920'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/03/merging-pdf-documents-in-preview-on-mac.html' title='Merging PDF Documents in Preview on Mac OS X Snow Leopard'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-6520730262336332179</id><published>2010-03-11T10:14:00.000-08:00</published><updated>2010-03-11T10:23:03.154-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><category scheme='http://www.blogger.com/atom/ns#' term='raphael'/><category scheme='http://www.blogger.com/atom/ns#' term='codemirror'/><title type='text'>Raphaël Live</title><content type='html'>&lt;a href="http://raphaeljs.com"&gt;Raphaël&lt;/a&gt; is an amazing JavaScript Library for creating Vector Graphics in browsers. It was created by Dmitry Baranovskiy. It is goes further than HTML Canvas in that any object is accessible in the DOM and so can be made in to buttons, dragged around the canvas, etc. &lt;span style="color: rgb(255, 0, 0);"&gt;You need to know about it!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To help my exploration of the library I built a simple in-browser environment with a drawing canvas and  the &lt;a href="http://marijn.haverbeke.nl/codemirror/"&gt;CodeMirror&lt;/a&gt; code editor so that I could try out Raphaël calls and see the results immediately. That worked out really well for me and so today I've released a more developed version of the tool, along with a range of code examples.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://craic.com/tutorials/javascript/raphael_live/raphael_live.html"&gt;Raphaël Live&lt;/a&gt; allows you to load in code examples into the editor, run them, see the results, modify the attributes, etc., re-run them and thereby learn how to use the library.&lt;br /&gt;&lt;br /&gt;The tool is freely distributed. You can use it on the craic.com site, or download you own version from &lt;a href="http://github.com/craic/raphael_live"&gt;GitHub&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Hope that you'll check it out...&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-6520730262336332179?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/6520730262336332179/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=6520730262336332179' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/6520730262336332179'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/6520730262336332179'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/03/raphael-live.html' title='Raphaël Live'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/10916230720502332632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-3502142047796434595</id><published>2010-03-10T15:58:00.000-08:00</published><updated>2010-03-10T15:58:04.261-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='searchlogic'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><title type='text'>Rails searchlogic and confusing column names</title><content type='html'>&lt;a href="http://github.com/binarylogic/searchlogic"&gt;Searchlogic&lt;/a&gt; is a great Rails gem from Ben Johnson for adding model search capabilities to your Rails app with a minimum of effort. &lt;br /&gt;&lt;br /&gt;You can build complex queries very easily such as &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Company.name_like_or_address_like&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;But if you have column names that contain the Model name you can run into problems.&lt;br /&gt;&lt;br /&gt;For examples, let's say my Company model has columns 'company_name' and 'company_address', then my query becomes:&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Company.company_name_like_or_company_address_like&lt;/div&gt;&lt;br /&gt;It gets worse is my Person model has_one :company and I want to search companies through that model - now my query becomes&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Person.company_company_name_like_or_company_company_address_like()&lt;/div&gt;&lt;br /&gt;Not only is that ugly as sin, it may cause searchlogic to barf when you use it in a search form. &lt;br /&gt;&lt;br /&gt;My experience is that it can handle ugly queries like this when run in script/console but for some reason they may fail in the context of a real Rails app.&lt;br /&gt;&lt;br /&gt;So what can you do about it?&lt;br /&gt;&lt;br /&gt;The best solution is to change the names of your columns to remove the model names, but that is not always possible, especially in legacy databases.&lt;br /&gt;&lt;br /&gt;Failing that, you can create a named scope in your model that performs the same query but uses a shorter, more sensible name. Searchlogic will use your named scopes quite happily.&lt;br /&gt;&lt;br /&gt;In my example I would create a named scope in the Company model like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;named_scope :company_name_address_like, lambda { |name|&lt;br /&gt;  { :conditions =&amp;gt; ['company_name like ? or company_address like ?', "%#{name}%", "%#{name}%"] }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;I can then call it as &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Company.company_name_address_like().&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Don't be tempted to include 'or','and', etc. in your custom named scope names. Searchlogic appears to try and split up the scope into components based on these 'operator' words.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-3502142047796434595?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/3502142047796434595/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=3502142047796434595' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3502142047796434595'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3502142047796434595'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/03/rails-searchlogic-and-confusing-column.html' title='Rails searchlogic and confusing column names'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/13582954721486542844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_f8EIq63pOsk/SdzN4VmaUoI/AAAAAAAAAAM/lS_mySaOTlQ/S220/craic_logo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-2487024068933368222</id><published>2010-03-10T07:56:00.000-08:00</published><updated>2010-03-10T08:04:40.328-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='nokogiri'/><category scheme='http://www.blogger.com/atom/ns#' term='mac os x'/><category scheme='http://www.blogger.com/atom/ns#' term='snow leopard'/><title type='text'>Nokogiri and Snow Leopard</title><content type='html'>I'm not alone in having problems installing the &lt;a href="http://nokogiri.org/"&gt;nokogiri&lt;/a&gt; ruby gem on a Mac that has been upgraded to Snow Leopard. The problem lies in the gem not being able to find a suitable version of &lt;span style="color: rgb(255, 0, 0);"&gt;libxml2&lt;/span&gt;, despite Snow Leopard having a recent version of that library installed. (Not sure if this is by default or only if you have the developer tools installed...).&lt;br /&gt;&lt;br /&gt;People have tried various things but the place to look first is &lt;span style="color: rgb(255, 0, 0);"&gt;/opt/local/lib/xml2.*&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you have the libxml2 installed there then remove (or move) those files, along with &lt;span style="color: rgb(255, 0, 0);"&gt;/opt/local/libz.*&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Try installing the gem again (&lt;span style="color: rgb(255, 0, 0);"&gt;sudo gem install nokogiri&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;If it succeeds, you're good - &lt;span style="font-style: italic;"&gt;if not&lt;/span&gt; then try removing the libxml2 include files in /opt/local/include - try again - and if still no luck then try trawling through other directories under /opt/local.&lt;br /&gt;&lt;br /&gt;You should not have to specify the explicit libxml2 file locations with options to the gem install.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-2487024068933368222?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/2487024068933368222/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=2487024068933368222' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/2487024068933368222'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/2487024068933368222'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/03/nokogiri-and-snow-leopard.html' title='Nokogiri and Snow Leopard'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/13582954721486542844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_f8EIq63pOsk/SdzN4VmaUoI/AAAAAAAAAAM/lS_mySaOTlQ/S220/craic_logo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-8600899259979296959</id><published>2010-03-03T17:12:00.000-08:00</published><updated>2010-03-04T08:10:38.554-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git'/><title type='text'>Git - push and pull between repositories</title><content type='html'>I've been trying to improve my git skills beyond the basics. But I ran into real confusion when trying to clone one repo into another and then trying to keep them in sync using git pull and git push.&lt;br /&gt;&lt;br /&gt;In principle this should work fine but when I pushed changes back to the origin and then ran git status in the origin I would see the 'old' versions of files in the origin marked as having changed - no merge conflicts, just that they were not up to date.&lt;br /&gt;&lt;br /&gt;Turns out that you can't (easily) keep two repos in sync where the origin is a regular working copy. What you need to do is create a third repo that is a so called 'bare' repository. Bare repos only contain the contents of the .git directory and their role is simply to track changes.&lt;br /&gt;&lt;br /&gt;So here is a simple example of how to set this up:&lt;br /&gt;&lt;br /&gt;(I'm just using repos on my local machine to keep things simple)&lt;br /&gt;&lt;br /&gt;1: Create your original working directory under git and check your code in. I'll call this repo_original.&lt;br /&gt;&lt;br /&gt;2: Clone this into the bare repo with '&lt;span style="color: rgb(255, 0, 0);font-family:courier new;" &gt;git clone --bare repo_original repo_bare&lt;/span&gt;'&lt;br /&gt;(Take a look at the contents of repo_bare - it's just like a .git directory)&lt;br /&gt;&lt;br /&gt;3: Clone the bare repo into a working copy with '&lt;span style="color: rgb(255, 0, 0);font-family:courier new;" &gt;git clone repo_bare repo_1&lt;/span&gt;'&lt;br /&gt;&lt;br /&gt;4: Make a second working copy with '&lt;span style="color: rgb(255, 0, 0);font-family:courier new;" &gt;git clone repo_bare repo_2&lt;/span&gt;'&lt;br /&gt;&lt;br /&gt;5: Try making some changes in repo_1, commit them and push back to the origin (repo_bare) with '&lt;span style="color: rgb(255, 0, 0);font-family:courier new;" &gt;git push&lt;/span&gt;'&lt;br /&gt;&lt;br /&gt;6: Now go to repo_2 and pull from repo_bare with '&lt;span style="color: rgb(255, 0, 0);font-family:courier new;" &gt;git pull&lt;/span&gt;'. Look at your files and you should see the changes you made in repo_1. Try making changes in repo_2, push them, go to repo_1, pull changes and see that they came across.&lt;br /&gt;&lt;br /&gt;So far so good.&lt;br /&gt;&lt;br /&gt;7: Make conflicting changes in the same file in repo_1 and repo_2 and commit in both repos.&lt;br /&gt;&lt;br /&gt;8: Push the changes from repo_1&lt;br /&gt;&lt;br /&gt;9: Push the changes from repo_2 and you should be rejected with something like this&lt;br /&gt;&lt;pre style="color: rgb(255, 0, 0);"&gt;$ git push&lt;br /&gt;To /Users/jones/tips/repo_bare&lt;br /&gt;! [rejected]        master -&gt; master (non-fast forward)&lt;br /&gt;error: failed to push some refs to '/Users/jones/tips/repo_bare'&lt;/pre&gt;&lt;br /&gt;That's OK - there is a conflict but you can't resolve those on a bare repo, so it won't let you proceed.&lt;br /&gt;&lt;br /&gt;10: Instead, on repo_2, pull the current origin and you will see something like this:&lt;br /&gt;&lt;pre style="color: rgb(255, 0, 0);"&gt;$ git pull&lt;br /&gt;remote: Counting objects: 5, done.&lt;br /&gt;remote: Compressing objects: 100% (2/2), done.&lt;br /&gt;remote: Total 3 (delta 0), reused 0 (delta 0)&lt;br /&gt;Unpacking objects: 100% (3/3), done.&lt;br /&gt;From /Users/jones/tips/repo_bare&lt;br /&gt;0d97e7a..494885c  master     -&gt; origin/master&lt;br /&gt;Auto-merged README&lt;br /&gt;CONFLICT (content): Merge conflict in README&lt;br /&gt;Automatic merge failed; fix conflicts and then commit the result.&lt;/pre&gt;&lt;br /&gt;That's what we want to see - there is a real conflict (we created it) and we can resolve it by editing the file and committing in the normal way.&lt;br /&gt;&lt;br /&gt;So it's not difficult once you figure it out but it is not well explained in the guides that I've seen. Hope this helps.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 102, 255);"&gt;Bonus Section - Branches&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There are two ways to handle branching in repository setups like this - not sure of the official terms but I think of them as private and shared.&lt;br /&gt;&lt;br /&gt;A '&lt;span style="color: rgb(51, 102, 255);"&gt;private&lt;/span&gt;' branch is something I setup in my clone of a repo which will not get passed back to the origin repo. I create it, work in it and eventually merge it back into my repo's master. That branch will never get copied back to the origin and therefore any collaborators with their own repos will never know about it.&lt;br /&gt;&lt;br /&gt;A '&lt;span style="color: rgb(51, 102, 255);"&gt;shared&lt;/span&gt;' branch is one that I want to share with collaborators, so I need a way for them to access it. To do this, go to the origin repo, 'repo_bare' in the above example and create the branch there: '&lt;span style="color: rgb(51, 102, 255);"&gt;git branch dev&lt;/span&gt;'. When you go to a cloned repo and do a pull you will see that new branch pulled over and '&lt;span style="color: rgb(51, 102, 255);"&gt;git branch -a&lt;/span&gt;' will how it listed as 'origin/dev' but when you try to check it out you'll get an error.&lt;br /&gt;&lt;pre&gt;$ git co dev&lt;br /&gt;error: pathspec 'dev' did not match any file(s) known to git.&lt;br /&gt;Did you forget to 'git add'?&lt;br /&gt;&lt;/pre&gt;What you need to do is track this branch in each of the cloned repos. To do this, in the cloned repo, run '&lt;span style="color: rgb(51, 102, 255);"&gt;git branch --track dev origin/dev'&lt;/span&gt;. Now you can see a local branch called dev and you can checkout the branch. push and pull will now keep the tracked branch in sync as well as the master. You need to setup the tracked branch on each of the cloned repos in order to work with it.&lt;br /&gt;&lt;br /&gt;What I haven't figured out yet is how to 'promote' a private branch in a cloned repo up to a shared branch. I suspect you have to use '&lt;span style="color: rgb(51, 102, 255);"&gt;git stash&lt;/span&gt;' to stash the contents of that branch, delete the branch and then create a shared branch, track it and then put the stash back into it.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-8600899259979296959?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/8600899259979296959/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=8600899259979296959' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/8600899259979296959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/8600899259979296959'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/03/git-push-and-pull-between-repositories.html' title='Git - push and pull between repositories'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/13582954721486542844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_f8EIq63pOsk/SdzN4VmaUoI/AAAAAAAAAAM/lS_mySaOTlQ/S220/craic_logo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-6377378068946473391</id><published>2010-03-01T14:51:00.000-08:00</published><updated>2010-03-01T14:59:44.768-08:00</updated><title type='text'>Apple Numbers and CSV Files</title><content type='html'>The Mac OS X spreadsheet program 'Numbers', from Apple and part of the iWork suite, is a competitor to Microsoft Excel. There are some things about it I prefer to Excel, others where I prefer Excel.&lt;br /&gt;&lt;br /&gt;But one glaring omission in Numbers is that it will not open a Comma Separated Values (CSV) file from the Open menu. CSV files are a standard way to exchange spreadsheet datasets and not being able to load them into Numbers makes no sense.&lt;br /&gt;&lt;br /&gt;In fact there is a way to do this by Drag and Dropping the file into a worksheet.&lt;br /&gt;&lt;br /&gt;1: Your CSV file MUST have a .csv suffix - you will just copy the filename otherwise.&lt;br /&gt;2: Drag and Drop the file into a single cell of an open worksheet - choose the cell that will take the 'top left' value of your dataset.&lt;br /&gt;3: That's it - simple once you know the trick - seemingly impossible until you do...&lt;br /&gt;&lt;br /&gt;Numbers will accept tab delimited files via the Open menu option with no problems.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-6377378068946473391?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/6377378068946473391/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=6377378068946473391' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/6377378068946473391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/6377378068946473391'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/03/apple-numbers-and-csv-files.html' title='Apple Numbers and CSV Files'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/13582954721486542844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_f8EIq63pOsk/SdzN4VmaUoI/AAAAAAAAAAM/lS_mySaOTlQ/S220/craic_logo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-4335604212734938637</id><published>2010-02-15T13:22:00.000-08:00</published><updated>2010-02-15T13:33:45.600-08:00</updated><title type='text'>Rails check_box_tag and Rails 2.3.x</title><content type='html'>Basic HTML checkboxes have an inherent problem in that there is no explicit value passed to the server when the box is unchecked.&lt;br /&gt;&lt;br /&gt;Under Rails 2.2.2 (and thereabouts) you could circumvent this limitation with an ugly hack.&lt;br /&gt;&lt;br /&gt;If you wanted to use a check_box_tag helper in a form you had to use a had to follow it with a hidden_field_tag that contained the unchecked value. For instance:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&amp;lt;%= check_box_tag :approval_check_box, '1' %&amp;gt;&lt;br /&gt;&amp;lt;%= hidden_field_tag :approval_check_box, '0' %&amp;gt;&lt;/pre&gt;&lt;br /&gt;If the check box was not checked then value in the hidden field would be passed. Ugly, but it worked fine.&lt;br /&gt;&lt;br /&gt;But at some point in the move to Rails 2.3.x this hack was turned on its head and the construct show above will now always pass the unchecked value to the server.&lt;br /&gt;&lt;br /&gt;The fix is simple - just reverse the two lines:&lt;br /&gt;&lt;pre&gt;&amp;lt;%= hidden_field_tag :approval_check_box, '0' %&amp;gt;&lt;br /&gt;&amp;lt;%= check_box_tag :approval_check_box, '1' %&amp;gt;&lt;/pre&gt;&lt;br /&gt;The real solution if to use a check_box helper where you can explicitly specify the unchecked value, rather than a check_box_tag.&lt;br /&gt;&lt;br /&gt;I stumbled across this while updating an older app from Rails 2.2.2 to 2.3.5. It took a while to narrow the issue down to this problem. &lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-4335604212734938637?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/4335604212734938637/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=4335604212734938637' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/4335604212734938637'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/4335604212734938637'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/02/rails-checkboxtag-and-rails-23x.html' title='Rails check_box_tag and Rails 2.3.x'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/13582954721486542844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_f8EIq63pOsk/SdzN4VmaUoI/AAAAAAAAAAM/lS_mySaOTlQ/S220/craic_logo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-1512969391376342829</id><published>2010-02-10T14:06:00.000-08:00</published><updated>2010-02-10T14:16:52.844-08:00</updated><title type='text'>Rails, Time Zones and the current local time</title><content type='html'>Since version 2.1 it has been easy to handle user-specific time zones in Rails. Take a look at &lt;a href="http://railscasts.com/episodes/106-time-zones-in-rails-2-1"&gt;Railscast #106&lt;/a&gt; for details.&lt;br /&gt;&lt;br /&gt;Rails takes care of converting times in your models back and forth from local timezones and UTC in the database and it works great.&lt;br /&gt;&lt;br /&gt;But I wanted to put the &lt;b&gt;current&lt;/b&gt; local time at the bottom of each page, so that if they printed out the page they had a time stamp right there.&lt;br /&gt;&lt;br /&gt;My server is set up to with UTC as its time zone and Rails picks up on that, such that if I simply print out Time.now I get it in UTC, regardless of having set Time.zone to 'US Pacific...', which is not what I want.&lt;br /&gt;&lt;br /&gt;Because I'm not accessing the time from a database record, it doesn't apply the user specific conversion.&lt;br /&gt;&lt;br /&gt;The way to do this is to add 'in_time_zone' which forces Time to use the current Time.zone.&lt;br /&gt;&lt;br /&gt;Bottom Line:&lt;br /&gt;&lt;br /&gt;To display the current time in a user's local time zone, use &lt;span style="color: rgb(255, 0, 0);"&gt;Time.now.in_time_zone&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-1512969391376342829?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/1512969391376342829/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=1512969391376342829' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/1512969391376342829'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/1512969391376342829'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/02/rails-time-zones-and-current-local-time.html' title='Rails, Time Zones and the current local time'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/13582954721486542844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_f8EIq63pOsk/SdzN4VmaUoI/AAAAAAAAAAM/lS_mySaOTlQ/S220/craic_logo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-6812732208442795930</id><published>2010-02-03T16:17:00.000-08:00</published><updated>2010-02-03T16:24:00.776-08:00</updated><title type='text'>Rails, searchlogic and will_paginate</title><content type='html'>The searchlogic gem, for active record searching, integrates well with will_paginate, for pagination of the results in index pages, and it comes with simple helpers for setting up sortable column headers.&lt;br /&gt;&lt;br /&gt;But I had trouble setting the default sort order for the results if not filtering had taken place or if no column header had been clicked. What I found on the web was a little confusing. Here's how it works (as of Feb 2010).&lt;br /&gt;&lt;br /&gt;The model has a list of companies and I want the default search order to use their names.&lt;br /&gt;&lt;br /&gt;In your controller:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; @search = Company.search(params[:search])&lt;br /&gt; @search.order ||= :ascend_by_name&lt;br /&gt; @companies = @search.all.paginate :page =&gt; params[:page], :per_page =&gt; 20&lt;/pre&gt;   &lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;Note that you set the order in @search and leave out the :order parameter to paginate.&lt;/span&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;Simple, elegant, love it...&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-6812732208442795930?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/6812732208442795930/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=6812732208442795930' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/6812732208442795930'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/6812732208442795930'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/02/rails-searchlogic-and-willpaginate.html' title='Rails, searchlogic and will_paginate'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/13582954721486542844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_f8EIq63pOsk/SdzN4VmaUoI/AAAAAAAAAAM/lS_mySaOTlQ/S220/craic_logo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-3927325435009769020</id><published>2010-02-02T14:55:00.000-08:00</published><updated>2010-02-02T15:16:27.799-08:00</updated><title type='text'>Rails, Searchlogic and Dates</title><content type='html'>I've been using the &lt;a href="http://github.com/binarylogic/searchlogic"&gt;searchlogic&lt;/a&gt; gem from Ben Johnson and its a great way to build complex search forms for your models. &lt;a href="http://railscasts.com/episodes/176-searchlogic"&gt;Railscast #176&lt;/a&gt; is a great introduction to the topic by Ryan Bates (You can't go wrong with Railscasts!).&lt;br /&gt;&lt;br /&gt;One topic missing from the documentation is how searchlogic handles Dates, but the functionality is in there. Here is how you use it.&lt;br /&gt;&lt;br /&gt;You treat a date effectively as a number and you can use 'equals', 'gte', 'lte', etc. as comparison operators.&lt;br /&gt;&lt;br /&gt;Assuming you have a column named 'date', of type 'date' in your model, you can put something like this in your form:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;%= f.label :date, "Date" %&amp;gt;&lt;br /&gt;&amp;lt;%= f.text_field :date_gte, :size =&gt; 12 %&amp;gt; - &lt;br /&gt;&amp;lt;%= f.text_field :date_lte, :size =&gt; 12 %&amp;gt;&lt;/pre&gt;&lt;br /&gt;You can then enter dates into one or both of the fields to retrieve records that fall into that date range.&lt;br /&gt;&lt;br /&gt;But what date format should you use? This is where it gets clever. It wants to use YYYY-MM-DD format but if you enter MM/DD/YYYY it accepts is and converts it for you. Brilliant! It even takes text like 'Dec 1 2009' and converts that. Interestingly it won't accept invalid dates like '2009-11-31' and just gives you back the form with the field cleared out.&lt;br /&gt;&lt;br /&gt;With a column of type 'Datetime' it converts your entries as well but this time it converts '2010-01-01' into 'Fri Jan 01 00:00:00 -0800 2010'. I'm sure it does something similar with columns of type 'Time'.&lt;br /&gt;&lt;br /&gt;Undoubtedly the code is leveraging the Ruby time and date libraries to make the conversions, which can be lifesavers. Incorporating the functionality into searchlogic makes your forms much more tolerant of user inputs and it does so in a totally unobtrusive way.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-3927325435009769020?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/3927325435009769020/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=3927325435009769020' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3927325435009769020'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/3927325435009769020'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2010/02/rails-searchlogic-and-dates.html' title='Rails, Searchlogic and Dates'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/13582954721486542844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_f8EIq63pOsk/SdzN4VmaUoI/AAAAAAAAAAM/lS_mySaOTlQ/S220/craic_logo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-746182749564393693</id><published>2009-12-17T11:14:00.000-08:00</published><updated>2009-12-17T11:36:08.155-08:00</updated><title type='text'>Creating a Mail Merge from Contacts in Highrise</title><content type='html'>I've started using &lt;a href="http://highrisehq.com"&gt;Highrise&lt;/a&gt; from 37 Signals to manage sales prospects for the &lt;a href="http://sqipdb.com"&gt;SQIP Patent Sequence Database&lt;/a&gt;. My requirements for a CRM system are pretty basic. Highrise fits the bill for now, but it's OK - not great.&lt;br /&gt;&lt;br /&gt;One glaring problem for me is that I want to create a file of all contacts and their addresses for a physical mailing. In Highrise I record the address for each Company and then just record the company for each Person. When you dump your contacts out as a CSV file 'Person' records do not inherit the address of the linked Company... &lt;span style="font-style: italic;"&gt;really, it doesn't...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So I wrote a Ruby script to create what I want from the CSV file. You can find that here:  &lt;a href="http://gist.github.com/258950"&gt;http://gist.github.com/258950&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;1. Dump your contacts from Highrise&lt;br /&gt;2. Run the script on that file&lt;br /&gt;&lt;code&gt;$ ./merge_highrise_contacts.rb contacts.csv &gt; mail_merge.csv&lt;/code&gt;&lt;br /&gt;3. Load the output file into Excel or Numbers (09)&lt;br /&gt;4. Save as a Worksheet&lt;br /&gt;5. Follow the regular Mail Merge instructions for MS Word/Excel or Apple Pages/Numbers&lt;br /&gt;&lt;br /&gt;You need the '09 version of Pages/Numbers to do a proper Mail Merge. I prefer Numbers to Excel for this as it handles international characters properly, which I need.&lt;br /&gt;&lt;br /&gt;In Numbers you need to designate the Header line as such by selecting 'Convert to Header Row' from the pull down menu on the row 1 label.&lt;br /&gt;&lt;br /&gt;I'm all for the 37 Signals 'Keep things simple' approach but there are features that are just too widely used to ignore. Not being able to build a mailing list is one. Not having Prefix and Suffix for Person records is another.&lt;br /&gt;&lt;br /&gt;Many of my contacts have doctorates and I want to record the prefix 'Dr.' for those that do. The only way I can do that in Highrise is to include it in the First Name. This is a pain.&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-746182749564393693?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/746182749564393693/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=746182749564393693' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/746182749564393693'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/746182749564393693'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2009/12/creating-mail-merge-from-contacts-in.html' title='Creating a Mail Merge from Contacts in Highrise'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/13582954721486542844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_f8EIq63pOsk/SdzN4VmaUoI/AAAAAAAAAAM/lS_mySaOTlQ/S220/craic_logo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-7995117738452207850</id><published>2009-12-16T13:47:00.000-08:00</published><updated>2009-12-16T15:01:46.857-08:00</updated><title type='text'>Screencasting on Mac OS X 10.6 Snow Leopard</title><content type='html'>I've been making several screencasts as tutorials for our &lt;a href="http://sqipdb.com/"&gt;SQIP Patent Sequence Database&lt;/a&gt; service.&lt;br /&gt;&lt;br /&gt;If, like me, you're not that familiar with video technology and terminology, the process can be confusing - which compression settings? how many frames per second? etc.&lt;br /&gt;&lt;br /&gt;With Mac OS X 10.5 (Leopard) you could do simple video editing in Quicktime Player if you upgraded to the Pro version. Ironically in Snow Leopard you can trim video clips in regular Quicktime Player, but without the flexibility and controls of the previous version - and there is no Pro version... so Snow Leopard is a step backwards. The version of iMovie in iLife 09 is great when it comes to editing clips, but is confusing in terms of exporting the finished movie.&lt;br /&gt;&lt;br /&gt;Here are the steps that I use to get from my screen to a finished screencast on a hosting service that I can embed in a web page. Its not perfect, but it works for me...&lt;br /&gt;&lt;br /&gt;Here are the main steps:&lt;br /&gt;1. Set browser to 1024 x&lt;br /&gt;2. Record screen activity and audio in iShowU&lt;br /&gt;3. Load the movie into iMovie&lt;br /&gt;4. Cut and splice together clips in iMovie&lt;br /&gt;5. Export as MPEG-4 movie (.mp4)&lt;br /&gt;6. Load into QuickTime Player and re-export as a streaming MPEG-4 file (.m4v)&lt;br /&gt;7. Upload to screencast.com&lt;br /&gt;&lt;br /&gt;I'm not going into all the details but here are the settings that work for me in each of these components:&lt;br /&gt;&lt;br /&gt;1. Set my browser to a defined size (1024 x 768)&lt;br /&gt;&lt;br /&gt;Create a bookmarklet with this string: 'javascript:window.resizeTo(1024,768)'&lt;br /&gt;&lt;br /&gt;2. Record screen activity and audio in iShowU&lt;br /&gt;&lt;br /&gt;Here are my settings - 'Apple Animation' for compression, capture size and frame rate are the most important.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_f8EIq63pOsk/SylZAvPvb1I/AAAAAAAAABQ/F2YQzFUO5vo/s1600-h/iShowU_capture_options.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 359px;" src="http://1.bp.blogspot.com/_f8EIq63pOsk/SylZAvPvb1I/AAAAAAAAABQ/F2YQzFUO5vo/s400/iShowU_capture_options.png" alt="" id="BLOGGER_PHOTO_ID_5415957896107093842" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;3. Import in to iMovie09&lt;br /&gt;&lt;br /&gt;Go to File -&gt; Import... -&gt; Movies... -&gt; Optimize video: Full - Original Size&lt;br /&gt;&lt;br /&gt;Not sure if you need to optimize video - not tried it unchecked. Importing takes a while, probably due to whatever 'optimize' involves.&lt;br /&gt;&lt;br /&gt;4. Cut clips from your raw video and add to the new movie.&lt;br /&gt;&lt;br /&gt;I'm not going into detail with this - look at the iMovie Docs. I find iMovie to be pretty easy to use once you get the hang of it. I would really like to see real time codes for the start and stop of clips and be able to set those directly, but I guess that is what Final Cut Pro is for.&lt;br /&gt;&lt;br /&gt;5. Export as MPEG-4 movie (.mp4)&lt;br /&gt;&lt;br /&gt;Here is where it can get tricky... pick the wrong settings and the output looks bad, or it takes *hours* to export, or the output file is huge... or ALL of the above!&lt;br /&gt;&lt;br /&gt;I don't have this totally figured out but here is what works for me. Note that I'm going from 1024x768 raw footage to 640x480 output.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_f8EIq63pOsk/SylcMv39PQI/AAAAAAAAABY/aVuKdSzZE-c/s1600-h/iMovie09_export_options.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 379px;" src="http://3.bp.blogspot.com/_f8EIq63pOsk/SylcMv39PQI/AAAAAAAAABY/aVuKdSzZE-c/s400/iMovie09_export_options.png" alt="" id="BLOGGER_PHOTO_ID_5415961400969084162" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;The important settings are:&lt;br /&gt;- MP4 file format&lt;br /&gt;- H.264 video format&lt;br /&gt;- image size (640 x 480 VGA)&lt;br /&gt;- IMPORTANT - frame rate - Custom - 5 frames per second (this is what you recorded the footage at)&lt;br /&gt;- don't worry about the data rate and don't worry about the Streaming tab&lt;br /&gt;- set the audio to mono&lt;br /&gt;&lt;br /&gt;In my hands a 12 minute screencast is exported in a few minutes and yields a file around 25 MB.&lt;br /&gt;&lt;br /&gt;6. Load into QuickTime Player and re-export as a streaming MPEG-4 file (.m4v)&lt;br /&gt;&lt;br /&gt;Without this step, your users have to wait to download the entire file before they can start viewing. You must be able to do this within iMovie but I haven't figured it out yet.&lt;br /&gt;&lt;br /&gt;First of all, view your .mp4 movie in Quicktime Player to make sure it works the way you want.&lt;br /&gt;&lt;br /&gt;Then go File -&gt; Save for Web... and Export versions for Computer (and iPhone if you want) - then 'Save'.&lt;br /&gt;&lt;br /&gt;This will create a folder with several files - all I care about is the .m4v, but view the .html file for links and more info. Open the .m4v file in Quicktime Player to check that it is the same as the .mp4. Compare the files sizes - the .m4v may actually be larger than the .mp4.&lt;br /&gt;&lt;br /&gt;7. Upload to screencast.com&lt;br /&gt;&lt;br /&gt;I use &lt;a href="http://screencast.com"&gt;screencast.com&lt;/a&gt; to host my screencasts. You can get a free account, which has been fine for my needs or pay a modest amount and get a much higher bandwidth limit.&lt;br /&gt;&lt;br /&gt;It works out pretty well for me, but I do run into odd issues from Firefox on the Mac - things freezing in the admin interface - seems fine from Safari.&lt;br /&gt;&lt;br /&gt;Once uploaded to screencast, look under the 'share' icon to get the code needed to embed a flash player in your own web page and try viewing the video. Having converted it to 'streaming' in the previous step you should see the video start pretty much right away while the rest of the data downloads.&lt;br /&gt;&lt;br /&gt;If you skip this step then you will be stuck with a black screen for as long as it takes to download - no progress indicator! Not sure if this is a Flash problem or a Screencast one, either way it is not good.&lt;br /&gt;&lt;br /&gt;BONUS - Title slides in iMovie&lt;br /&gt;&lt;br /&gt;I make title slides in OmniGraffle that are the size of a frame (1024 x 768) and save these as PNG files. You can add these to you iMovie project by dragging and dropping and then changing the length of time they should be visible for.&lt;br /&gt;&lt;br /&gt;But a big Gotcha for me, is that by default iMovie will try and apply a silly 'Ken Burns' transition to the slide making it grow (or shrink) slightly. This makes the text look rubbish in my examples.&lt;br /&gt;&lt;br /&gt;Click on that 'clip' and use the small 'cog wheel' pull down menu to go to 'Cropping, Ken Burns and Rotation'. Now in the video preview panel (top right), click on the 'Fit' button to make the title slide fit the frame exactly - then click 'Done'&lt;br /&gt;&lt;br /&gt;Here is an example of my screencasts embedded in a web page: &lt;a href="https://www.sqipdb.com/sqip/tutorial_new_account"&gt;Creating a New Account in SQIP&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Good Luck&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-7995117738452207850?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/7995117738452207850/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=7995117738452207850' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/7995117738452207850'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/7995117738452207850'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2009/12/screencasting-on-mac-os-x-106-snow.html' title='Screencasting on Mac OS X 10.6 Snow Leopard'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/13582954721486542844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_f8EIq63pOsk/SdzN4VmaUoI/AAAAAAAAAAM/lS_mySaOTlQ/S220/craic_logo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_f8EIq63pOsk/SylZAvPvb1I/AAAAAAAAABQ/F2YQzFUO5vo/s72-c/iShowU_capture_options.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-7336124171332075689</id><published>2009-12-16T08:15:00.001-08:00</published><updated>2009-12-16T08:26:04.195-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sqipdb.com'/><category scheme='http://www.blogger.com/atom/ns#' term='sqip'/><category scheme='http://www.blogger.com/atom/ns#' term='sequence'/><category scheme='http://www.blogger.com/atom/ns#' term='seqid'/><category scheme='http://www.blogger.com/atom/ns#' term='patent'/><category scheme='http://www.blogger.com/atom/ns#' term='craic'/><category scheme='http://www.blogger.com/atom/ns#' term='listing'/><category scheme='http://www.blogger.com/atom/ns#' term='biotech'/><title type='text'>Announcing the Launch of the SQIP Patent Sequence Database</title><content type='html'>Craic is pleased to announce the launch of a web service that we've been working on for the past couple of years.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://sqipdb.com/"&gt;SQIP&lt;/a&gt; (pronounced 'skip') is a database of DNA, RNA and Protein sequences derived from issued patents and published patent applications, along with a sophisticated interface that allows users to load their own sequences, run searches against the database, evaluate matches and then view the patents associated with those matches.&lt;br /&gt;&lt;br /&gt;It is targeted not only at biotech patent agents and attorneys, but also at business development and research staff in biotech companies.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://sqipdb.com/"&gt;SQIP&lt;/a&gt; has been built on many of the technologies that this blog has touched on. It has been a lot of work but by leveraging best-in-class software we've been able to build something that we think will change patent sequence searching.&lt;br /&gt;&lt;br /&gt;You can sign up for a free account at &lt;a href="http://sqipdb.com/"&gt;http://sqipdb.com&lt;/a&gt;. You can explore all the features of SQIP, including searches with pre-loaded sequences, at no charge. You simply pay for searches with your own searches - no annual commitment, no per-user charges, no surprises.&lt;br /&gt;&lt;br /&gt;Take a look at SQIP.&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-7336124171332075689?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/7336124171332075689/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=7336124171332075689' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/7336124171332075689'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/7336124171332075689'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2009/12/announcing-launch-of-sqip-patent.html' title='Announcing the Launch of the SQIP Patent Sequence Database'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/13582954721486542844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_f8EIq63pOsk/SdzN4VmaUoI/AAAAAAAAAAM/lS_mySaOTlQ/S220/craic_logo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-8580295484180159150</id><published>2009-12-11T11:33:00.000-08:00</published><updated>2009-12-11T12:14:17.958-08:00</updated><title type='text'>Ruby and Rails issues on Snow Leopard Upgrade</title><content type='html'>I had been holding off upgrading my MacBook to Snow Leopard as I figured there would be issues with the Ruby installation and some of the gems. I decided to go for it yesterday... yup, there were issues...&lt;br /&gt;&lt;br /&gt;Snow Leopard comes with Ruby 1.8.7 already installed so it is tempting to use that but I follow Dan Benjamin's advice and install my own versions of MySQL, Ruby and Ruby gems in /usr/local. Dan has produced a series of excellent guides on installing Rails, etc on the Mac. &lt;a href="http://hivelogic.com/articles/compiling-ruby-rubygems-and-rails-on-snow-leopard/"&gt;HERE&lt;/a&gt; and &lt;a href="http://hivelogic.com/articles/compiling-mysql-on-snow-leopard/"&gt;HERE&lt;/a&gt; for example. However, his instructions do not always work for me. Here are the steps I needed to do get my setup running on my upgraded laptop.&lt;br /&gt;&lt;br /&gt;The main issue is that you want Ruby and MySQL compiled as 64 bit applications. If you have Ruby as 32 bit and MySQL as 64 then things will break with cryptic messages.&lt;br /&gt;&lt;br /&gt;I don't like MacPorts and, although I like installing binary packages, I prefer to compile Ruby etc. That way I retain full control on installing new versions.&lt;br /&gt;&lt;br /&gt;MySQL:&lt;br /&gt;1. Follow Dan Benjamin's advice on XCode, paths, etc&lt;br /&gt;2. Dump your existing MySQL contents.&lt;br /&gt;3. Download and compile MySQL as per Dan's &lt;a href="http://hivelogic.com/articles/compiling-mysql-on-snow-leopard/"&gt;instructions&lt;/a&gt;.&lt;br /&gt;4. Load your data and check that MySQL is working as expected.&lt;br /&gt;&lt;br /&gt;Ruby:&lt;br /&gt;1. Don't compile the code as root/sudo - use sudo to run make install and gem install, but nothing else.&lt;br /&gt;2. Make a list of your currently installed gems (gem list --local &gt; gem.list)&lt;br /&gt;3. Download and compile readline-6.0 (&lt;a href="http://ftp.gnu.org/gnu/readline/"&gt;http://ftp.gnu.org/gnu/readline/&lt;/a&gt;). Supposedly you no longer need to do this, but I found it necessary.&lt;br /&gt;4. Download Ruby into a user writeable directory in /usr/local/src or ~/src&lt;br /&gt;5. Move the existing /usr/local/bin/ruby and /usr/local/lib/ruby (if you have them) - you shouldn't need to but it will make it easier to validate that the new version has been installed&lt;br /&gt;6. Run ./configure with these options&lt;span style="font-family: monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;./configure --enable-shared --enable-pthread CFLAGS=-D_XOPEN_SOURCE=1 --with-readline-dir=/usr/local&lt;/code&gt;&lt;br /&gt;7. Follow with make, sudo make install&lt;br /&gt;8. Check that you now have /usr/local/bin/ruby and check that it is compiled as as 64 bit by running 'file /usr/local/bin/ruby'. You should see '/usr/local/bin/ruby: Mach-O 64-bit executable x86_64'.&lt;br /&gt;9. Now download and install rubygems as per Dan Benjamin.&lt;br /&gt;10. Any gems that have C extensions need to be recompiled, but to be safe you should install all of them (You could copy them from your old installation but don't). I have a script for doing this which I should post.&lt;br /&gt;11. The MySQL gem is different - you want to pass the path of the mysql dir to the gem install, like this:&lt;br /&gt;&lt;code&gt;sudo gem install mysql -- --with-mysql-dir=/usr/local/mysql&lt;/code&gt;&lt;br /&gt;Note  that you should not need to specify ARCH_FLAGS or anything else, which is recommended elsewhere - not needed.&lt;br /&gt;12. Install Phusion Passenger if you are using that.&lt;br /&gt;13. Check out your Rails apps. Use 'script/console' and try some simple finds on your models.&lt;br /&gt;&lt;br /&gt;If you see this: &lt;span style="color: rgb(255, 0, 0);"&gt;NameError (uninitialized constant MysqlCompat::MysqlRes)&lt;/span&gt; it is most likely that your Ruby and/or gems are not compiled as 64 bit. You will see all sorts of posts where people have seen that error. I think most of them are the result of this mismatch.&lt;br /&gt;&lt;br /&gt;To check any executable/library just do 'file &lt;yourfile&gt;' and see if it says 32-bit or 64-bit.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-8580295484180159150?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/8580295484180159150/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=8580295484180159150' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/8580295484180159150'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/8580295484180159150'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2009/12/ruby-and-rails-issues-on-snow-leopard.html' title='Ruby and Rails issues on Snow Leopard Upgrade'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/13582954721486542844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_f8EIq63pOsk/SdzN4VmaUoI/AAAAAAAAAAM/lS_mySaOTlQ/S220/craic_logo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-5436020218293874609</id><published>2009-11-11T14:14:00.000-08:00</published><updated>2009-11-11T14:28:03.437-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='firefox'/><category scheme='http://www.blogger.com/atom/ns#' term='jetpack'/><title type='text'>Source Code for Mozilla Jetpack Features</title><content type='html'>Mozilla Labs have released &lt;a href="https://jetpack.mozillalabs.com/"&gt;Jetpack&lt;/a&gt;, an environment for writing Firefox extensions using JavaScript. It looks pretty neat and I'm interested in trying writing one myself.&lt;br /&gt;&lt;br /&gt;The best way to learn a new environment is to look at working examples and you can find a growing number of these in the Jetpack Gallery.&lt;br /&gt;&lt;br /&gt;You just &lt;a href="https://jetpack.mozillalabs.com/install.html"&gt;install Jetpack&lt;/a&gt; and then install the 'Features' that interest you and try them out.&lt;br /&gt;&lt;br /&gt;But where is the source code? It's not under the Tools menu and you can't do something simple like right-click the Feature icon in your status bar.&lt;br /&gt;&lt;br /&gt;1: Enter '&lt;a href="about:jetpack"&gt;about:jetpack&lt;/a&gt;' in the URL box&lt;br /&gt;2: This brings up a page with links to various things including a tutorial and the API reference.&lt;br /&gt;3: Click on 'Installed Features' to see a list of everything you have installed.&lt;br /&gt;4: Click on 'view source' next to each Feature to bring up the JavaScript source in a new window.&lt;br /&gt;&lt;br /&gt;I'm not a fan of too many browser extensions but some of them like Firebug, YSlow and S3Fox are invaluable. Jetpack will make it easier for folks like me to contribute new extensions.&lt;br /&gt;&lt;br /&gt;Of course this only applies to the Firefox browser...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-5436020218293874609?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/5436020218293874609/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=5436020218293874609' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5436020218293874609'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5436020218293874609'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2009/11/source-code-for-mozilla-jetpack.html' title='Source Code for Mozilla Jetpack Features'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/13582954721486542844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_f8EIq63pOsk/SdzN4VmaUoI/AAAAAAAAAAM/lS_mySaOTlQ/S220/craic_logo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-7296818288934429148</id><published>2009-10-15T12:54:00.000-07:00</published><updated>2009-10-15T13:10:32.945-07:00</updated><title type='text'>Remote Desktop Software</title><content type='html'>In the past I've used VNC as a remote desktop solution for viewing, say, a Linux desktop on a remote Mac, but I've now switched to &lt;a href="http://www.nomachine.com"&gt;NoMachine NX&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;VNC is widespread and I think most Linuxes come with it already installed. But when I tried to use it recently with a Fedora VNC server and Mac OS X VNC client (Chicken of the VNC) I was seeing performance that made it unusable.&lt;br /&gt;&lt;br /&gt;I think the problem stems from a variant of the VNC protocol or software called TightVNC and I believe the default Linux implementation uses this. Running a Tight VNC client on a Windows machine gave reasonable performance and doing the same on Mac OSX might solve the problem.&lt;br /&gt;&lt;br /&gt;Instead I decided to check out NoMachine NX, which I had heard about in the past. This is commercial software but there are free versions of the server and client available for all the main platforms.&lt;br /&gt;&lt;br /&gt;Installing the server (on Fedora) involves downloading RPMS for the client, node and server (you need all 3) and installing them:&lt;br /&gt;&lt;br /&gt;# sudo rpm -i nxclient-3.4.0-5.x86_64.rpm              &lt;br /&gt;# sudo rpm -i nxnode-3.4.0-6.x86_64.rpm                          &lt;br /&gt;# sudo rpm -i nxserver-3.4.0-8.x86_64.rpm&lt;br /&gt;&lt;br /&gt;It installs into /usr/NX by default and you start/stop the server with&lt;br /&gt;# /usr/NX/bin/nxserver --status|--start|--stop|--restart&lt;br /&gt;&lt;br /&gt;You don't need to bother with any other NX options right now. At least, not if you are accessing machines in a private network. You may need to tweak your Fedora to allow the remote client to access your desktop (I didn't have to).&lt;br /&gt;&lt;br /&gt;On the client end (Mac OS X in my case), download and install then fire up the application. It will give you a 'Connection Wizard' which is self explanatory.&lt;br /&gt;&lt;br /&gt;The session will open up an X window on your Mac and I find the performance (on a local network) to be more than adequate. With remote desktops there can be issues with the 'scope' of keystrokes - for example you can't Cmd-C some text in the Mac world and expect to Cmd-V it into a Linux app - that sort of thing.&lt;br /&gt;&lt;br /&gt;So if you want an open source solution then play around with VNC, otherwise go with NoMachine NX.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-7296818288934429148?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/7296818288934429148/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=7296818288934429148' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/7296818288934429148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/7296818288934429148'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2009/10/remote-desktop-software.html' title='Remote Desktop Software'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/13582954721486542844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_f8EIq63pOsk/SdzN4VmaUoI/AAAAAAAAAAM/lS_mySaOTlQ/S220/craic_logo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-7215332329306780491</id><published>2009-10-14T07:11:00.000-07:00</published><updated>2009-10-14T08:09:22.424-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mac laptop disk error repair'/><title type='text'>Fixing Broken Macs</title><content type='html'>If and when you need to resuscitate a Mac that won't boot up all the way, there are some commands that will save you a lot of time.&lt;br /&gt;&lt;br /&gt;If your problem is not a true hardware issue then chances are there are disk errors and so the first task is to check and repair the disks. You can boot off an install CD/DVD or one with repair tools on it, but if you are comfortable with booting UNIX machines then skip that and...&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;Boot in Single User Mode&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Hold down Command-S when you turn the machine on. You should get a gray screen which will quickly turn into a classic UNIX console with all sorts of cryptic text. At the bottom of which should be some instructions to either check the disks or to reboot in 'full' Single User Mode.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;Disk repair with fsck&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Your first step should be to run fsck, the UNIX disk checking program, with the options -fy. The 'f' forces fsck to check all available filesystems and 'y' answers Yes whenever it would ask you to approve a fix. If you skip the 'y' then you'll be sat there for hours responding to prompts.&lt;br /&gt;&lt;br /&gt;# fsck -fy&lt;br /&gt;&lt;br /&gt;That will likely produce lots of scary messages about different files. Don't sweat the details, just let fsck do its thing. Any files that it breaks were already broken by the underlying disk issue. fsck won't compound the damage, only repair most or all of it.&lt;br /&gt;&lt;br /&gt;When it finishes, run it again! There can be dependency issues with disk fixes so to play it safe just run it multiple times until it reports no new errors. Typically the first run will get them all.&lt;br /&gt;&lt;br /&gt;If you want to poke around on the filesystem then you can mount it with:&lt;br /&gt;# mount -uw /&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;Reboot the System&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you are feeling lucky then just type 'reboot' at the prompt to see if your system comes back all the way. Fingers crossed...&lt;br /&gt;&lt;br /&gt;If it doesn't then just restart the machine with Command-S as before and get back to Single User Mode.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;'Full' Single User Mode&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;At this point you are in Single User Mode but with only the basic services. You can start up a bunch more stuff with&lt;br /&gt;&lt;br /&gt;# sh /etc/rc.d&lt;br /&gt;&lt;br /&gt;You'll see a bunch more verbage on the console. Keep an eye on it to see if any services are not able to start up - important clues to your problem. You'll either get a system prompt or an error. Hit return to get the prompt if you don't see one.&lt;br /&gt;&lt;br /&gt;Now you have access to pretty much all the command line programs, man pages etc. an you are free to do untold damage to your system...&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;diskutil&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;One useful program to know about is diskutil, which is the Mac tool for messing with disks. Look at the man page for details.&lt;br /&gt;&lt;br /&gt;To see what disks the system knows about:&lt;br /&gt;# diskutil list&lt;br /&gt;&lt;br /&gt;To eject a CD/DVD in the drive (your device name may be different)&lt;br /&gt;# diskutil eject /dev/disk1&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;Zapping the PRAM&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You'll see mention about zapping the PRAM memory in the machine by starting it up while holding down Option + Command + P + R  (don't worry about Shift for the P and R). Hold them until your hear two chimes.&lt;br /&gt;&lt;br /&gt;This is easy to do - and has never had any effect on any system that I've played with...&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;Booting from a CD/DVD&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To force a boot from a CD with recovery tools on it, turn the machine on, pop the disk in and hold down the C key. You should get to a gray screen with the spinning indicator. Let go of the C key and you should get an OS install menu, or whatever you have on your CD.&lt;br /&gt;&lt;br /&gt;If a simple disk repair doesn't fix the issue then you may need to reinstall the OS from disk. Not a problem but be sure to select 'Archive and Install' in order to keep your existing files. Some might say just go for a reinstall regardless of the problem - but I would strongly suggest doing a disk repair first.&lt;br /&gt;&lt;br /&gt;Good luck with your fix.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-7215332329306780491?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/7215332329306780491/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=7215332329306780491' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/7215332329306780491'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/7215332329306780491'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2009/10/fixing-broken-macs.html' title='Fixing Broken Macs'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/13582954721486542844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_f8EIq63pOsk/SdzN4VmaUoI/AAAAAAAAAAM/lS_mySaOTlQ/S220/craic_logo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-1843427812174096666</id><published>2009-10-13T09:27:00.000-07:00</published><updated>2009-10-13T09:30:09.735-07:00</updated><title type='text'>Rails Production Environments</title><content type='html'>Two things that I always forget when working with a Rails app in production mode - without them you get the development environment.&lt;br /&gt;&lt;br /&gt;Migrations:&lt;br /&gt;$ rake db:migrate RAILS_ENV=production&lt;br /&gt;&lt;br /&gt;Console&lt;br /&gt;$ script/console production&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-1843427812174096666?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/1843427812174096666/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=1843427812174096666' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/1843427812174096666'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/1843427812174096666'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2009/10/rails-production-environments.html' title='Rails Production Environments'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/13582954721486542844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_f8EIq63pOsk/SdzN4VmaUoI/AAAAAAAAAAM/lS_mySaOTlQ/S220/craic_logo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-1005779942420074548</id><published>2009-09-15T08:53:00.000-07:00</published><updated>2009-09-15T09:10:18.484-07:00</updated><title type='text'>SHA1 Digest of an Empty String</title><content type='html'>&lt;span style="color: rgb(255, 0, 0);"&gt;The use of SHA1 digests of data as unique identifiers is the answer to &lt;/span&gt;&lt;span style="font-style: italic; color: rgb(255, 0, 0);"&gt;everything&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I know that appears to be ridiculous hyperbole, but I'll go into why I think that is the case in a longer post at some point. For now you'll have to take my word for it that using them as identifiers has simplified the inner workings of a big project tremendously. It's not just me either, the Software revision control system Git uses them as IDs for all its commits.&lt;br /&gt;&lt;br /&gt;Anyway... one issue that can arise with them is that you notice that one specific digest string occurs more frequently than others in this uniformly distributed hash space... yikes... what's going on?&lt;br /&gt;&lt;br /&gt;That digest would be &lt;span style="color: rgb(255, 0, 0);"&gt;da39a3ee5e6b4b0d3255bfef95601890afd80709&lt;/span&gt; - make a note of it!&lt;br /&gt;&lt;br /&gt;It represents the SHA1 digest of an Empty String&lt;br /&gt;&lt;br /&gt;You might want to consider adding an explicit test for that string somewhere in your code.&lt;br /&gt;&lt;br /&gt;Ideally you want a direct test for an empty string being used as an ID, but checking for this digest is a useful catch-all test.&lt;br /&gt;&lt;br /&gt;Once I realized that this digest was being generated, and realized what it represented, then I could focus in on the root cause very quickly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-1005779942420074548?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/1005779942420074548/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=1005779942420074548' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/1005779942420074548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/1005779942420074548'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2009/09/sha1-digest-of-empty-string.html' title='SHA1 Digest of an Empty String'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/13582954721486542844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_f8EIq63pOsk/SdzN4VmaUoI/AAAAAAAAAAM/lS_mySaOTlQ/S220/craic_logo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-392986009767757992</id><published>2009-08-19T16:47:00.001-07:00</published><updated>2009-08-19T16:56:26.048-07:00</updated><title type='text'>Capistrano and Environment Variables</title><content type='html'>When it works well, &lt;a href="http://www.capify.org"&gt;Capistrano&lt;/a&gt; is a great way to deploy Rails applications and take care of any remote server operations that are needed for that app.&lt;br /&gt;&lt;br /&gt;But if you run into problems it can be a bear to troubleshoot. And the documentation is not great.&lt;br /&gt;&lt;br /&gt;One issue that can catch you (or me!) unawares is the 'run' command that runs a Unix command on the remote host. I use these to symlink various files and to start up a daemon on the new deployment once that is complete.&lt;br /&gt;&lt;br /&gt;You run into a problem if any of your remote commands require access to your Unix Environment Variables. The 'run' command is executed in a minimal environment without any of these.&lt;br /&gt;&lt;br /&gt;The solution is to specify the variables that you need, such as PATH, as key/value pairs in the 'default_environment' hash in your cap deploy.rb file.&lt;br /&gt;&lt;br /&gt;For example, here are two variables defined near the top of my file:&lt;br /&gt;&lt;pre class='prettyprint'&gt;default_environment['AMAZON_ACCESS_KEY_ID'] = "YourAwsKeyHere"&lt;br /&gt;default_environment['AMAZON_SECRET_ACCESS_KEY'] = "YourSecretAccessKeyHere"&lt;/pre&gt;&lt;br /&gt;Easy enough, once you know... not at all easy if you don't know!&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-392986009767757992?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/392986009767757992/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=392986009767757992' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/392986009767757992'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/392986009767757992'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2009/08/capistrano-and-environment-variables.html' title='Capistrano and Environment Variables'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/13582954721486542844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_f8EIq63pOsk/SdzN4VmaUoI/AAAAAAAAAAM/lS_mySaOTlQ/S220/craic_logo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-1412789847309440698</id><published>2009-08-19T09:28:00.000-07:00</published><updated>2009-08-19T16:16:59.339-07:00</updated><title type='text'>Lightbox2 in a Rails App</title><content type='html'>&lt;a href="http://www.lokeshdhakar.com/projects/lightbox2"&gt;Lightbox2&lt;/a&gt;, by Lokesh Dhakar, is an excellent JavaScript script for displaying images and slide shows as overlays on a web page, triggered by clicking on a thumbnail.&lt;br /&gt;&lt;br /&gt;I wanted something like this to display screenshots in the online help for a Rails application. Overall it was pretty simple to set up, but here are some of the tweaks I needed to make.&lt;br /&gt;&lt;br /&gt;1: Lightbox2 uses prototype.js and Scriptaculous. I had those in my Rails app but I found I had to upgrade those scripts to the latest versions in order to get Lightbox2 to work.&lt;br /&gt;&lt;br /&gt;2: I had included the prototype and scriptaculous libraries using the Rails helper 'javascript_include_tag :defaults', but that alone is not sufficient. Lightbox2 needs the builder and effects scripts loaded. Lightbox2 says to use this line:&lt;br /&gt;&lt;pre class='prettyprint'&gt;&amp;lt;script type="text/javascript" src="/javascripts/scriptaculous.js?load=effects,builder"&amp;gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;And I put that right after the javascript_include_tag. This is undoubtedly duplication... I should probably just include the supporting scripts directly and leave out the Rails helper.&lt;br /&gt;&lt;br /&gt;3: As the Lightbox2 docs point out, make sure you have the four default gif image files in the right places and that they are defined correctly in lightbox.js and lightbox.css. &lt;br /&gt;&lt;br /&gt;4: Add the calls to lightbox.js and lightbox.css in your Rails layout file. Note that you have to change the paths from the example to suit Rails:&lt;br /&gt;&lt;pre class='prettyprint'&gt;&amp;lt;script type="text/javascript" src="/javascripts/lightbox.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;link rel="stylesheet" href="/stylesheets/lightbox.css" type="text/css" media="screen" /&amp;gt;&lt;/pre&gt;&lt;br /&gt;5: Now you're ready to add images and links that use Lightbox2. The idea is very simple. Take a thumbnail image img tag and place within a 'a' tag pair. Make the href of the 'a' tag point to the full size image. Importantly, in the 'a' tag add the attribute 'rel="lightbox"'. For example:&lt;br /&gt;&lt;pre class='prettyprint'&gt;&amp;lt;a href="/images/fullsize.jpg" rel="lightbox" title="Picture of a cat"&amp;gt;&amp;lt;img src="/images/thumbnail.jpg" style="border: 1px solid #808080;"&amp;gt;&amp;lt;/a&amp;gt;&lt;/pre&gt;The title attribute of the 'a' tag becomes the caption of the overlay image. In this example I have included a border on the thumbnail image. That should do it for basic operation.&lt;br /&gt;&lt;br /&gt;6: To fine tune the script you can edit lightbox.js and lightbox.css. For me the animation is too slow. You can disable the animation entirely but I preferred to just speed it up with a maximum setting of 10. I also messed with the CSS for the 'imageData' set of CSS IDs to change the font and specified a different image for the 'close' icon in the .js file.&lt;br /&gt;&lt;br /&gt;Lightbox2 is pretty slick. You can do slide shows with it as well. Hope this helps you get it integrated with Rails.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-1412789847309440698?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/1412789847309440698/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=1412789847309440698' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/1412789847309440698'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/1412789847309440698'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2009/08/lightbox2-in-rails-app.html' title='Lightbox2 in a Rails App'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/13582954721486542844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_f8EIq63pOsk/SdzN4VmaUoI/AAAAAAAAAAM/lS_mySaOTlQ/S220/craic_logo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-655485046668756623</id><published>2009-08-17T14:01:00.000-07:00</published><updated>2009-08-17T14:08:15.081-07:00</updated><title type='text'>Configuring SSL on an AWS EC2 instance - Security Groups</title><content type='html'>If you are trying to set up SSL with Apache (or any other server) on an AWS EC2 instance then before you do anything else, &lt;span style="color: rgb(255, 0, 0);"&gt;add port 443 to your Security Group&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Until you do that absolutely &lt;span style="color: rgb(255, 0, 0);"&gt;NOTHING&lt;/span&gt; will work!&lt;br /&gt;&lt;br /&gt;You typically set up a Security Group when you create your EC2 account and then forget about them - I know I did...&lt;br /&gt;&lt;br /&gt;You can see what ports you have open with this command:&lt;br /&gt;&lt;pre class="prettyprint"&gt;$ ec2-describe-group&lt;/pre&gt;And you open up Port 443 with this command ('default' is the name of my security group):&lt;br /&gt;&lt;pre class="prettyprint"&gt;$ ec2-authorize -p 443 default&lt;/pre&gt;&lt;br /&gt;I hope to write more on troubleshooting SSL set ups shortly.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-655485046668756623?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/655485046668756623/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=655485046668756623' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/655485046668756623'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/655485046668756623'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2009/08/configuring-ssl-on-aws-ec2-instance.html' title='Configuring SSL on an AWS EC2 instance - Security Groups'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/13582954721486542844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_f8EIq63pOsk/SdzN4VmaUoI/AAAAAAAAAAM/lS_mySaOTlQ/S220/craic_logo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7975027231082637331.post-5724467509310581187</id><published>2009-08-12T13:53:00.000-07:00</published><updated>2009-08-12T14:08:21.002-07:00</updated><title type='text'>AWS EBS Volumes and Snapshots</title><content type='html'>AWS Elastic Block Store Volumes are invaluable for setting up EC2 nodes.&lt;br /&gt;&lt;br /&gt;You can clone and/or backup Volumes into static Snapshots, also extremely useful. But be aware that the process of creating a Snapshot can be &lt;span style="color: rgb(255, 0, 0);"&gt;extremely slow&lt;/span&gt; and this can be a major problem if you are not expecting the delay.&lt;br /&gt;&lt;br /&gt;For example, creating a snapshot from a &lt;span style="color: rgb(255, 0, 0);"&gt;50GB&lt;/span&gt; volume took almost &lt;span style="color: rgb(255, 0, 0);"&gt;2 hours&lt;/span&gt; for me today. Now, times will vary for all sorts of reasons. Most importantly, the first time you create a snapshot off a given volume will take the longest. Subsequent snapshots are just recording the changes since the previous one.&lt;br /&gt;&lt;br /&gt;Being prevented from using your Volume for an extended period of time can be a huge problem, so plan ahead and make your snapshots overnight, for example.&lt;br /&gt;&lt;br /&gt;Having said that, if your Volume contains &lt;span style="color: rgb(255, 0, 0);"&gt;Static&lt;/span&gt; or Read-Only data, then you have more flexibility:&lt;br /&gt;- You can create a Snapshot from a mounted Volume, without having unmount or detach&lt;br /&gt;- You can mount an unmounted Volume that is in the process of Snapshot creation.&lt;br /&gt;&lt;br /&gt;This is convenient and does not appear to be explicit in the AWS docs, as far as I can see.&lt;br /&gt;But this is limited to Volumes that will not change during snapshot creation.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;WARNING: DO NOT try this with a Volume that is being written to, such as one holding a database.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7975027231082637331-5724467509310581187?l=craiccomputing.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craiccomputing.blogspot.com/feeds/5724467509310581187/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7975027231082637331&amp;postID=5724467509310581187' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5724467509310581187'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7975027231082637331/posts/default/5724467509310581187'/><link rel='alternate' type='text/html' href='http://craiccomputing.blogspot.com/2009/08/aws-ebs-volumes-and-snapshots.html' title='AWS EBS Volumes and Snapshots'/><author><name>Robert Jones</name><uri>http://www.blogger.com/profile/13582954721486542844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_f8EIq63pOsk/SdzN4VmaUoI/AAAAAAAAAAM/lS_mySaOTlQ/S220/craic_logo.jpg'/></author><thr:total>0</thr:total></entry></feed>
