My First Ruby

Vanwege de hype rond Ruby on Rails wilde ik wel eens Ruby proberen. Met Ruby on Rails heb je in ongeveer 15 minuten een min of meer werkende applicatie maar dan weet je eigenlijk nog niets van Ruby en ik denk dat het beter is om een taal te leren kennen en daarna je te wagen aan leuke frameworks. Dus eerst maar even iets simpels:

Ik gebruik Amarok als music player. Amarok houdt een soort van score bij op basis van het aantal keer dat de track speelt en hoe lang je de track beluistert. Ik wou de meest gedraaide tracks naar mijn mp3 player hebben, willekeurig totdat het filesystem vol is. Grappig om mee te beginnen, want je moet dan een paar dingen doen: een klein beetje rekenen en een database aanspreken (Amarok gebruikt een database)

Het script is nog niet af. Het liefst wil ik ik dit aanroepen met als verplicht argument een doel directory en dat het script dan zelf bepaalt hoeveel ruimte er nog beschikbaar is. Ook het eigenlijke kopieren moet nog in Ruby maar voor nu vindt ik xargs voldoende.

Met nul kennis van Ruby heeft me dit 45 minuten gekost. De meeste tijd ging zitten in de error handling. In Perl en PHP is het meer gedoe. Ik heb ook nog een PHP versie gemaakt (copy-paste vanuit Ruby). Het is een beetje flauw om PHP als voorbeeld te nemen: het is niet bedacht om vanaf de command line te draaien dus die bizarre manier om iets naar STDERR te schrijven zullen we PHP maar vergeven…

Hierbij het ruby script:

require "mysql"

# TODO: returns free space on device
def get_free_space
	return 500 * 1024 * 1024
end

begin
	space = get_free_space;
	dbh = Mysql.real_connect("localhost", "", "",  "amarok")
	sql = "SELECT * FROM statistics WHERE percentage > 90 ORDER BY RAND()"
	res = dbh.query(sql)

	while space > 0 && row = res.fetch_hash do
		begin
			filesize = File.size(row['url'])
			if space - filesize > 0
				puts row['url']
			end
			space -= filesize
		rescue SystemCallError
			# Can't read file, for whatever reason. Report on STDERR and ignore
			$stderr.puts "Can't read " + row['url']
		end
	end

rescue MysqlError => e
	puts e.error
ensure
	res.free
	dbh.close
end

En het equivalent in PHP:

<?php

function mysql_error_catch()
{
	print mysql_error();
	mysql_close();
	die;
}

// TODO: returns free space on device
function get_free_space()
{
	return 500 * 1024 * 1024;

}
$space = get_free_space();
$dbh = @mysql_connect("localhost", "amarok", "!amarok");
mysql_select_db('amarok');
if (!$dbh)
	mysql_error_catch();
$sql = "SELECT * FROM statistics WHERE percentage > 90 ORDER BY RAND()";
$res = mysql_query($sql);
if (!$res)
	mysql_error_catch();
while ($space > 0 && $row = mysql_fetch_assoc($res))
{
	if ($filesize = @filesize($row['url']))
	{
		if ($space - $filesize > 0)
		{
			echo "{$row['url']}\n";
			$space -= $filesize;
		}
	}
	else
	{
		// Can't read file, for whatever reason. Report on STDERR and ignore
		$fp = fopen("php://stderr", "w");
		fwrite($fp,"Can't read ".$row['url']);
		fclose($fp);
	}
}
mysql_close();

?>

3 Responses to “My First Ruby”

  1. alles over says:

    Ok, ruby ziet er redelijk leesbaar uit. Het enige wat ik wat minder vindt zijn de ‘begin’ en ‘end’ definities in plaats van accolades {}. Dan moet je zoveel typen.

  2. Juice10 says:

    @ alles over:

    Als je dat minder vind zul je super blij zijn dat je geen $ voor alle vars hoeft te doen. *joepie* ;)

  3. Nem says:

    ‘k Ben nu een paar weken met Rails bezig maar ik blijf het erg lastig vinden…

Leave a Reply