Ruby off the Rails?
Archive - Originally posted on "The Horse's Mouth" - 2011-09-06 22:31:35 - Graham EllisTime was ... "if it's Ruby it must be Rails". The Ruby on Rails framework was the initial killer application that brought the Ruby language to the attention of many, and was so prevelant that it masked other excellent uses. So I'm delighted to see significant other uses of Ruby growing in addition to its use in Rails. Ruby is an excellent, and still underrated, "scripting" language, taking the eclectic best principles from Perl 5 and adding a true underlying Object Oriented philospohy and foundations.
I'm giving a Ruby course this week; I will be running a day to introduce Rails on Friday, but up to that point we're looking at the language - for delegates who are new to programming, rather than for programmers converting from something else. It's our Learning to program in Ruby course.
For readers who may be familiar with programming in other languages, may I present an elegant script which I wrote at the end of yesterday - [here]. I've taken all the records in a data file, each of which contains data about a UK railway station, and created an object from each. I've then enquired of the objects looking for stations where traffic has grown almost five times in six years, and reported on that selected few. That's the overview ... now for the code ...
Open the file of data, and initialiase an "array" to hold each station:
fh = File.new "railstats.xyz"
stns = []
Read each station into the array, converting the data on each line from a string of text to a format that's easily useable:
while (lyne = fh.gets)
stns.push Station.new(lyne)
end
Loop through each of the places where there's a station, reporting on the growth if it's between 4.5 and 5 times:
for place in stns
growth = place.getgrowth
if growth > 4.5 and growth < 5.0
puts "Growth #{growth} at #{place.getname}"
end
end
Of course, much of the work that's done here is in the piece of code that defines a Station, how it works and what we can do with it. For the purposes of this demonstration I included the definition in the same program file (it means that the delagates can see it all in one window, and that you can download it all in a single file) ... for a live and developing suite of applications, I would share the station definition between programs by wrining it in a separate file and then calling it up with a require statement.
Anyway - the definintion of a "Station":
class Station
def initialize(record_text)
@fdc, @tlc, @postcode, @gridref,
@lati, @longi, @name, @t2005,
@t2006, @t2007, @t2008,
@t2009, @t2010 = record_text.chomp.split "\t"
end
def getgrowth
return 1.0 if @t2005 == "NULL" or @t2010 == "NULL"
@t2010.to_f / @t2005.to_f
end
def getname
return @name
end
end
There's a great deal more that I could do there, and some design decisions made ... I've elected to name each element from each line and to store them in separate variables not an array, but I've elected to store them all as strings rather than make conversions to other types. I've decided to leave the logic to work out whether or not I can calculate a growth factor until the code is asked for such a factor rather than doing so as soon as each Station is set up, and I've decided that if I can't calculate a growth factor, I'll treat the station as if it had neither growth nor a loss in traffic. The beauty of the structure that Ruby has let me employ is that all these detailed decisions can be left up to the station 'expert' and hidden in this class definition. The person calling the code shown earlier just need to know what questions to ask and how to handle the answers. This 'hidden within' approach is known as encapsulation if you would like a posh word for it.
You can download the data (it's extracted from public data provided by the Office of the Rail Regulator and the Department for Transport amongst others) from [here]. Output looks like this:
munchkin:rs grahamellis$ ruby thirdrail
Growth 4.84424038039829 at Bradford Forster Square
Growth 4.69588971475764 at London Fields
Growth 4.88378896251115 at Hackney Wick
Growth 4.62891340332681 at Maghull
Growth 4.91176855609373 at South Tottenham
Growth 4.60778231652162 at West Hampstead Thameslink
Growth 4.72221717401181 at Brondesbury Park
Growth 4.725 at Havenhouse
Growth 4.97251091015432 at Ore
Growth 4.64773309666371 at Worcester Foregate Street
munchkin:rs grahamellis$
... none of which I have any photos of to illustrate the article ...
My subject line asks "Ruby off the Rails?". Most certainly it is not. It's an excellent language, and this week's a real pleasure letting me introduce programming through Ruby to a group of delegates on our course.