Elixir et le module Agent

Voici un petit article sur le module Agent Elixir. Qu’est-ce qu’un Agent? Il faut voir cela comme un key /value store, une sorte de Redis vous permettant de stocker par exemple l’état d’une partie de poker ou tout autre information sur l’état de votre application. Un Agent est un serveur léger permettant de stocker et de mettre à jour un état. Cet état est alors accessible par tous les processus de l’application.

Pour instancier un Agent nous avons à disposition la méthode start_link/1

Ensuite le module Agent nous permet de récupérer l’état à l’aide de la méthode get/2. Cette méthode se veut flexible, on ne veut pas tout le temps récupérer l’intégralité de l’état, on ne souhaite bien souvent qu’une partie de l’état. Par exemple dans le cas d’une partie de poker, on souhaite récupérer la main d’un joueur pour pouvoir l’afficher. Pour permettre cela la méthode get/2 demande en paramètre une fonction prenant en paramètre l’état courant et retournant ce que nous souhaitons avoir. Voici un exemple:

Créons l’Agent avec un état initial:

Maintenant faisons appel à la méthode get/2 pour extaire la main du premier joueur. Pour cela il nous faut définir une méthode prenant en paramètre l’état courant.

Cette méthode nous permet de récupérer la main du premier joueur. C’est vrai, cela fonctionne. Mais en utilisant le pattern matching d’Elixir, il y a moyen de faire beaucoup mieux que ça. Voici une version exploitant les capacités de pattern matching. J’aime utilisé cette technique dans le paramètre même de la fonction.

La fonction est grandement simplifiée, tout est traitée dans le paramètre de la fonction. Il est maintenant possible de convertir la fonction en une fonction anonyme comme suit:

La mise à jour de l’état fonctionne de la même façon, la méthode update/2 prend une fonction en paramètre. Cette fonction prend l’état en paramètre. Il faut que cette fonction retourne le nouveau paramètre mis à jour.

Par exemple, ajoutons un nouveau joueur à notre liste de joueurs de poker. Nous allons reprendre notre statut initial et y ajouter un nouveau joueur:

Pour ajouter ce joueur, mettons en place la méthode nous permettant cela. Comme vous vous en doutez, le state est immuable c’est à dire que je ne peux pas me contentez de simplement mettre à jour une partie du state et de le renvoyer. Il faut que je le copie.

C’est bien ce que l’on veut mais le problème est que cette fonction ne correspond à la signature de la méthode demandée par Agent.update(agent, fun). Nous avons le paramètre du nouveau joueur qui est en trop. Pour  régler ce problème, nous allons faire du currying.

Pour ceux qui ne savent pas ce qu’est le currying, est la transformation d’une fonction à plusieurs arguments en une fonction avec moins d’argument. Elixir permet de faire cela assez simplement comme vous allez le voir dans l’exemple suivant.

Il y a encore bien des choses à voir sur l’Agent pour en avoir une connaissance complète mais cet article nous donne déjà de quoi faire de belle choses avec le module Agent.


Advertisements

Elixir et le module Task

Hello les loulous! Oui Elixir est un beau langage. Cet remarque est purement personnelle et ne repose sur aucun argument technique. Mais c’est ainsi. Elixir est mon jouet. Je ne code pas professionnellement avec. Je l’utilise pour apprendre le paradigme fonctionnel. Certains râleurs diront que ce n’est pas le meilleur langage pour apprendre le fonctionnel et qu’il serait mieux de commencer par Lisp. Mais comme c’est écrit sur le bavoir ci-dessous, “je m’en fish”.


Aujourd’hui j’aimerais vous présenter le module Task.

Task spawn un processus pour exécuter une tâche précise passée en paramètre. Le plus souvent le processus est isolé, il ne cherche pas à communiquer avec d’autres processus. Le use case le plus fréquent est de créer une tâche dans le but de convertir des données ou de faire un calcul pouvant être fait en parallèle. Le concept principal d’une Task est la conversion de code séquentiel en code concurrent.

Cela me fait penser à la création de background jobs avec Sidekiq en Ruby. Mais les projets Ruby se rapprochant le plus des Tasks Elixir sont celluloid et concurrent-ruby.

Le module Task est celui se rapprochant le plus d’un processus Elixir. Task.start permet de lancer un processus Elixir comme avec spawn.

Task.start(fn() -> 2 * 2 end)

Mais son utilité est limitée car la valeur du processus n’est pas retournée. Il y a surement des cas ou cela semble intéressant mais ce n’est pas la raison principale de l’utilisation de Task.

Ne nous attardons pas sur cette méthode et intéressons nous plutôt aux méthodes Task.async et Task.await. Ce duo de méthodes nous permet de lancer l’exécution d’une fonction en parallèle et d’en récupérer la valeur. Tout comme start la méthode async nous permet de lancer une processus. La différence est qu’async retourne une Task struct. Cette struct peut être ensuite passée à await pour récupérer le résultat de la fonction.

Voili. C’est tout pour cette petite introduction aux Tasks Elixir. Si vous avez déjà lu des choses sur ce joli langage, vous remarquerez que je ne parle pas du tout de Supervision. La raison en est que je ne maitrise pas encore cette partie. Dès que j’en saurais plus sur ce sujet, je ferais une note dessus.

Hanami my personal return of experience

TL;DR Hanami may be nice on paper but it’s too constraining when it comes to work on real life situations. I’m sorry to say this but Hanami is a hipster framework.

Hanami documentation consits of a starter guide and that’s all. No in-depth documentation. You’ll rapidly notice that if you look for a problem on the web, you won’t get any Stackoverflow answers cause it’s not used that much.

Few weeks ago, I had a problem I was not able to fix, I’ve posted a question on Gitter and nobody replied. The question have posted twice.

Yesterday, I had a problem with Hanami to execute a ‘group by’ and ‘count’ query. Reading the Rom-rb documentation – not the Hanami one – I found the method group_and_count. Perfect isn’t it? But no! It was to good to be true. In Hanami, the repository running a query will always map the result with attributes of its associated entity. And what about extra fields from the result? There are omitted. As simple as that. No easy way to get the raw data fron the query. No, it would be too easy.

One guy had kind of the same problem (https://github.com/hanami/model/issues/466), he got the advice to use another entity with the same fields as the query result. Ok, where is the documentation about how to map the result to another entity? Please tell me, cause personally I don’t know.

There is a map_to method that could do the job but it returns the same object without any modification. Maybe I did something wrong but again, where is the documentation to tell me I’m wrong?

I’ve reproduced my problem with a Rom-rb example and I’ve been able to fix it easily with the as_hash method but in Hanami this method is not accessible on the Rom::Relation object we have access to. Why? I guess it’s because Hanami developers like restrictions.

To be able to fix my problem with this framework, I had to get access to the Sequel::Dataset object and do the call by myself.

As a conclusion, Hanami is too hipster for me. When I use a tool it’s to get things done with not to have hard time trying to fix problems that should not exist.

How I stopped coffee

Why i decided to stop drinking coffee

25 years of drinking coffee everyday. 25 years of having difficulties to sleep correctly. 25 years of feeling irritable. It was time to do something. Here is my little story about why I decided to stop drinking coffee.

At my parents

As a teenager, I could always find a coffee at any time of the day in the kitchen. My mother was making sure the coffee machine was full all day long. At that time two things were important for her a full packet of cigarettes and a full cup of coffee. She liked black coffee. No sugar, no milk, just a dark one. I never got hooked to smoking but the coffee rapidly became a part of me. My breakfast and after lunch coffee were the most important.

I was a student in an engineer school close to Paris and my studies were the priority number one. The only thing that mattered was my diploma. And coffee was here to give me this boost of energy I needed to succeed. It was my best ally.

This beverage was something positive for me. It was a real help for the student I was and I really liked the drink. The smell of it was captivating. I liked to train myself to be able to differentiate arabica and robusta coffees. I was playing the coffee connoisseur.

At my apartment

When I got my first apartment, my coffee habits changed a little bit. I didn’t have an electrical coffee machine. To honore my italian roots, I’ve chosen an italian one.

These machines are used in my family on sundays when the whole family is gathering. Special day so special coffee machine. We were not crazy about coffee, it’s just part of the culture we have.

At work

One thing I didn’t tell is I work in the IT, more precisely in startups. In these companies two things are important a powerful apple laptop and a nice cup of coffee laying on the side. It was part of the startup way of life.

alt text

At some point, I realized I wasn’t drinking water anymore. Coffee was there to hydrate my body. And during long work days, coffee was a great help.
In fact, I thought it was but I was just blind.

I even worked in a company having it’s own coffee machine to create cappuccinos like in coffee shops. A must! First their was the coffee addiction and also the challenge of making a good cappuccino. Total addiction loop…

The challenge

At that time, I started to have sleeping problems. I thought it was mainly because of my environment, the noise of the street for example.

Making a complete night from start to end was clearly not me. When I was able to read 4:00 AM on the clock, I knew that the night would be long. And boring. Watch the ceiling is ok the five first minutes but after that it’s annoying.

Another thing that annoyed me was that I had a tendency to be too emotional. Others would say I was on the nerves. I was irritable and had a negative view of the world.

That’s when I decided to do a coffee break. That was the beginning of a difficult journey. This path was a real pain.

The first days the strong headaches I had demonstrated me how I was dependent of this beverage. M brain was craving for caffeine. In fact, my brain was not able to work without its dose of caffeine. I was a coffee junky!

On my way to work, in the metro, I was feeling dizzy and my body couldn’t bear this lack of caffeine.

The worst was at the office. It seemed my brain was not awaken. When you’re watching television it’s ok to feel sleepy but when you have to deal with technic problems it’s another story. Furthermore when you work with colleagues drinking coffee and feeling energized. You feel like everyone will notice that you’re slow like a snail.

This is a hard moment cause it’s when you start thinking that a sip of the beverage will give you the boost you need to clear your thoughts. After all, a small cup is not that harmful. But if you start with one cup, you will finish the day with three empty cup of coffee on your desk. And you will be an the drinking bandwagon with nothing to stop you. The first times, I tried to stop I generally ended by doing this kind of mistake.

One interesting thing when you are not drinking coffee is that you are more conscious of the amount of cups your colleagues drink. And that’s a lot. It makes more conscious of fact that in general we drink to much of this dark beverage. They drink it like water. Like I was doing before.

It’s now 3 weeks since I’ve stopped and I’m not sure it’s completely alright. I’ve overcome the feeling bad period now I have to succeed on the long run. It’s the forth or fifth time I’m trying to stop and I always end up with a cup in my hand again. Will this be the good one? I hope. I’ll tell you this in few weeks.

Colemak keyboard Layout

After more than 10 years of Qwerty, I’m switching to Colemak.

Why?

I’ve realised alternative layouts are quiet popular in the Ruby on Rails community and in my company some people uses Dvorak layout. So I’ve started to read about the Qwerty alternatives. My interest got attracted by the Colemak and the Norman. They are just iterations of our good Qwerty so they are easy to learn.

I’ve finally chosen Colemak cause it has a better distribution of keys accross all fingers.

Use template for your commits

Yes it’s great to add descriptions and unicorns 🦄 in your tickets and pull request but where content is really needed is in your commits. It will always be connected to your code. It’s a reference we (developers) have to care about.

 

So your commits needs to be structured and they need to contain data. That’s way a simple commit template allow this.

 

Here is my personal commit template:

 

“`
feat: add hat wobble
^–^ ^————^
| |
| +-> Summary in present tense.
|
+——-> Type: chore, docs, feat, fix, refactor, style, or test.

 

Types:
chore: add Oyster build script
docs: explain hat wobble
feat: add beta sequence
fix: remove broken confirmation message
refactor: share logic between 4d3d3d3 and flarhgunnstow
style: convert tabs to spaces
test: ensure Tayne retains clothing
wip: not finished yet!
“`

 

Try it on few commits and you’ll how it make your git log more useful.

 

Difference between Kernel.load and Kernel.require

First of you may ask yourself: “But gosh! What is the difference between ‘require’ and ‘Kernel.require’?”. And the response is NONE! It’s the same. Ruby loads the Kernel module without a receiver and thus can be called in functional form:

sprintf "%.1f", 1.234 #=> "1.2"

or

require "my_class"

Basically Kernel.load will reload every time the file.

Where Kernel.require will load the file just once and return true. If already loaded, it returns false.

So you have to manipulate them carefully. For example,

# foo.rb
puts "loading file"
MY_CONST = 4

The first `Kernel.load(‘foo.rb’) will be fine.
But the second will output an error:

 warning: already initialized constant MY_CONST

Where with Kernel.require, it will always works fine cause the second time, require won’t load the file.

Knowing the difference between both is interesting afterward when you dig in the way Rails load it’s dependencies:

https://guides.rubyonrails.org/autoloading_and_reloading_constants.html

Resources

Create a Rake task using Rake::Task

Yes it’s true you can create a rake task in a rake file this way:

namespace :my_namespace do
  desc "TODO"
  task :my_task1 => :environment do
    puts "DONE! 🎉"
  end

But let’s say, you want a gem to make available a rake task in the app loading it.

The Rakefile of your application could look like this:

require_relative 'config/application'
Rails.application.load_tasks

require "my/gem/rake_task"
My::Gem::RakeTask.load

The 2 last lines inject your new rake task in Rake.applications.tasks.

The My::Gem::RakeTask.load could load a rake file located in your gem but it’s not really clean.
Another solution could be to implement directly your task in My::Gem::RakeTask.load.

The code could look like this:

# Main method
def self.load
  task_name = "gem:migrate"
  task_comment = "Run gem migrations"

  Rake::Task.define_task(Rake::Task.new(task_name, Rake.application))
  migration_task = Rake::Task[task_name]
  migration_task.enhance { Api::Interface::Migrations::Migrator.call(gem_name) }
  migration_task.comment = task_comment
end

This code would create a rake task ‘gem:migrate’ with the code Api::Interface::Migrations::Migrator.call(gem_name).

Notice that the task is created Rake::Task.new and stored Rake::Task.define_task and then fetched back Rake::Task[task_name]
before any modification made on it.
It’s the only solution I found to keep the task’s comment.
Else it is always lost when storing the task afterward.

What I’ve learned

I’ve discovered a rake task has a list of actions.
It’s a list of code blocks executing sequentially.
I thought it just had one code block but in fact it’s a list.

Reloading your gem in the dummy app

Where is the dummy Rails app?

The dummy app is a Rails app located in

my_gem
└── test
    └── dummy

It allows to test the gem directly in an app.

How to reload the Gem on modification?

This is done in 3 steps :

  • in Gemfile, add the option require: false:
    gem 'my_gem' , path: '../..', require: false
  • in config/application.rb, insert the lib directory of the gem in the autoload_paths:
    config.autoload_paths << File.absolute_path(File.join(Dir.pwd, "../../lib"))
  • in the main Controller require the gem with the command require_dependency:
    require_dependency 'my_gem'

Now on every modification in the gem, the dummy app will reload the gem’s code.

Resources

Benchmarking sorting algorithms in Ruby

For some time now, I wanted to try the implementation of some simple sort algorithms in Ruby. So I did!

I’ve implemented 4 sorting algorithms:
– Quick sort
– Merge sort
– Bubble sort
– Binary tree sort

Quick sort

It’s one of the most efficients. In average, it makes O(n.log(n)) comparisons to sort n items. This is kinda good.

Concept

It takes a pivot element and moves all the inferior elements to the left part of the array and all the superior ones to the right. It iterates on the 2 sub arrays until it has just a one value array. The array is then sorted.

module QSort
  def self.sort(ar)
    return ar if ar.size = 1

    pivot = ar.pop
    sub1 = []
    sub2 = []

    ar.each do |elem|
      (elem = pivot) ? sub1.push(elem) : sub2.push(elem)
    end

    sort(sub1) + [pivot] + sort(sub2)
  end
end

Benchmarks

To sort an array of 500'000 random integers
  user     system      total        real
  3.220000   0.030000   3.250000 (  3.256061)

To sort an array of 1'000'000 random integers
      user     system      total        real
  6.680000   0.130000   6.810000 (  6.845635)

Note

One thing that could be nice is to implement a version using in-place swapping not requiring extra arrays.

Merge Sort

Merge sort is a divide and conquer algorithm. It’s a stable algorithm which means it has the same complexity in average or worst case scenario: O(n.log(n)).

Concept

First, it divides the list in sub-lists until having just one-element lists.
Second, it merges the lists knowing the lists are ordered.

# Merge sort - Tri fusion
module MergeSort

  # merge 2 ordered lists
  def self.mergeList(a, b)
    return b if a.empty?
    return a if b.empty?
    (a[0] = b[0] ? [a.delete_at(0)] : [b.delete_at(0)]) + mergeList(a, b)
  end

  def self.sort(a)
    return a if a.size = 1
    b = a.slice!(0..(a.size/2 - 1))
    mergeList(sort(a), sort(b))
  end
end

Benchmark

The problem with this algorithm or maybe more with Ruby is that if you want to sort a big list (i.e. 1’000’000 elements) you get a ‘Stack level too deep’ exception in your face ! I guess it’s a Ruby problem, I should test it with another language to compare.

I can not even ask it to sort a 100’000 elem lists. I’m a little bit upset there…

I finally found a solution. The easiest way to fix this is increasing the Stack Size of Ruby VM, setting the RUBY_THREAD_VM_STACK_SIZE environment variable:

export RUBY_THREAD_VM_STACK_SIZE=50000000
To sort an array of 100'000 random integers
user      system   total     real
43.790000 0.860000 44.650000 ( 44.763988)

It’s deceiving, I was expecting better performance.

Bubble sort

This is the most time consuming one. The complexity of this one is O(n2) in every scenario (average or worst).

Concept

It repeatedly steps through the list to be sorted, compares each pair of adjacent items and swaps them if they are in the wrong order. Pretty simple no?

module BubbleSort
  def self.sort(ar)
    return ar if ar.size <= 1

    swapped = false
    loop do
      for i in 0..(ar.size - 2) do
        if ar[i] > ar[i + 1]
          ar[i], ar[i + 1] = ar[i + 1], ar[i]
          swapped = true
        end
      end
      break if swapped == false
    end
    return ar
  end
end

Benchmarks

For 1’000’000 entries, I can’t let my computer turn all night. So no benchmark there.

Tree sort

Concept

This one is nice. The idea is to insert list’s elements in a sorted binary tree. Each node has all its inferior elements to the left and all higher ones to its right. Once this insertions are done, we just have to flatten the tree to create the ordered list.

The insertions takes on average O(n.log(n)) which is pretty good.

# Binary tree sort - Tri arborescent
# Tree struct: [leftTree, value, rightTree]
module BinaryTreeSort

  # building the tree
  def self.insert(tree, value)
    return [nil, value, nil] if tree.nil?
    if value <= tree[1]
      [insert(tree[0], value), tree[1], tree[2]]
    else
      [tree[0], tree[1], insert(tree[2], value)]
    end
  end

  # convert the tree to an array
  def self.flatten(tree)
    return [] if tree.nil?
    flatten(tree[0]) + [tree[1]] + flatten(tree[2])
  end

  def self.sort(ar)
    return ar if ar.size <= 1
    tree = nil
    ar.each do |elem|
      tree = insert(tree, elem)
    end
    return flatten(tree)
  end
end

Benchmarks

To sort an array of 500'000 random integers
       user     system      total        real
  9.430000   0.100000   9.530000 (  9.573206)

To sort an array of 1'000'000 random integers
       user     system      total        real
 20.080000   0.090000  20.170000 ( 20.239815)

Dealing with the RTL8723BE Wireless Network Adapter & Ubuntu

This wifi card is killing me …

2 years ago I’ve bought a Lenovo laptop. Ubuntu got installed smoothly on it. The only problem was the wifi. It was constantly being disconnected. That’s when I discovered my new laptop had this disease, it has the RTL8723BE Wireless Network Adapter.

After some research on internet I found that adding a configuration file for the dedicated kernel module would solve the problem.

echo "options rtl8723be fwlps=0" | sudo tee /etc/modprobe.d/rtl8723be.conf

The wifi was running without any problem. Happy ending, I was glad with my Ubuntu laptop running nicely.

1 week ago, wanting to put my hands on a new piece of hardware, I’ve acquired a HP something laptop. The thing I’m interested in with this laptop is that it has 4 cores. This will allow me to do some benchmarking using some Elixir code. So I’ve done another smooth installation of Xubuntu. (yes I’ve switched in between to XFCE which is light, simple and so nice. After Unity and Gnome 3, XFCE is way more fun and fast). I was glad again but suddenly the wifi stopped. I checked the hardware and discovered this laptop also have the RTL8723BE Wireless Network Adapter. I was really pissed off. I was really close to throw the laptop by the window and buy a Macbook Pro. But searching again on Google, I found a project (https://github.com/lwfinger/rtlwifi_new) developing alternative drivers for these kind of wifi cards. So I’ve decided to give it a try like the last trial.

git clone https://github.com/lwfinger/rtlwifi_new.git
cd rtlwifi_new

make all
sudo make install
sudo modprobe rtl8723be

Yes! Finally it was working again. But the downloading rate was not crazy. So I did some tweaking adding options to the config.


options rtl8723be fwlps=0 ant_sel=2 | sudo tee /etc/modprobe.d/rtl8723be.conf

The option `ant_sel=2` makes all the difference. Funny thing is the dl rate is higher than on my previous laptop. So like good Disney cartoons, everything ends well.

 

 

What will make you a better Elixir developer?

 

Practising, practising and practising. That’s it 🙂

So that’s what I did. During job interviews, you get these coding challenges, some are good, some are bad. I remember one: the bowling kata which is quiet fun.

Here is the description of the coding test:

Create a program, which, given a valid sequence of rolls for one line of American Ten-Pin Bowling, produces the total score for the game. Here are some things that the program will not do:

  • We will not check for valid rolls.
  • We will not check for correct number of rolls and frames.
  • We will not provide scores for intermediate frames.

Depending on the application, this might or might not be a valid way to define a complete story, but we do it here for purposes of keeping the kata light. I think you’ll see that improvements like those above would go in readily if they were needed for real.

We can briefly summarize the scoring for this form of bowling:

  • Each game, or “line” of bowling, includes ten turns, or “frames” for the bowler.
  • In each frame, the bowler gets up to two tries to knock down all the pins.
  • If in two tries, he fails to knock them all down, his score for that frame is the total number of pins knocked down in his two tries.
  • If in two tries he knocks them all down, this is called a “spare” and his score for the frame is ten plus the number of pins knocked down on his next throw (in his next turn).
  • If on his first try in the frame he knocks down all the pins, this is called a “strike”. His turn is over, and his score for the frame is ten plus the simple total of the pins knocked down in his next two rolls.
  • If he gets a spare or strike in the last (tenth) frame, the bowler gets to throw one or two more bonus balls, respectively. These bonus throws are taken as part of the same turn. If the bonus throws knock down all the pins, the process does not repeat: the bonus throws are only used to calculate the score of the final frame.
  • The game score is the total of all frame scores.

Examples:

  • [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10] should return 300
  • [9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9 ] should return 190
  • [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5] should return 150
  • [9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0] should return 90
I’ve put my answer to this problem in a Github Gist.

First steps with Elixir

Functional programming languages (FPL) are becoming more and more popular. Not sure if they are more and more used but at least they are more and more discussed on the web.

I’ve finally decided to take the time to learn one of these FPL. And there was the problem, which one to choose! There is so many of them.

After some reading and some stupid google query searchHaskell seems nice but a little bit too complicated to start with. So I looked at Clojure, Scala, and list goes and goes. But there is something I didn’t tell you about me, I’m a Ruby on Rails developer. And there is one FPL with a syntax close to Ruby based on a good FPL from the 80s: Elixir.

Elixir is a FPL based on Erlang with a nice and simple syntax close to Ruby. One another important thing made me pick Elixir, its getting started documentation, it’s just awesome. It took me some days to go through it. It’s a good piece of documentation with relevant examples.

I’m just at the first stage of discovering this interesting language. Some updates soon.

 

Gitweb configuration, the easy way

Ok if you have juste one git repository, git instaweb is for you. This command automatically generate the config to connect with a webserver installed on your server. I recommand you to try, it’s impressive as it’s simple. For me the best config is :

git instaweb -d webrick

Now if you have several git projects as I am, you want to use gitweb. In fact instaweb uses the gitweb script but configured for one specific repository. The script is in .git/gitweb/gitweb.cgi .

On Ubuntu, install the script with the command:

apt-get install gitweb

I’m going to assume you have apache2 and mod_perl installed. So in the config file

/etc/apache2/sites-enabled/000-default

add this config at the end of the VirtualHost block:

ScriptAlias /git “/usr/lib/cgi-bin/gitweb.cgi”
<Directory “/home/git/”>
Options Indexes FollowSymLinks ExecCGI
Order allow,deny
Allow from all
</Directory>

Now you just have to configure gitweb by setting the directory containing your git projects in the file:

/etc/gitweb.conf

Finally, restart apache and you should be able to browse your projects on this url:

http://localhost/git

XML to NSDictionary Converter

I found recently a nice lib easily converting XML to NSDictionary. The code is now on GitHub.

Here are the key ideas:

  1. XML elements map to key names in the dictionary
  2. Each element corresponds to a child dictionary
  3. Attribute key-value pairs are added to the element’s child dictionary
  4. Strings from text nodes are assigned to the child dictionary’s “text” key
  5. If an element name is encountered multiple times, the value of the element is set to an array of children dictionaries

For a more detailed presentation.

A detailed example:

The XML to parse:

//    <items>
//        <item id=”0001″ type=”donut”>
//            <name>Cake</name>
//            <ppu>0.55</ppu>
//            <batters>
//                <batter id=”1001″>Regular</batter>
//                <batter id=”1002″>Chocolate</batter>
//                <batter id=”1003″>Blueberry</batter>
//            </batters>
//            <topping id=”5001″>None</topping>
//            <topping id=”5002″>Glazed</topping>
//            <topping id=”5005″>Sugar</topping>
//        </item>
//    </items>
//

The Code:

NSString *testXMLString = @”<items><item id=\”0001\” type=\”donut\”><name>Cake</name><ppu>0.55</ppu><batters><batter id=\”1001\”>Regular</batter><batter id=\”1002\”>Chocolate</batter><batter id=\”1003\”>Blueberry</batter></batters><topping id=\”5001\”>None</topping><topping id=\”5002\”>Glazed</topping><topping id=\”5005\”>Sugar</topping></item></items>”;

// Parse the XML into a dictionary
NSError *parseError = nil;
NSDictionary *xmlDictionary = [XMLReader dictionaryForXMLString:testXMLString error:&parseError];

// Print the dictionary
NSLog(@”%@”, xmlDictionary);

The result

// xmlDictionary = {
//    items = {
//        item = {
//            id = 0001;
//            type = donut;
//            name = {
//                text = Cake;
//            };
//            ppu = {
//                text = 0.55;
//            };
//            batters = {
//                batter = (
//                    {
//                        id = 1001;
//                        text = Regular;
//                    },
//                    {
//                        id = 1002;
//                        text = Chocolate;
//                    },
//                    {
//                        id = 1003;
//                        text = Blueberry;
//                    }
//                );
//            };
//            topping = (
//                {
//                    id = 5001;
//                    text = None;
//                },
//                {
//                    id = 5002;
//                    text = Glazed;
//                },
//                {
//                    id = 5005;
//                    text = Sugar;
//                }
//            );
//        };
//     };
// }
//

Install Rmagick on Mac OS X

I like to use the standard ruby tools when developing with Rails. So if I have a gem to install, I won’t use ‘apt-get install’ or ‘port install’, I will use ‘gem install’. To install Rmagick the command is:

sudo  gem install rmagick

And the result is :

Building native extensions.  This could take a while…
ERROR:  Error installing rmagick:
ERROR: Failed to build gem native extension.

/usr/local/bin/ruby extconf.rb
checking for Ruby version >= 1.8.5… yes
checking for gcc… yes
checking for Magick-config… no
Can’t install RMagick 2.13.1. Can’t find Magick-config in /usr/local/bin/:/opt/local/bin:/opt/local/sbin:/usr/local/mysql/bin/:/usr/bin:/bin:/usr/sbin:/sbin

*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers.  Check the mkmf.log file for more
details.  You may need configuration options.

Provided configuration options:
–with-opt-dir
–without-opt-dir
–with-opt-include
–without-opt-include=${opt-dir}/include
–with-opt-lib
–without-opt-lib=${opt-dir}/lib
–with-make-prog
–without-make-prog
–srcdir=.
–curdir
–ruby=/usr/local/bin/ruby

Gem files will remain installed in /usr/local/lib/ruby/gems/1.8/gems/rmagick-2.13.1 for inspection.
Results logged to /usr/local/lib/ruby/gems/1.8/gems/rmagick-2.13.1/ext/RMagick/gem_make.out

It seems there are dependencies not installed. To solve this problem, I will use macport and install the necesary libs with the command:

sudo port install tiff -macosx imagemagick +q8 +gs +wmf

After a bunch of compilation, I relaunch my gem command :

sudo gem install rmagick

And “Voila!” it works. Now have fun with RMagick functionalities.

Killer tool to develop on iPhone: ack-grep

When developing for iPhone, the IDE coming in mind is XCode and it’s a good thing cause XCode is a good piece of software. I use XCode everyday but I never found the search functionality good enough. That’s why I switched to ack-grep. It’s a little perl script way faster than grep or any other search functionality. And the result presentation is clear and efficient.

Recently, I had to work on an complex iPhone application developed by another company. ack-grep helped me a lot to dig in the hairy code. Since I’m using this tool I can’t work without it.

The installation is easy, it’s worth a try.