Archive for the ‘Ruby’ Category
rspec – Invalid character '\240′ in expression
We have been using rspec on my project for the unit testing of our Ruby code and while running one of the specs last week I ended up getting this somewhat en-cryptic error message:
Invalid character '\240' in expression ...
After convincing myself that this error wasn't actually possible it turned out that I had somehow entered an 'invisible to TextMate' character after one of the method definitions – on the editor it just looked like a space.
I'm not sure exactly what the character was but deleting it got rid of the error and got my test/spec running again.
Calling shell script from ruby script
Damana and I previously posted about our experiences with different Ruby LDAP solutions.
Having settled on Ruby-LDAP (although having read Ola and Steven's comments we will now look at ruby-net-ldap) we then needed to put together the setup, installation and teardown into a ruby script file.
A quick bit of Googling revealed that we could use the Kernel.exec method to do this.
For example, you could put the following in a ruby script file and it would execute and show you the current directory listing:
exec "ls"
The problem with using Kernel.exec, which we became aware of after reading Jay's post, is that we lose control of the current process – i.e. the script will exit after running 'exec' and won't process any other commands that follow it in the file.
Luckily for us there is another method called Kernel.system which allows us to execute a command in a sub shell, and therefore continue processing other commands that follow it.
We were able to use this method for making calls to the make script to install Ruby-LDAP:
@extconf = "ruby extconf.rb" system @extconf system "make" system "make install"
There is one more option we can use if we need to collect the results called %x[...]. We didn't need to collect the results so we have gone with 'Kernel.system' for the time being.
Jay covers the options in more detail on his post for those that need more information than I have presented.
Ruby LDAP Options
As I mentioned in an earlier post a colleague and I spent a few days looking at how to connect to an OpenDS LDAP server using Ruby.
We ended up analysing four different solutions for solving the problem.
Active LDAP
This approach involved using the Active LDAP Ruby which "provides an object oriented interface to LDAP. It maps LDAP entries to Ruby objects with LDAP attribute accessors based on your LDAP server's schema and each object's objectClasses".
We had real problems trying to even connect to our OpenDS server using this library. We eventually found out that OpenDS is not actually listed as one of the supported interfaces.
The real benefit of this approach was that the library is written in Ruby meaning that getting permission to install it would be easier.
The fact that we couldn't actually get it to work didn't help!
Java LDAP libraries + RJB
This approach involved interacting with LDAP with Java libraries and then using the Ruby Java Bridge to connect to these from our Ruby code.
We were able to solve the problem quite easily using this approach but the Ruby code we ended up writing was very Javaesque in style and it didn't feel like we were utilising the power of Ruby by using Java for such a fundamental part of the problem we were attempting to solve.
On the positive side RJB is easily installable via a gem and we were able to connect to OpenDS and execute the operations that were required.
Ruby-LDAP
The third option we looked at was Ruby-LDAP, a Ruby extension library written in C.
The disadvantage of this was that we needed to have make available to install it onto our machine. Seeing as we were using a Mac this meant downloading XCode to make use of the GCC compiler.
Interacting with the different libraries was tricky initially but we eventually got the hang of it and were able to connect to OpenDS despite it not being listed as one of the supported libraries.
ruby-net-ldap
ruby-net-ldap is a pure Ruby LDAP library, installable via a gem.
This had by far the best examples and most intuitive interface of the options that we analysed and worked for us first time without too much fuss. Connecting to our Open DS server was seamless.
Overall
Our original selection, despite the slightly more complicated installation was Ruby-LDAP.
However, Ola Bini pointed out ruby-net-ldap which actually proved to meet our criteria even more closely than Ruby-LDAP did and as such was the option we went with.
For those that are interested, Damana has posted more of the technical details behind the approaches we took.
Ruby: Ignore header line when parsing CSV file
As my Ruby journey continues one of the things I wanted to do today was parse a CSV file.
This article proved to be very useful for teaching the basics but it didn't say how to ignore the header line that the CSV file contained.
The CSV file I was parsing was similar to this:
name, surname, location Mark, Needham, Sydney David, Smith, London
I wanted to get the names of people originally to use them in my code. This was the first attempt:
1 2 3 4 5 6 7 8 9 10 | require 'csv' def parse_csv_file_for_names(path_to_csv) names = [] csv_contents = CSV.read(path_to_csv) csv_contents.each do |row| names << row[0] end return names end |
I then printed out the names to see what was going on:
1 2 3 4 | names = parse_csv_file_for_names( "csv_file.csv" ) names.each do |name| puts name end |
This is what was printed:
name Mark David
It turns out that the 'shift' method is what I was looking for to help me ignore the first line of the file. The new and improved method now looks like this:
1 2 3 4 5 6 7 8 9 10 11 | require 'csv' def parse_csv_file_for_names(path_to_csv) names = [] csv_contents = CSV.read(path_to_csv) csv_contents.shift csv_contents.each do |row| names << row[0] end return names end |
Not a particularly complicated thing to do in the end although I had been expecting to find a method on CSV that would allow me to ignore the header line automatically. As far as I could tell there isn't one!
Ruby: Unzipping a file using rubyzip
In the world of Ruby I've been working on a script which needs to unzip a file and then run an installer which is only available after unpacking it.
We've been using the rubyzip gem to do so but so far it hasn't felt intuitive to me coming from the Java/C# world.
ZipFile is the class we need to use and at first glance I had thought that it would be possible to just pass the zip file name to the 'extract' method and have it do all the work for me!
Turns out you actually need to open the zip file and then create the directory location for each file in the zip before extracting them all individually.
We eventually ended up with this little method:
1 2 3 4 5 6 7 8 9 10 11 12 | require 'rubygems' require 'zip/zip' def unzip_file (file, destination) Zip::ZipFile.open(file) { |zip_file| zip_file.each { |f| f_path=File.join(destination, f.name) FileUtils.mkdir_p(File.dirname(f_path)) zip_file.extract(f, f_path) unless File.exist?(f_path) } } end |
Which we can then call with the zip file and the destination where we want to unzip the file.
1 | unzip_file("my.zip", "marks_zip") |
Is there a better way to do this? It feels a bit clunky to me at the moment.
Ruby: Parameterising with ActiveResource
We've been using Ruby/Rails on my current project to create a RESTful web service. One of the problems we wanted to solve was making the data queried by this web service configurable from our build.
We started off with the following bit of code (which makes use of the recently added ActiveResource class):
1 2 3 |
class MyClass < ActiveResource::Base self.site = "http://localhost:3000/" end |
And then called this class as follows:
1 |
MyClass.create(:param => "param-value") |
This worked fine for us until we wanted to parameterise the 'site' value so that we could set it to different values depending which build we were running (dev/ci/qa). We tried all the obvious ways – overriding the constructor and passing in the site, trying to set the site by calling MyClass.site but none of them did what we wanted. We eventually ended up creating a new method to create an instance of the class with our configurable site:
1 2 3 4 5 6 7 8 |
class MyClass < ActiveResource::Base def instance(site, args) self.site = site new(args) unless args.nil? end end |
We then call the code like this:
1 2 |
my_class = MyClass.instance("http://localhost:3000", :param => "param-value") my_class.save |
It seems like a bit of a hack but it got it working!
Out of interest it has taken me ages to try and find a way to put the Ruby code on here in a readable format. I tried to use the TextMate exporter but that wasn't giving me any love. I eventually ended up using Spotlight, a neat little tool written by Tyler Jennings. I found it from Jake Scruggs blog post.
Watching a master at work
I've always found it fascinating watching people who really excel in their field going about business, be it footballers, tennis players, actors, whoever.
This week at TWU I've been playing around with some Ruby on Rails as I mentioned in the previous post, and yesterday I had the opportunity to watch one of the leading figures in the Ruby on Rails field at work. Take a bow Obie Fernandez, who gave several of the TWU attendees a demonstration of how to develop applications using Ruby on Rails. It was actually bordering on the severely impressive watching the speed at which he thought through concepts and then transformed them into code.
I also realised that the way I'd been using the language previously had been dubious at best. I hadn't realised that you can take care of database creation without using MySQL Administrator, nor had I realised quite how 'clever' Ruby on Rails is at mapping database tables to models created in the application.
It was almost painful watching how simple it is to do arduous tasks, such as creating textboxes and drop down boxes, in Ruby on Rails and it almost made me want to weep as I recalled the many hours I've spend using PHP and C# tweaking interaction between code and stored procedures/queries.
So +1 for Ruby on Rails and I certainly hope to improve my ability with it over the next few weeks.
First thoughts on Ruby…
I've heard a lot about Ruby on Rails over the last couple of years but I'd never really been intrigued to get it set up on my machine and 'have a play' with it so to speak.
It turned out to be a relatively painless process and after following the instructions on the official site I had it all setup within about half an hour which was a record for me for getting a development environment setup. With a bit of help from the Pragmatic Programmers Guide to Ruby I managed to get some basic pages setup. The design of the URLs and the separation of the code is actually fairly intuitive. Ruby on Rails uses the MVC (Model – View – Controller) Architecture/Design Pattern very strictly and the code for each of these is written in a separate file.
One aspect of this that made sense to me as a PHP programmer was the way that the URLs in Ruby on Rails are constructed in a "/[controller_name]/[action]" format. I also like the fact that everything in Ruby on Rails is an object, even such things as integers and strings. It takes a bit of getting used to but after using it for a bit it seems counter intuitive to do it any other way.
I don't think I'm about to become an advocate for the use of Ruby on Rails for every development project I work on – I'm still a big fan of C# and the .NET platform and I find it unlikely that I'll change my mind in the near future but we shall see!