Coding is an Art

Anoiaque::Ergasterium

20/10/2010

Install ruby 1.9.2 on snow leopard : readline compile error

Even if i had readline installed on my system in /usr/local, i still get the same (readline) error at compile of ruby 1.9.2 when i try to install it with rvm.

I remedy that compile error like that:

  • (re)install libxml2:
  • tar xzvf libxml2-2.7.3.tar.gz  
    cd libxml2-2.7.3 
    ./configure --with-python=/System/Library/Frameworks/Python.framework/Versions/2.3/ 
    make 
    make install
  • (re)install readline
  • curl -O ftp://ftp.cwru.edu/pub/bash/readline-6.0.tar.gz
    tar xvf readline-6.0.tar.gz
    cd readline-6.0
    ./configure && make && make install
  • Then install readline via rvm package :
  • rvm package install readline  

17/10/2010

Recursive Hash#sort and Array#to_hash

Ruby standard Hash#sort method does not sort recursively an hash.
Here is a method that do the job.
It recursively sort the hash using Array#sort and return the sorted array.


 class Hash
   
    # Return array from hash recursively sorted
    def to_sorted_array block=nil
      sort(&block).inject([]) do |array, (key, value)|
        value = value.is_a?(Hash) ? value.to_sorted_array : value
        array << [key, value]
      end
    end
    
  end


hash={'user' => {'adress' => {'town' => 'Paris', 'street' => "rue de Quimper"}, 'name' => 'toto', 'age' => 12}}
hash.to_sorted_array # =>
[["user", [["adress", [["street", "rue de Quimper"], ["town", "Paris"]]], ["age", 12], ["name", "toto"]]]]



The Array#to_hash ruby standard method do not transform an array into an hash equivalent, recursively.
Here is a method which do the job:

class Array
  # Recursively convert array to hash 
  def to_hash 
    inject({}) do |hash, (key, value)|
      value = value.to_hash if value.kind_of?(Array)
      hash.merge!({key => value})
    end
  end
    
end

  array = [["user", [["adress", [["street", "rue de Quimper"], ["town", "Paris"]]], ["age", 12], ["name", "toto"]]]]
  array.to_hash
  
  {"user"=>  {"name"=>"toto", "adress"=>{"street"=>"rue de Quimper", "town"=>"Paris"}, "age"=>12}}

I' ve put these extensions into a library on github : ruby_extensions

To install the gem :
gem install ruby_extend

03/09/2010

Why :_:: == :_ is true in Ruby

The origin of this post is a tweet of PragDav Retweetted by Igrigorik (http://twitter.com/igrigorik/status/22767684142)
I've digged a bit to answer why :_:: == :_ is evaluated to true.

First, you can access to instance or class methods in ruby like this : Foo.new::say_hello => "Hello"

:_ is a symbol so an instance of Symbol class

So
:_ has methods(you can list it by :_::methods)

Therefore
:_:: == is the call to the method == of the instance :_ of the Symbol class

Therefore
:_::==:_ can be interpreted as == (:_, :_) where == is the method

As == (:_, :_) is true , :_::==:_ is true



QED

18/07/2010

How to get and send image with Rails without paperclip or other image gem

How to get an image or binary data from an input file from client side, without paperclip or other image gem.
class Picture < ActiveRecord::Base 
  
  def image_file=(uploaded_data)
    self.content_type = uploaded_data.content_type
    self.filename = uploaded_data.original_filename
    self.image_data = uploaded_data.read
    self.size  = uploaded_data.size 
  end
  
end

In controller, to get the file data and to send it to client :

class PicturesController < ApplicationController
  
  def update
    @picture.image_file = params[:picture] #FileTemp object
    @picture.save
  end
  
  def code_image
    @image_data = Picture.find(params[:id])           
    @image = @image_data.binary_data           
    send_data (@image, :type => @image_data.content_type, :filename => @image_data.filename, :disposition => 'inline') 
  end

end

String concatenation benchmark in ruby

What to use for concatenate strings in ruby , "+=" or "<<" or concat() ? Here is a benchmark that can guide if concatenations is in a loop.
def benchmark_string_concatenation n
Benchmark.bm(10) do |x|
x.report("With '+=' :") {string = ""; n.times {|n| string += "e"} }
x.report("With '<<' :") {string = ""; n.times { |n|string << "e"} }
x.report("With #concat :") {string = ""; n.times { |n|string.concat("e")} }
end
end


Results with n = 5000:
              user      system    total     real
With '+='   : 0.010000 0.010000 0.020000 ( 0.022831)
With '<<'   : 0.000000 0.000000 0.000000 ( 0.001734) 
With concat : 0.000000 0.000000 0.000000 (0.001689)


Results with n = 50000:
                user    system    total   real
With '+='   : 0.710000 0.000000 0.710000 ( 0.737932)
With '<<'   : 0.020000 0.000000 0.020000 ( 0.019771)
With concat : 0.020000 0.000000 0.020000 ( 0.019853)

Recursively chained send on an object with Array#inject

Suppose you have an arbitrery and dynamic list of methods to call on an object.
For example you have Cat class with methods :
#drink_milk
#sleep
#climb_curtain
#purr
And you want a method taking an arbitrery list of actions to execute as parameter.
With powerful inject method ... so easy to do :

class Cat

  def drink_milk
    puts "I drink milk"
    self
  end

  def sleep
    puts "I sleep"
    self  
  end

  def climb_curtain
    puts "I climb the curtain"
    self  
  end

  def purr
    puts "Miaouu"
    self  
  end


  def do_these_things actions
    actions.inject(self) {|cat, action| cat.send(action)}
  end

end

cat = Cat.new
cat.do_these_things [:sleep, :drink_milk] # => I sleep I drink milk
cat.do_these_things [:purr, :drink_milk, :climb_curtain] # => Miaouu I drink milk I climb the curtain

02/05/2010

Exporter une collection d'objets ruby vers un fichier excel

Permet d'exporter des collections de différentes classes.
Permet d'inclure les attributs d'associations.

Installation :
gem install to_excel
Source + documentation : to_excel github repository
Gemcutter : to_excel gem

Fools ignore complexity. Pragmatists suffer it. Some can avoid it. Geniuses remove it.
Alan Perlis


The best way to predict the future is to invent it.
Alan Kay


Ne découvre de nouvelles terres que celui qui sait quitter tout rivage.
André gide


Qui ne doute pas acquiert peu
Léonard de Vinci


Our life is frittered away by detail... simplify, simplify.
Henry David Thoreau