Posts Tagged ‘ruby’

Rails Rumble aftermatch

Wednesday, October 22nd, 2008

Vorig weekend hebben we met Openminds en Gorilla webdesign samen een project ontwikkeld voor Rails Rumble. De applicatie is “locatr.eu“, en is een eenvoudig spelletje, die een foto toont, en de gebruiker moet raden waar de foto genomen is.

Het werd een weekend vol coding, Wii-spelen (flink op m’n doos gehad), goed eten en drinken, en een fijne samenwerking tussen de twee bedrijven. We hebben flink wat werk gestopt in het correct berekenen van de afstand tussen verschillende punten, en het opzoeken van foto’s op afstand uit de database, op een performante manier. Het “niet moeten registeren” hebben we goed opgelost (naar onze mening). De layout heeft ook van Jelle de nodige liefde gekregen. Technisch zit het geheel zeer netjes in elkaar, alles gebeurt REST-full, er wordt veel gebruik gemaakt van externe API’s en plugins, en de programmacode is prima leesbaar en voldoende DRY. Jammer genoeg is de snelheid van de applicatie wat minder, aangezien de VDS van Linode wat te wensen overlaat.

Allen zijn dus uitgenodigd om een kijkje te gaan nemen, en er wat mee te spelen. Laat maar weten wat je ervan vindt, en als je even tijd hebt, volg dan even de procedure om voor ons te stemmen (zal online komen op onze profielpagina eens het stemmen kan beginnen).

Helemaal af zou ik de applicatie niet noemen, er zijn nog enkele extra’s die ik wel leuk zou vinden, maar er was gewoon niet genoeg tijd. Zo hadden we nog volgende extra’s voorzien: RSS feed, een mobile interface die wat meer lightweight is, de mogelijkheid om foto’s te vlaggen als “niet goed”, etc etc… Afhankelijk van de populariteit van het ding gaan we die misschien nog implementeren eens de judging en voting achter de rug is.

convert textpattern to radiant

Saturday, January 5th, 2008

This is a quick-n-dirty, poor-mans solution to a migration from TextPattern to Radiant CMS. It doesn’t work perfect, it is some manual work, but it did the trick for me, and that’s all I needed. Observe:

First of all, get your data from the textpattern database, and import it in the Radiant CMS database. I used a simple mysqldump command for this, and loaded it back.

db-server $ mysqldump database textpattern > dumpfile.mysql
...(copy)...
devel-server $ mysql -u root site_development < dumpfile.mysql

A small note: I quickly loaded the dump in my editor and converted all the fieldnames to lower case before loading it back in the radiant database. You might want to do this also.

Lazy as I am, I quickly altered the table name to be plural, so Rails/Radiant wouldn't complain:

mysql> rename table textpattern to textpatterns;

Then I fired up Textmate and made this little script:

class Textpattern < ActiveRecord:Base; end 
 
u = User.find :first
 
Textpattern.find(:all, :conditions => {:section => 'article'}).each do |textpattern|
  p = Page.new({
    "virtual"=>false, 
    "class_name"=>'Page', 
    "slug"=>textpattern.url_title.downcase.strip.gsub(/\s+/,'-'), 
    "updated_at"=>textpattern.lastmod, 
    "title"=>textpattern.title, 
    "created_by"=>u, 
    "breadcrumb"=>textpattern.title, 
    "lock_version"=>0, 
    "enable_comments"=>0, 
    "updated_by"=>u, 
    "comments_count"=>0, 
    "published_at"=>textpattern.posted, 
    "status_id"=>100, 
    "position"=>1, 
    "layout_id"=>nil, 
    "parent_id"=>87, 
    "created_at"=>textpattern.lastmod}) do |newpage|
      newpage.parts.create({"name"=>"body", "filter_id"=>"Textile", "content"=>textpattern.body})  
      newpage.parts.create({"name"=>"summary", "filter_id"=>"Textile", "content"=>textpattern.excerpt}) 
  end
  p.save!
end

The first line will add a model for the Textpattern table we added, so we can use the ActiveRecord magic to access this table. The second line will load the first user it can find (I only had one, so no problems there).

From then on, we just get all the Textpatterns articles we want (a specific section in this case), and with each of these, I create a new page in radiant, and add pageparts to them, with good defaults.

Once done (and bugfixed), I simply copy-pasted this in a script/console session in my radiant-project. Done.

The defaults were stolen from a page I quickly created and published in Radiant, under the correct section. You need to pay attention to the “parent_id” for the Page-creation (get it from the database, or from the url when hovering it in the admin section), and the “name” for the PagePart creation sections.

Last work is to drop the added table from your database.

As I told you, quick-n-dirty, and nothing I’m really proud of, but I needed it fast, and I’ve published it here as it might help other people.

ngrams in ruby

Monday, November 5th, 2007

Een technisch stukje. Voor een project moest ik N-Grams bepalen van teksten. Wat is dit nu juist: wanneer je een woord neemt, en een bepaald getal (neem 3), dan zijn alle n-grams met lengte 3 (ook wel ‘trigrams’ genoemd dan) elk stukje van 3 letters uit het woord. Als het woord dus “voorbeeld” is, dan is dat “voo”, “oor”, “orb”, etc. Voor bepaalde taalproblemen zijn niet de woorden, maar wel ngrams de werkmiddelen.

Wat op het eerste zicht een triviaal probleem lijkt, resulteert al snel in een dubbele for-lus, met daarin de “substr”-variant van de gebruikte taal. Aangezien dat er volgens mij ongelooflijk lelijk uitziet, heb ik blijven zoeken naar een andere oplossing. Met een goeie voorzet van iemand op IRC kwam ik tot de volgende oplossing:

>> word = "voorbeeld"
>> word.split('').each_cons(3){|n| puts n.join }
voo
oor
orb
rbe
bee
eel
eld
=> nil

Dit gebruikt ‘enumerator’ voor de each_cons-methode!. Natuurlijk ga ik de resultaten niet gewoon uitschrijven, maar ik sla ze op in een gewone array om dan verder te gebruiken.

Op zich ziet het er wel beter uit dan een dubbele for-lus, maar natuurlijk blijft het een heel kostelijke operatie. Er wordt gegoocheld met arrays, deze worden omgezet in dubbele arrays, en uiteindelijk wordt elk onderdeel terug samengesteld. De split met de lege string vind ik ook geen schitterende oplossing…

Op zich dus een moeilijke keuze (one-liner tegen ik-vind-dat-vieze-code). De dubbele lus zou al snel duidelijker zijn voor mensen die voor het eerst naar de code kijken, zeker met een substr erin. Maar dan opteer ik voor goed commentaar:

...
# Make ngrams with length: word="example", length=3 => "exa", "xam", "amp", "mpl", "ple"
word.split('').each_cons(length){|n| ngrams < < n.join }
...

Dat is toch een stuk duidelijker lijkt me.