Programming

Rails Chronicles – Part 2

July 9th, 2011    1 Comment

Before you read any further: This is the second in a series of posts intended to capture how I went about learning how to create Web apps using Rails. I thought it might be interesting to look back in a few months and see all the things I got wrong and didn’t understand about Ruby and Rails when I started out. So, if you’re looking for enlightenment about Rails, you’re in the wrong place. I’d recommend you head over to Michael Hartl’s Ruby on Rails Tutorial: that’s the site that really got me started.

Test first

Chapter 3 of Michael Hartl’s Rails Tutorial introduces you to testing within Rails development. I’ve known about test-driven development (TDD) for a long time, but I’ve never actually done it. So I was looking forward to finding out how you write tests for something you’ve not built yet.

To be honest, not only have I never written tests before writing the code, I’ve never written tests full stop. In all my years of writing software programs (I wrote my first program, in BASIC, in 1989, then worked my way through C, Visual Basic for Applications, JavaScript, Perl and PHP) I’ve never actually written a test in software to test software I’ve written. So, this feels like a step up from my hacky habits towards a modicum of semi-professional rigour.

RSpec

RSpec (the R is for Ruby, Spec for Specification) is a Ruby package that lets you use a simple grammar to create specifications for software you intend to build. You can then test the software against the specification. The process goes something like this:

  • You write a test. This test describes the behavior of a small element of your system.
  • You run the test. The test fails because you have not yet built the code for that part of your system. This important step tests your test case, verifying that your test case fails when it should.
  • You write enough code to make the test pass.
  • You run the tests and verify that they pass.

The above is from Behavior-driven testing with RSpec by Bruce Tate, which is a good tutorial on RSpec if you want to stray from Michael Hartl’s tutorial for a while.

Fixing the ANSICON warning

When I ran the RSpec tests for the first time (section 3.2.2 of the Rails Tutorial):

$ bundle exec rspec spec/

it worked but the output text included the message:

 *** WARNING: You must use ANSICON 1.31 or higher (http://adoxa.110mb.com/ansicon) to get coloured
 output on Windows

This sounds serious but it only means your console (in my case MINGW32 running bash – which came when I installed git from GitHub) isn’t displaying the colours it could be displaying.

If you want to fix this:

  1. Go to http://adoxa.110mb.com/ansicon/ and download ANSICON 1.40.
  2. Unzip the downloaded zip file.
  3. Open a command console as Administrator (i.e. type cmd into the start menu, right-click cmd.exe and choose Run as Administrator).
  4. cd to the location of the unzipped files
  5. You’ll find subdirectories called x86 and x64. On a 32-bit machine go into the x86 directory. On a 64-bit machine go into the x64 directory.
  6. If you want to see command syntax enter:

    ansicon.exe -h

  7. To install ANSICON, enter:

    ansicon.exe -i

Autotest and Growl

The tutorial describes using Autotest and Growl to run tests and notify you when your test completes by displaying a summary of the test results. The good thing about using Growl is that, you can kick off a suite of tests and then go away and do other things in Windows while the tests run. When they finish, a message is displayed on top of all other windows.

I’m still pretty hazy about exactly what Autotest does and doesn’t do. As its name suggests it obviously runs tests automatically, but I’ve yet to figure out why tests get triggered when you save changes to some files but not others. However, it’s very handy for something to be sitting waiting for you to change certain files and, when you do, checking the file to make sure you haven’t contravened any of the definitions in your specification. You do this by opening a dedicated console window, entering:

$ autotest

and then just leaving the window open in the background so that the autotest process keeps running and will run your tests as you work on your Rails project.

I set up Growl by following Michael Hartl’s instructions (plus the instructions he cross-refers to for Windows users):

$ gem install autotest -v 4.4.6 $ gem install autotest-rails-pure -v 4.1.2 $ gem install autotest-standalone $ gem install autotest-growl

Download and install Growl for Windows from:

http://www.growlforwindows.com/gfw/ 

Create a .autotest file as follows:

$ gvim ~/.autotest

Containing the single line of text:

require 'autotest/growl'

Of course if you want to use Growl to notify you the results of tests you’ve got to start it first. In Windows 7 just enter growl in the Start menu search box and then press Enter when Windows finds the Growl program. I suppose if you were working on Ruby all the time and regularly running tests you could set up Growl to start automatically when Windows starts.

When you start Growl it displays a message telling you it’s running, but that’s all it does. It’s just waiting for a notification to display. Growl lives in the system tray. You can click it and change the setup options:

growl1

growl2

I’m not entirely sure what added Autotest to the list of applications. It wasn’t there at first but one of the command-line commands must have added it.

After setting up Growl when you start Autotest:

$ autotest

and your tests complete you get a sound and a visual notification telling you whether your tests passes or failed. I chose the notification style called Visor which slides down from the top of the screen:

growl-autotest-notification

No DRb server is running

If, when you run autotest (or when you just run bin/rspec spec), you get:

No DRb server is running. Running in local process instead ...

it means Spork isn’t running.

Spork is a gem that you put into the Gemfile for your project. It contains a Distributed Ruby (DRb) server that enables Ruby programs to work with other Ruby programs by sending/receiving messages via the DRb server. So one Ruby program can use a method that’s defined in another Ruby program running on the same computer, or on a computer somewhere else on the network.

More about Distrubuted Ruby here: http://ruby.about.com/od/advancedruby/a/drb.htm

You need to associate your Ruby program with Spork. The setup instructions for Spork are described in the tutorial here: http://ruby.railstutorial.org/chapters/static-pages#sec:spork

To start Spork, open a new console window for the purpose, navigate to your project directory and enter:

$ bundle exec spork

You can then go back to your other console window and run autotest and it should complete the tests in less time, because it’s not having to load so much stuff (Spork has preloaded that stuff and is sitting waiting for connections).

Switching Web server from WEBrick to thin

Rails comes with the lightweight WEBrick Web server that you can use for testing pages – as described in the Rails Tutorial. However, I had a few odd little niggles with it, and it seemed very slow, so I switched to using an alternative called “thin”. To do this you need to install the eventmachine and thin gems.

Note: You need a particular version of eventmachine for thin on Windows.

  1. At the command line, change directories to your project directory.
  2. Edit the Gemfile file within the project directory to:

    group :development do   …   gem 'eventmachine', '1.0.0.beta.2'   gem 'thin' end

  3. Then run:

    $ bundle install

  4. You can then start the server like this:

    $ rails s thin

    Or, to redirect it’s output to a file and detach the process from the bash shell:

    $ rails s thin >> thin_output_log.txt &

Solving the ssh.exe problem

After initially using GitHub without any problems, when I tried to update GitHub a few days later I discovered that this was no longer working.

Whenever I tried to do anything involving a connection to GitHub – even just ssh git@github.com – I got a message saying: ssh.exe has stopped working.

ssh-stopped-working

After much fruitless Googling, uninstalling and reinstalling Git for Windows, disabling anti-virus, etc. I finally discovered the fix, which is to set the file properties of ssh.exe and ssh-keygen.exe (in the Git/bin directory) so that they run in either Windows XP or Vista compatibility mode (either will do).

compatibility-mode

I presume this is because I’m running 64-bit Windows 7. But I’ve no idea why it worked fine when I installed it initially.

Bizarrely, after restarting Windows I seem to have to go through this process again, even though the settings indicate that it should run in compatibility mode. It appears to be necessary to go to this tab in the Properties dialog box for these files and click OK to force this mode to be used.

Comments

  1. User Gravatar Matt said:

    January 9th, 2012 at 11:09 pm (#)

    hi, I'm on 64 bit win7. I love you man. love.

Leave a comment

 

My first (useful) Ruby program

June 25th, 2011

Summary: Batch convert files with names like 25_06_2011 21_30.wav to names like 2011-06-25_2130_Saturday.wav.

I have a load of files with date/time-based file names in the format dd_mm_yyyy hh_mm.wav. I’d prefer these files to have a format that allowed them to be sorted in a directory in a meaningful way by the file name (i.e. yyyy-dd-mm). I also have a pet hate of file names containing spaces. It would also be useful to show the day of the week in the file name. So what I’d really like is a file name in the format yyyy-dd-mm_hhmm_<dayname>.wav.

In the past I’d have written a Perl script to rename a batch of files, but since I’ve been looking at Ruby recently it made sense to have a bash at doing this in Ruby.

Here’s the program I came up with:

1 #!/c/ruby/bin/ruby
2 # Created by Alistair Christie
3 # Date: 25 June 2011
4 # This is my first functional Ruby program.
5 # It's purpose is to take files in the current directory (if no arg supplied) -
6 # or files in the specified directory (argument on command line) -
7 # that match the pattern nn_nn_nnnn nn_nn.wav
8 # (i.e. iPod voice memos saved as WAV files: dd_mm_yyyy hh_mm.wav)
9 # copy them to an archive subdirectory
10 # and rename the originals yyyy-mm-dd_hhmm_<dayname>.wav
11
12 require 'date'
13 require 'fileutils'
14
15 if ARGV.length > 0
16     $input_directory = ARGV[0]
17 else
18     $input_directory = '.'
19 end
20
21 Dir.chdir($input_directory)
22
23 $archivedir = "originalFiles_nowRenamed"
24 $count = 0
25
26 puts "Processing ..."
27
28 def file_match(pattern=/\d\d_\d\d_\d\d\d\d \d\d_\d\d\.wav/, path='.')
29   Dir[File.join(path,'*')].each do |file|
30     if file =~ pattern
31         $count += 1
32         if $count==1 then Dir.mkdir($archivedir) unless File.exists?($archivedir)
33         end
34         file =~ /^[^\d]*(\d\d)_(\d\d)_(\d\d\d\d) (\d\d)_(\d\d)/
35         #puts "Matched file: #{file}"
36         dt = Date.new($3.to_i, $2.to_i, $1.to_i);
37         dy = Date::DAYNAMES[dt.wday]
38         newfilename = "#$3-#$2-#$1_#$4#$5_" + dy + ".wav"
39         FileUtils.cp(file, $archivedir + "/" + file)
40         FileUtils.mv(file, newfilename)
41         puts file + " renamed " + newfilename
42     end
43   end
44 end
45
46 file_match
47
48 if $count>0 then puts $count.to_s + " files were renamed."
49 else puts "No files were renamed."
50 end
51

Anyone looking at this who knows how to code in Ruby will, doubtless, immediately see all sorts of issues with it. But I’m quite happy with it because it didn’t take long to write and it does the job.

I’ve saved this file as RenameWavFiles.rb in the iTunes directory where all these files get created and I have a shortcut to that directory so that all I need to do is click the shortcut icon to open the directory in Windows Explorer, then double-click the Ruby file to rename any new files. The files are copied to a subdirectory with their original names just in case there’s a problem. Job done!

I wrote the code in Vim 7.2 and one nice thing about the GVim incarnation of Vim is that, in the Syntax menu, there’s a Convert to HTML option that creates the output you can see above.

gvim-convert-to-HTML

Leave a comment



Rails Chronicles – Part 1

June 19th, 2011    1 Comment

150px-Ruby_on_Rails.svgBefore you read any further: The purpose of this post is to capture how I went about learning how to create Web apps using Rails. I thought it might be interesting to look back in a few months and see all the things I got wrong and didn’t understand about Ruby and Rails when I started out. So, if you’re looking for enlightenment about Rails, you’re in the wrong place. I’d recommend you head over to Michael Harl’s Ruby on Rails Tutorial: that’s the site that really got me started.

Introduction

I have a stinking cold this weekend and, apart from dragging myself out to walk the dog, I’ve been fit for nothing else but sitting on the sofa (or lying in bed) with my laptop. But I thought I’d try to use the time profitably by finally getting around to learning how to use Rails. I’ve been meaning to do this for over five years now – i.e. since the days when all the tech podcasts I listened to hyped it up as the great new thing on the Web.

Back in 2006 I even bought my daughter a copy of the original edition of Chris Pine’s Learn to Program book – which uses Ruby to teach programming – on the off-chance that she might get interested in coding. We sat and went through some of it together but she really wasn’t interested so the book then lay unread for years, until a couple of months back when I packed it into one of several big cardboard boxes with all my other computer books and it went off to the Oxfam bookshop.

The trouble has been (apart from inertia, laziness and wariness about potentially wasting lots of time on yet one more thing I really don’t need to know about) that I’ve been doing most of the dynamic Web page goodness I need to do quite fine all these years using PHP (well, a combination of PHP, MySQL, Javascript, CSS and plain old HTML to be precise). So I haven’t had a need to learn about Rails. But PHP seems antiquated these days and I really feel like I need to move on. I also wanted to get a better understanding what Model-View-Controller (MVC) is all about. I understand the principals of MVC, but it’s not until you actually use a programming concept that you really understand it.

Before PHP I was a committed Perl devotee and it took me a while to switch to PHP because I really liked Perl and I was doing some fairly complex stuff with it. I got into Perl because I’d started writing Web pages in HTML, discovered you couldn’t do much with HMTL alone, started writing Javascript, discovered that that had its limitations (as well as being the source of a great deal of pain back then) and so I ended up, like many people who followed the same route, writing Perl CGI scripts. That was before PHP had really got going and, for hobbyist Web site creators like myself, Perl CGI scripts on Apache servers was about the only way to go. And I really enjoyed writing Perl. The only thing that did for Perl was the whole issue with modules: figuring out which modules you needed, which versions were installed, installing multiple versions of modules so as not to break someone else’s scripts, and so on. Modules were a bit of a nightmare. PHP just seemed to have everything built in and you could just crack on and do the coding.

So I switched from Perl to PHP and never looked back. But I do remember being horrified at first by the mix of HTML and code within PHP files. The recipe seemed to be: chuck all your ingredients (design, content, functionality) into one bowl and give it a good old mix. It struck me as having massive potential for confusion and maintenance issues. With my Perl scripts I’d used separate HTML templates. The Perl script requested by the browser called up other scripts as required, did the processing, worked with the database, gathered together all the dynamic content and then selected from a choice of templates and built the final HTML by replacing placeholders with the dynamic content. I really liked the idea of keeping the page design and static content as separate as possible from the code – it just seemed a lot cleaner that way. So that’s one thing I’m expecting Rails to have got right and I’m looking forward to getting back to that kind of way of doing things. We’ll see.

Starting point

I can’t code in Ruby. I’ve read up about it at various points during the past few years and I’ve written a few little Ruby programs in the course of dipping my toes in the subject. Specifically, I’ve spent some time with these resources:

But, as of today, I have to say I really can’t code in Ruby. Should I have concentrated on this for a bit before jumping into Rails? I’ve read conflicting advice answering this question definitely yes, and no, it’s not necessary. It’ll be interesting to see how much this lack of knowledge holds me back or trips me up.

As far as Rails goes, before this weekend I’d watched pretty much every video I could find about Rails at one time or another – including all the ones where someone zips through and creates a (seemingly) fully functioning social media Web site in about ten minutes. For non-macho programmers like myself that kind of thing (where someone is talking super fast and typing commands even faster, and things are zapping past you on the screen: zap, there goes validation, blink and you miss it, there goes authentication …), that just puts me off, because what it says to me is: only ubergeeks will really find this as easy as this guy seems to – the rest of us would doubtlessly only get mired in bizarre error messages before we ever got anywhere near creating a working Web page.

Anyway, I’d heard a podcast a while back where Michael Hartl was being interviewed about the Rails tutorial he’d written and the screencasts he’d created, and how he makes a really good living from people buying the screencasts and the PDF of the tutorial, even though the same content that’s in the PDF is available for free as Web pages. So this weekend I finally went and looked up http://ruby.railstutorial.org/ruby-on-rails-tutorial-book and started reading the first chapter of the tutorial book. And so far so good. I’ve done the first two chapters now and I like it. It’s up to date and it works.

gvim

The other thing I spent some time on was downloading, setting up and relearning vim (actually gvim). This is a lightly updated version of the UNIX vi editor. There’s a Windows version of gvim that lets you relive the experience of using a text editor originally created by a 22-year-old Bill Joy back in 1976. It might sound crazy to choose to go back to using vim, but I think it might make sense – there are some definite benefits.

I started using vi in 2001 when I got a job as a technical author and discovered, first day on the job, that I wouldn’t be using Word or even Notepad. I had a choice between vi and Emacs, neither of which I’d heard of before. I tried them both and settled on Emacs at the time, but since leaving that job I’ve never used Emacs again but I’ve used vi regularly over the years just because it’s always available on any UNIX/Linux server you ever connect to.

For a long time my text editor of choice was UltraEdit. I then switched to Notepad++ and I’ve stuck with it for the last eight or nine years now. But I thought I’d tie in learning Rails with brushing up my vi expertise (in the shape of gvim on Windows). I should point out that I’m working on Windows 7. So, after some tweaking of colours and window setup, and spending a little time revising the subject and creating a personal cheatsheet on vim (in vim), I’m using it quite happily now. I’ve never really been a mouse lover. I like keyboard shortcuts, and the great thing about vi is being able to keep your hands on the keyboard all the time: it really does allow you to get things done far quicker than you can by pointing, clicking, dragging.

git

git is another of those things I’ve been hearing about a lot over the past five years or so and felt I should find out more about. Back when I was learning vi and Emacs I was also learning about CVS, and I found it a steep learning curve. Fast forward a few years and, at my current job, we switched our version control from CVS to SVN and I came to really like SVN. I particularly like TortoiseSVN and its repo browser. But I’ve been thinking about looking at git for a while now – just to find out why people seem to like it better (it seems to be the most-used version control system for software source files now).

So I was pleased to discover that Michael Hartl’s tutorial gets you committing your Rails code to github right from the start. The only trouble I’ve had with the tutorial so far has been that I couldn’t push code up to github successfully to begin with and I struggled for a while (and posted a question on stackoverflow about it) before realising that I’d screwed up with one of my initial commands, meaning I had to delete the .git directory and start over. The problem was that I’d tried to push up my code before going to the github Web site and creating an account and a repository. Yes, I know: duh! But the problem seemed to be that having made this error, even though I then went and created the account and repository, something in my .git directory must have been messed up. So that held me up for a few hours, but – after backing up and redoing it – it now works fine.

The git commands are (like much in the world of Ruby on Rails, I suspect) the kind of thing that you just have to learn. It’s not obvious and you can’t just guess and figure it out. You need to know that exact words and syntax or it won’t work.

One of the things I like about having installed git from github is that I now have a bash shell on my Windows 7 machine. I can press the Windows key, type bash, press Enter and I get a console window with the bash shell, which allows you to do a lot more, a lot more easily than the standard Windows DOS-type command console.

Heroku

Finally, for this inaugural Rails Chronicle post, something else I’d heard about in a podcast but never used: Heroku. I spent a few days up in Glen Esk earlier this year and I remember one day walking the dog across the field to the river and than back up along the side of the Tarf listening to a podcast about Heroku, which is a hosting service for Web applications. Actually it’s more than that. It’s a system for continuous deployment of Web applications that’s intigrated with git to make it easy to push files up to Heroku’s cloud service and build a deployment that you can immediately browse to.

It seems to work incredibly easily and smoothly – but, again, working from the command line, you need to know the right commands; although these seem to amount to:

$ heroku create
$ git push heroku master
$ heroku rake db:migrate

Conclusion

So far so good. I’ve only done the first two chapters but they cover a whole lot of ground and I feel like I’ve learned a lot already. What I haven’t learned however, is any Ruby – so far.

Leave a comment



Gotchas with running a Perl script as a cron job

August 3rd, 2010    4 Comments

So you've written a Perl script and it runs fine from the command line using a command such as:

perl /home/alistair/scripts/myscript.pl

Great, so now you set up a cron job so that the script will run automatically. For example, let's say you want to run it every Monday morning at 4.20 am:

20 4 * * 1 perl /home/alistair/scripts/myscript.pl

 
However, when this runs it generates the following email:

Your "cron" job on myserver
perl /home/alistair/scripts/myscript.pl

produced the following output:

Can't locate DBI.pm in @INC (@INC contains: /usr/perl5/5.6.1/lib/sun4-solaris-64int /usr/perl5/5.6.1/lib /usr/perl5/site_perl/5.6.1/sun4-solaris-64int /usr/perl5/site_perl/5.6.1 /usr/perl5/site_perl /usr/perl5/vendor_perl/5.6.1/sun4-solaris-64int /usr/perl5/vendor_perl/5.6.1 /usr/perl5/vendor_perl .) at /home/alistair/scripts/myscript.pl line 15.
BEGIN failed--compilation aborted at /home/alistair/scripts/myscript.pl line 15.

 
What this means is that your script uses a Perl module (in this example, DBI.pm) which can't be found. The error message shows all the paths in the @INC list of paths where Perl looks for modules. So, for some reason, Perl found the module when you ran the script, but didn't find the module when cron ran the script as you.

The reason is that cron doesn't run in the same environment that you're using. When you connect to the server, you probably automatically change to your preferred shell (e.g. csh, ksh or bash) and load up a whole set of environment variables. This happens within the startup file – for example, .bashrc or .cshrc. But cron doesn't load up any of this, and it uses sh by default.

To see what's in @INC within your environment use this command:

perl -le 'print for grep {$_ ne q{.}and -d} @INC'

 
And you'll probably notice differences between the output you get and the contents of @INC listed in the error message.

So, to make sure @INC contains the necessary paths in any environment, load it up from within your Perl script. To do this, add something like the following to the top of your Perl script, just after the path to Perl:

BEGIN {
     push @INC,( '/usr/local/lib/perl5/5.8.2/sun4-solaris',
          '/usr/local/lib/perl5/site_perl/5.8.2/sun4-solaris',
          '/usr/local/lib/perl5/site_perl/5.8.0/sun4-solaris',
          '/usr/local/lib/perl5/site_perl/5.6.1/sun4-solaris' );
}

So now Perl will be able to find the missing Perl module. Sorted! Well maybe not.

If you now try running the script from the cron job you may get something like:

Your "cron" job on myserver
perl /home/alistair/scripts/myscript.pl

produced the following output:

ld.so.1: perl: fatal: relocation error: file /usr/local/lib/perl5/site_perl/5.8.0/sun4-solaris/auto/DBI/DBI.so: symbol Perl_PerlIO_stderr: referenced symbol not found Killed

Now it's complaining about not finding something called ld.so.1. The problem here is with your PATH.

On my server, ld.so.1 lives in /usr/lib. You should be able to find out where ld.so.1 is by running:

whereis ld.so.1

/usr/lib isn't exactly an obscure place to look, but it's not in the PATH when the cron job runs. So the easy solution is to explicitly set the contents of the PATH environment variable in the cron job:

20 4 * * 1 PATH=/usr/local/bin:/usr/bin:/usr/sbin:/usr/lib; perl /home/alistair/scripts/myscript.pl

Now, just before the Perl script is run, the PATH gets set to three paths: /usr/local/bin, /usr/bin, /usr/sbin and /usr/lib. The syntax used here is that required by the sh shell in which cron runs.

At last, job done. The script runs and you'll be emailed any output it generates.

Leave a comment



PHP (or Perl) one line if/then/else statements

August 8th, 2009

If you're toggling something between two states in PHP or Perl it's often handy to use an if/then/else one liner.

In pseudocode this goes like this:

<if this evaluates to TRUE> then <parse this> else <parse this>

All you need to do is replace the "then" with a question mark and the "else" with a colon:

<if this evaluates to TRUE> ? <parse this> : <parse this>

For example:

print  $trueOrFalse ? "you're telling the truth" : "you're lying";

Ignore the print command, it's not part of the if/then/else statement, it's just here to do something with the outcome of that statement.

The expression immediately to the left of the question mark is evaluated. The expression between the question mark and the colon is parsed if the expression evaluates to TRUE, otherwise the expression immediately to the right of the colon is parsed. So in the above example, either "you're telling the truth" or "you're lying" is printed, depending on whether $trueOrFalse is ... you guessed it ... TRUE or FALSE.

But perhaps a more common situation is toggling the value assigned to a variable. For example, toggling between TRUE and FALSE:

$trueOrFalse = $trueOrFalse ? FALSE : TRUE;

Here's a practical example of the use of if/then/else one liners. There's two in this chunk of PHP. The scroll box list below the code is the kind of thing this PHP produces.

<div style="overflow:auto; height:100px; width:300px; border:3px groove #DDD; padding:0">
<?php
    $alternateLine = FALSE;
    while($presidentsArray) {
        print "<div style=\"background-color:";
        print $alternateLine ? "#F5F8F9" : "white";
        print "; padding-bottom: 1px\"> &nbsp; &nbsp; <a href=\"someURL\" title=\"This link goes nowhere\">" .
          $presidentsArray['name'] . "</a></div>";
        $alternateLine = $alternateLine ? FALSE : TRUE;
    }
?>
</div>

Leave a comment



^ back to top ^

Page 1 of 3123