Ruby

Screencast su Rails e premi per patch sulla documentazione

| |

Ruby è un linguaggio ad alto livello, esplicito e coinciso; con Rails si alza ancora di più e raggiunge un'espressività impressionante.
Rails è in costante crescita e cambiamento, ogni giorno ci sono novità ed è difficile starci dietro.
La documentazione c'é, ma spesso non basta per apprendere e utilizzarlo al meglio, oltre la galassia di http://planetrubyonrails.org, c'é un sito che fornisce ogni 2 o 3 giorni degli screencast gratuiti su come utilizzarlo più efficaciemente.

Questo sito è Railcast.com e per aumentare la diffusione di questo framework mette in palio diversi premi(ipod e Nintendo DS) per chi propone delle patch entro il 27 luglio per aumentare la documentazione di Rails.

Approfitto per consigliarvi 3 screencast che mi sono piaciuti
#57 Fa vedere come gestire i checkbox multipli
#55 Pulire la vista dalla logica
#54 ruby-debug per trovare i bug e provare la correzione a runtime

10 Ruby and Rails related tecnologies for Web2.0 and beyond

| |

1. UJS
Unostrubsive Javascript, write in web1.0 and render in Web2.0, Web3.0,.. This is an attempt to add behaviors to the MVC pattern. The power of the standards but also integrated effects.

2. Globalize
A smart way to add internationalization and globalization to your sites

3. REST
Provide datas corresponding to the request easly

4. RSpec
Add readable and easy to mantain tests to your code

5. Rjs
Write the code in ruby also for the client-side

6. Capistrano
Develop locally and put the working code easly in production

7. Webserver indipendent
Apache, lighttpd, mongrel,.. Choose the webserver with the performance, features you need

8. Database indipendent
SQlite, Mysql, Postgresql, Firebird,.. You can choose the backend technology you prefere (as above)

9. Free Text editors / IDE with plugins, snippets, syntax highlight, autocompletion,..
Gedit textmate-like, Eclipse RDT/Aptana, Ride-me

10. Community
Documentation, Screencasts, Forums(1,2,3)

How to map Glade/Gtk widgets to instance variable without repeating yourself

| |
Glade is nice tool: it creates the xml of the inteface you see, but when you have to use this gui you have to map every widget created with an instance variable.
This is easy to mantain when you have few widgets, but when you have a lot textbox / entry you will have to map a lot of stuff.
Here's a Ruby version of a runtime code generation using the eval method

Download first the gui.glade
# gui.rb

require 'libglade2'

class Gui

 def initialize
   
  @glade = GladeXML.new("gui.glade") {|handler| method(handler)}
  
  @glade.widget_names.each do |name|
     begin
       instance_variable_set("@#{name}".intern, @glade[name])
       if @glade[name].class == Gtk::Entry
        # automatic version
       eval <<-END
        @#{name}.signal_connect('changed') do
          @window1.title= @#{name}.text
        end
        @#{name}.text= "My name is @#{name}"
       END
       end
      rescue
     end
    end
  
  # hand version
  @window1.signal_connect('destroy'){
   exit
  }
  
  @window1.show_all
  
 end
 
end

Gtk.init
Gui.new
Gtk.main
Conclusion
Yo will be able to access to any entry widget with @entry and set a common signal to all of them without doing it for each widget.

Howto manage an svn+edgerails+capistrano environment on Gnome/Linux

gedit rails svn scripts
 I found on internet a lot of informations about how to install something-in-rails but I didn't find a real world usage of it.
What I've written is an overview about how to be productive with rails in a quite common use case. This "ecosystem" is mainly for rails projects, but can be used also for other kind on applications.  

Install svn

Subversion is a very common version control system; sometimes it's installed in your web hosting space, but if you decide to set up on you PC you are more indipendent.
 sudo apt-get install subversion subversion-helper-scripts subversion-tools 
You have to create the directory for the svn projects

# '/svn-stuff' is where you put your config and svn internal stuff
sudo mkdir -p /svn-stuff
sudo svnadmin create /svn-stuff
-- sudo gedit /svn-stuff/conf/svnserve.conf
[general]
anon-access = read
auth-access = write
password-db = passwd # relative path to the users file
--

-- sudo gedit /svn-stuff/conf/passwd
[users]
username = password

--

Start svn server (called svnserve) with:

svnserve -d -r /svn-stuff
# it means 'daemon' and svn projects path

There's not a '/etc/init.d/svnserve start' script but you can start automatically svn server with xinetd

For more informations see Ubuntu forum and if you need the http interface you can install websvn

WARNING

+ Everything should go as expected, if you get something like "svnserve.conf:28: Option expected" probably you have to delete the space before a parameter like anon-access
+ You can start svnserve with -i, but It didn't work for me

Install edgerails environment

It's very easy to do 'gem install rails' but if you want lastest stable release or your web hosting doesn't update rails frequently this is the best thing to do.
We will keep latest rails in a directory called edgerails and all the apps we'll create will point the first rails path MYRAILSAPP/vendor/rails -> to edgerails/ So edgerails will be shared.

# '/projects' is the path to the dir where you store your apps
cd /projects
svn co http://dev.rubyonrails.org/svn/rails/branches/stable/ edgerails/
#This alias is to have edgerails as default rails
alias rails="ruby  /projects/edgerails/railties/bin/rails"
rails eapp
cd eapp/vendor/
ln -s ../../edgerails/ rails
cd ..
script/server # http://localhost:3000 and test rails version
# => Booting lighttpd (use 'script/server webrick' to force WEBrick)

cd ..

# It's the first import of the directory, and 'trunk' is the current release
svn import eapp svn://localhost/eapp/trunk -m "Import eapp"

# just to be secure that everything will go well anyway :)
mv eapp eappbak

# This will sinchronize the content with the current svn version

svn co svn://localhost/eapp/trunk eapp # with -r <number> you specify the release

#Test svn
cd eapp
echo "test" >> README
svn diff # differences with svn version
svn ci -m "added test ooh" # commit the changes to svn
svn up -r <number before> #rollback
# svn add file-or-dir # to add a file to svn

Common tasks

# -x automatically generates the svn code
script/plugin install -x acts_as_taggable
# -x automatically generates the svn code
script/generate model -c mymodel

Other stuffs

Capistrano permits to create tasks to manage your rails app
# Usually the web hosting already did this for you
sudo gem install capistrano --include-dependencies

cap --apply-to eapp
svn add config/deploy.rb
svn add lib/tasks/capistrano.rake
svn ci -m "added capistrano"
Install features for Gnome environment

nautilus svn scripts
to control common svn commands on a GUI!
sudo apt-get install nautilus-script-collection-svn
meld is a nicer way to see 'svn diff' with colors
edit the nautilus script 'diff' and put:
#zenity...
meld $@

Gedit rails, some basic autocompletion snippet for rails

Notes 

  • If you have enought RAM and CPU even Eclipse + Radrails + Subversive offers a nice environment.

Reverse URL translation with Globalize - Rails

Globalize is one of possible way(see the comparison) to translate a Rails app, you are forced to use a database to do this but It's really a powerful method to localize  an application because this plugin adds a method .t to every String.

Unfortunatly the method .t is just for English-to-otherLanguage translation so you have to hack it a bit to have reverse translation.

Here's the method I used to translate the URL:

  • Name of the controller statically translated in routes.rb
  • Translation of each chunk after in the controller


So I'll be able to manage, at the same way, url like:

http://x.com/ristorante/ricette/insalata.html
http://x.com/restaurant/recipes/salad.html

# config/environment.rb
# [...]

include Globalize
Locale.set_base_language 'en'


# enables reverse translation and redefine String#t
class String

alias :old_t :t

def t
if self.old_t == self.to_s
q = Translation.find_by_sql("SELECT tr_key FROM globalize_translations g where text='#{self.to_s}'")

if q.empty? # there's no translation
return self
else
return q[0].tr_key
end
else
self.old_t
end
end

end

Restart /script/server 

# config/routes.rb
# [...]

  map.connect 'ristorante/*url' ,
:controller => 'restaurant', :action=>'translate', :language => 'it'

  map.connect 'restaurant/*url' ,
:controller => 'restaurant', :action=>'translate', :language => 'en'
# app/controllers/restaurant_controller.rb
# [...]

def translate
if params[:url].nil? or params[:url].empty?
@url = []

url_join=url.join('/')

case url_join

# url empty
when ''
render :text => 'main'

# restaurant/ + recipes/pizza.html
when /^\w+\/+\w+\.html$/ then

# try to search 'pizza'.t in the db, without '.html'
@recipe= Recipe.find(:first, :conditions=> ["name = ?",@url[1].split('.')[0].t])

if @url[0] == 'recipes'.t
render :partial => 'view_recipe'
# if the same regexp match to some other subaction
elsif @url[0] == 'ingredients'.t
render :view_ingredients => 'view_ingredients'
else
render :text => 'Error 404' --> '+url_join
end


end

Probably this solution isn't very scalable, because it does to many queries, so if you adopt an url like http://site.com/ristorante/ricette/23/pollo.htm instead of http://site.com/ristorante/ricette/pollo.htm, you will save the reverse query, because the id is already present.

Snippets di Ruby on rails in Gedit

|

Gli snippet sono delle impalcature che permettono di velocizzare la scrittura del codice, Gedit le include come plugin e permette anche di farsene di personalizzate(vedi screencast).

L'idea viene presa da un editor molto comune tra gli sviluppatori in Ruby on Rails (che usano Mac) chiamato Textmate.

gedit snippets rails
 
il funzionamento è molto semplice, invece di scrivere tutto il costrutto si scrive la keyword principale o abbreviata, si preme tab e automaticamente ci si ritrova con il costrutto scritto, premendo <tab> si fà un salto direttamente alla posizione desiderata (Vedi screencast)

Non si tratta di autocompletamento che c'é nei mastodontici IDE come Eclipse, ma comunque rendono davvero veloce la scrittura del codice.

 

Creare gli snippet è facilissimo, bisogna solo stare attenti a fare l'escape di : ".
La sintassi è semplice $1 $2,.. corrispondono ai salti che vogliamo fare nel blocco di codice, primo <tab>, secondo <tab>, se poi vogliamo mettere un valore predefinito, che comunque può essere sovrascritto si usa ${1:variabile}.

Per esempio il for in si può fare così:

for ${1:nome_elemento} in ${2:nome_array}
    $3 ${1:element}
end
$0

Quindi scrivere:

for i in mio_array
print i
end

Diventa velocissimo, una volta fatto lo scheletro e impostato lo shortcut si salta tranquillamente nelle parti che servono, ovviamente una volta usciti dallo snippet si può sempre modificare il codice a proprio piacimento

Questi sono gli snippet di RoR/ActiveRecord che ho aggiunto alla sintassi di Ruby, potete installarli mettendo questo file nella cartella:

$HOME/.gnome2/gedit/snippets

 

Rails and Php on Apache without virtualhost

This is a simply hack to set up Apache with Ruby on Rails and PHP in the same tree.

I set up Apache+Rails following the wiki but then my php sites didn't work anymore, so I found this not for production way to have both together with a unique Apache installation and without virtual host(app1.host, app2.host).

So:

cd /var/www
rails railstest
cd railstest
script/generate controller prova 
<VirtualHost *>
ServerName localhost
DocumentRoot /var/www/
ErrorLog /var/log/apache2/error.log

<Directory /var/www/railstest/public>
Options ExecCGI FollowSymLinks
AddHandler fcgi-script .fcgi
AllowOverride all
Order allow,deny
Allow from all

</Directory>
</VirtualHost>

 Now restart apache and You will be able to access to your rails application with http://localhost/railstest/public/prova, if you don't want /public in the middle you can create symbolic links of public in /var/www (and call it railsapp)so You will be able to access to the controller with http://localhost/railsapp/prova and http://localhost/drupal-4.7-beta will work as usual

I've been surprised that ror on Apache is slower than  on Webrick(Ruby's webserver), I gonna try a real world solution.. probably this is a good point where to start.

Web 3.0? Come sarà il web del futuro?

|

Dopo il web 2.0 c'è già chi prova col 3.0, il web sta cambiando radicalmente e sempre più infretta; le tecnologie innovative già ci sono, adesso non resta che sincronizzarsi e migrare i contenuti.
Pagina statica -> pagina dinamica -> Applicazione web, sembra proprio essere questa l'evoluzione del web.


Ma dove poi questa rivoluzione?


Sembrerà banale, ma quando navighiamo su un sito e clicchiamo su un pulsante, tutta la pagina viene ricaricata; questo spreco/limitazione di risorse è stata da sempre una grande limitazione del protocollo web/http
Adesso grazie ad Ajax questo vincolo non c'è più e le applicazioni web di prossima generazione avranno poco da invidiare a quelle standalone e in alcuni casi le potranno addirittura rimpiazzare, vedi già gli editor WYSIWYG sul web.

Widget, trasparenze e interattivività ovunque, la tentazione sarà quella di offrire servizi e non più programmi, ma a quel punto ci sarà la GPL 4.0

PS: Anche i CMS dovranno aggiornarsi, per adesso ho trovato solo RailFrog(è ancora un embrione, ma é in stile Drupal) che supporta nativamente ajax, tramite ruby on rails

Programmare server e client con Ruby

Anche l'IBM si accorge delle grandi potenzialità di questo linguaggio multipiattaforma completamente ad oggetti.
Il documento tratta la programmazione dei socket, che possono essere utilizzati per la programmazione di rete, e fa alcuni esempi su come interfacciarsi sui protocolli più comuni.

Se siete nuovi a Ruby vi consiglio anche il mini-corso di Schroeder

Applicazioni multipiattaforma 100% GUI-Indipendent

|

Può capitare di dover realizzare programmi che siano utilizzabili con diverse interfacce grafiche, in Ruby ci sono diversi stratagemmi per farlo e al primo posto troviamo i blocchi, ecco un programmino d'esempio che funzione da gtk o console.

L'idea di base è che tutti i controlli dati vengono fatti dalla classe interna, mentre le interfacce si limitino solo a fare input/output; probabilmente questo approccio non va bene in tutti i casi, ma se si usano pochi semplici widget fa la sua bella figura.

Ho deciso di usare i metodi "error" e "notify", per semplicità, ma si sarebbero potute utilizzare anche le eccezioni; stesso discorso per l'alert. Gtk::Dialog sarebbe il widget giusto, ma rischierebbe di creare confusione.

Si esegue con:

ruby esempio.rb (Console) o ruby esempio.rb --gtk (Gtk)



#!/usr/bin/ruby
=begin
 == esempio.rb ==
 Una semplice implementazione di oggetti indipendenti dall'interfaccia grafica/console
 oOo. http://assente.altervista.org .oOo
=end

# Oggetto principale GUI-indipendent
class List
    def initialize()
        @a=[]
    end
    def add(value)
        # vari controlli sull'input
        if value==""
            error("Valore nullo")
        elsif value=~/[a-zA-Z]/
            error("Le lettere non sono ammesse")
        elsif value=~/[0-9]/
            @a << value
            notify("'#{value}' inserito")
        end
    end
    # yield viene sostituito con quello che passiamo a livello superiore,
    # puts oppure @display.text+=, fantastico, no?
    def show_all
        @a.each { |value| yield value}
    end
end

class ConsoleList < List
    def initialize
        super
        puts "Console mode"
        while true
            puts "1: Aggiungi 2: Visualizza 3: Esci"
            # toglie \n dall'input da terminale
            choice=gets.strip
            case (choice)
                when "1" then add
                when "2" then show_all
                when "3" then exit
            else
                error("Scelta non valida")                
            end        
        end
    end
    def add
        puts "Inserisci: "
        # manda al metodo List#add vedi su
        super(gets.strip)
    end
    # Richiamato da List
    def error(text)
        puts "!! #{text} !!"
    end
    def notify(text)
        puts ">> #{text}"    
    end
    def show_all
        super{|v| puts "|#{v}|"}
    end
end

class GtkList < List
    require 'gtk2'
    def initialize
        super
        puts "GUI mode"
        
        Gtk.init    
        
        #Inizializzo i widget
        @window=Gtk::Window.new
        @container=Gtk::VBox.new
        @entry=Gtk::Entry.new
        @display=Gtk::Label.new
        @button=Gtk::Button.new("Inserisci")
        
        #Assegno gli eventi
        @button.signal_connect("clicked"){add}
        @entry.signal_connect("activate"){add}
        @window.signal_connect("destroy"){exit}
        
        #impacchetto
        @container.add(@display).add(@entry).add(@display).add(@display).add(@button)
        @window.add(@container)
        
        @window.show_all
        
        Gtk.main
    end
    def add
        puts "Inserisci: "
        super(@entry.text)
        @entry.text=""
    end
    def error(text)
        # Con più spazio estendetevi Gtk::Alert :-)
        Gtk::Window.new.add(Gtk::Label.new("#{text}")).show_all
    end
    def notify(text)
        # Non necessario
        #Gtk::Window.new.add(Gtk::Label.new("#{text}")).show_all
        show_all
    end
    def show_all
        @display.text=""
        super{|v| @display.text+=v+" "}
    end
end

# Inizia qui
case(ARGV[0])
    when nil:     ConsoleList.new
    when "--gtk": GtkList.new
end


Syndicate content