Thursday, December 28, 2006

functional programming, json, mochikit

Through a javascript one liner, Delicious allow to retrieve tagged content ( via JSON, previously discussed)
<script type="text/javascript" src="http://del.icio.us/feeds/json/nrolland?count=20"></script>
The format under which data are received is the following :
Delicious.posts =
[{"u":"http://www.napyfab.com/ajax-indicators/",
 "d":"AJAX Activity Indicators",
 "t":["web2.0","javascript","design","graphics","webdesign","ajax","icons"]}]
If those tagged posts are to be processed, functional programming can help reduce significantly the amount of code needed. Example : Let's say I want to retrieve only those posts tagged with selected categories, and have them accessible through those categories. My navigation box on the right here is a simple example of that. Here's how I might do it in javascript, starting from imperative constructs to functional ones :
//v1 //v2 //v3 //v4 //v5 //v6 //v7

Thursday, December 14, 2006

RailsDay goodness at your fingertip

Who's going to thank Nicolas ? Now you can get all the wonderful applications crafted at the RailsDay in a single command. And they are ready for you to import into your RadRails environment too.. [railsday.rb]
def team_to_project(team)
    `mkdir "RadRails#{team}"`
    puts "Start fetching SVN for Team #{team}"
    `svn co  "http://svn.railsday2006.com/railsday/team#{team}" "RadRails#{team}`
        radrailsproject  =  <<-end_eval
<?xml version="1.0" encoding="UTF-8"?>
    <projectDescription>
        <name>RadRails#{team}</name>
        <comment></comment>
        <projects>
        </projects>
        <buildSpec>
            <buildCommand>
            <name>org.rubypeople.rdt.core.rubybuilder</name>
                <arguments>
                </arguments>
            </buildCommand>
        </buildSpec>
        <natures>
            <nature>org.rubypeople.rdt.core.rubynature</nature>
        </natures>
    </projectDescription>
    end_eval

    File.open("RadRails#{team}/.project","w") do |f|
        f << radrailsproject
    end
end

def fetch(range)
    range.entries.each do |team|
        team_to_project team
    end
end
After, just run an irb session and type in
require 'railsday'
fetch(1..183)
And there you go !

Labels: , ,

singleton class in ruby

A central concept in Ruby metaprogramming is the singleton class. Here is a short illustration for you to chew of how the singleton class opens up metaprogramming possibilities.

class A
 def self.thing
   @thing
 end
 def self.thing=(x)
   @thing = x
 end
end

This is equivalent to

class A
 class <<>

Wednesday, December 13, 2006

Have it all : Ruby, irb, autocompletion, autodocumentation

Ruby users live long and happy with irb. But everything is not rosy under default irb's sun. One generally wishes :
  • documentation at your fingertip. what's available from the expression I just started to type ?
  • just.. standard auto completion
  • also correct handling of keys like "[" and "]" (which fails if you are under French or other keyboard layouts) is of occasional use
So for all this, here is a irbrc file, working under windows and Unix.
  1. You need to create a file named .irbrc (for windows user, call it toto.txt then rename it .irbrc from the command line)
  2. Then create an system environment variable called IRBRC, containing the complete path to your .irbrc file.
  3. Then just install the fastri gem and strat the documentation server using the command
        • gem install fastri
        • fastri-server
That'll get you started with everything you need to truly enjoy IRB goodness PS: Credits to eigenclass and the other Rubyist for all this goodness [Updated at 19/12/06] You can either download the file , of copy it from down there [Click to display the .ircrb file]
require 'irb/completion'
require 'rbconfig'

module Kernel
  include Config

  def r(arg)
 (CONFIG["target_alias"] == "i386-mswin32") ?  ( puts `fri.cmd "#{arg}"` ) : (puts `fri "#{arg}"`)

  end
  private :r
end

class Array
  def filter(&predicate)

      self.each do |item| 
          if(predicate(item))

           yield item
           end
      end
  end
end

class Object
  include Config
  def puts_ri_documentation_for(obj, meth)

    case self
    when Module
      candidates = ancestors.map{|klass| "#{klass}::#{meth}"}

      candidates.concat(class << self; ancestors end.map{|k| "#{k}##{meth}"})

    else
      candidates = self.class.ancestors.map{|klass|  "#{klass}##{meth}"}

    end
    candidates.compact.each do |candidate|
      #puts "TRYING #{candidate}"

      desc =  (CONFIG["target_alias"] == "i386-mswin32") ?  ( `fri.cmd "#{candidate}"` ) : ( `fri "#{candidate}"`)

      unless desc == "nil"
        # uncomment to use ri (and some patience)
        #desc = `ri -T '#{candidate}' 2>/dev/null`
        #unless desc.empty?

        puts desc
        return true
      end
    end
    false

  end
  private :puts_ri_documentation_for

  def method_missing(meth, *args, &block)

    if md = /ri_(.*)/.match(meth.to_s)

      unless puts_ri_documentation_for(self,md[1])
        "Ri doesn't know about ##{meth}"
      end

    else
      super
    end
  end

  def ri_(meth)

    unless puts_ri_documentation_for(self,meth.to_s)
      "Ri doesn't know about ##{meth}"
    end

  end
end

RICompletionProc = proc{|input|
  bind = IRB.conf[:MAIN_CONTEXT].workspace.binding

  case input
  when /(\s*(.*)\.ri_)(.*)/
    pre = $1

    receiver = $2
    meth = $3 ? /\A#{Regexp.quote($3)}/ : /./ #}

    begin
      candidates = eval("#{receiver}.methods", bind).map do |m|

        case m
        when /[A-Za-z_]/; m
        else # needs escaping

          %{"#{m}"}
        end
      end
      candidates = candidates.grep(meth)

      candidates.map{|s| pre + s }
    rescue Exception

      candidates = []
    end
  when /([A-Z]\w+)#(\w*)/ #}

    klass = $1
    meth = $2 ? /\A#{Regexp.quote($2)}/ : /./

    candidates = eval("#{klass}.instance_methods(false)", bind)
    candidates = candidates.grep(meth)

    candidates.map{|s| "'" + klass + '#' + s + "'"}

  else
    IRB::InputCompletor::CompletionProc.call(input)
  end

}
#Readline.basic_word_break_characters= " \t\n\"\\'`><=;|&{("
Readline.basic_word_break_characters= " \t\n\\><=;|&"

Readline.completion_proc = RICompletionProc