Che esistano diverse implementazioni di Ruby è cosa nota e in questo articolo ci occupiamo di una delle più conosciute, quella basata su Java: JRuby. Ma perché occuparsene? Non abbiamo già un ottima implementazione nativa?
Con JRuby siamo in grado di utilizzare il nostro codice Java all'interno dei progetti Ruby e, considerando che abbiamo molto codice Java (legacy?) all'interno delle nostre organizzazioni, una buona strategia potrebbe essere quella di continuare ad utilizzare tale codice nei nuovi progetti (ruby/rails), e nel frattempo
iniziare un processo di migrazione e reingegnerizzazione del vecchio codice ("vecchio" ma stabile!).
In questo articolo vogliamo mostrare come:
- installare JRuby e testarlo
- iniziare un nuovo progetto Rails con JRuby
- utilizzare classi Java esistenti all'interno del progetto Rails
Per il nostro esempio abbiamo utilizzato questa configurazione basata su Mac OS X:
- Mac OS X 10.5.6
- Java 1.5.0-16
- Rails 2.2.2
- JRuby 1.1.3 (ruby 1.8.6 patchlevel 114)
ma non si dovrebbero incontrare problemi insormontabili con altri sistemi operativi.
Installazione
Anzitutto occorre installare JRuby:
$ su # port install jruby
Ora verifichiamo che funzioni correttamente:
# jruby -v jruby 1.1.3 (ruby 1.8.6 patchlevel 114) (2008-12-23 rev 6586) [i386-java]
Quindi scarichiamo l'ultima versione di rubygems dal sito ufficiale, estraiamo il contenuto del pacchetto e la installiamo:
$ wget http://rubyforge.org/frs/download.php/45905/rubygems-1.3.1.tgz $ tar -zxvf rubygems-1.3.1.tgz $ cd rubygems-1.3.1 $ jruby -S ./setup.rb
Infine, possiamo installare le gem necessarie:
# jruby -S gem install rails # jruby -S gem install mongrel jdbc-mysql activerecord-jdbcmysql-adapter
Notiamo che queste gem vengono installate sotto un path diverso da quello di ruby "nativo", quindi vengono tenute ben separate. Per altre piattaforme possiamo fare riferimento al wiki ufficiale di JRuby.
Come regola generale è utile notare che è sufficiente utilizzare lo switch -S
seguito dal comando ruby.
Costruire l'applicazione Rails
Ora, a scopo puramente dimostrativo, creiamo un semplice blog ("YAB": yet another blog):
$ jruby -S rails yab $ cd yab
Accertiamoci che tutto funzioni correttamente:
$ jruby -S rake -T $ jruby -S script/server
Puntando il nostro browser su http://localhost:3000
vedremo la familiare schermata di benvenuto.
Ottimo, tutto funziona, ma attualmente ong>JRuby non supporta le estensioni native>: non possiamo installare la gem mysql (come neppure sqlite). Dobbiamo scaricare ed installare il connettore MySQL per Java (un driver JDBC) da qui:
$ wget http://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.0.8.tar.gz $ tar -zxvf mysql-connector-java-5.0.8.tar.gz $ sudo cp mysql-connector-java-5.0.8/mysql-connector-java-5.0.8-bin.jar /opt/local/share/java/jruby/lib
Ci sono altre gem che varrebbe la pena provare, come activerecord-jdbcmysql-adapter
. Per ora concentriamoci sulla creazione del database:
$ echo "create database yad_development" | mysql -u root -p
dobbiamo modificare opportunamente il file config/database.yml
inserendo le seguenti linee:
development: adapter: jdbc driver: com.mysql.jdbc.Driver url: jdbc:mysql://localhost/yad_development username: root password: NotSoSecretPassword
Creato il db, possiamo continuare lanciando la generazione della risorsa post
:
$ jruby -S script/generate scaffold Post title:string content:text exists app/models/ ... <cut> ... create app/controllers/posts_controller.rb create test/functional/posts_controller_test.rb create app/helpers/posts_helper.rb route map.resources :posts
Lanciamo la migration:
$ jruby -S rake db:migrate == CreatePosts: migrating ==================================================== -- create_table(:posts) -> 0.0448s -> 0 rows == CreatePosts: migrated (0.0458s) ===========================================
Possiamo vedere le consuete schermate dell'applicazione rails prodotto dallo scaffolding sulla risorsa post
:
Proviamo ad inserire un nuovo post:
e vediamo che (ancora) tutto funziona come ci aspettiamo:
Utilizzare classi Java nei controller Rails
Finalmente possiamo utilizzare una classe Java esistente all'interno di un nuovo controller nella nostra applicazione Rails.
Supponiamo di avere una classe Java responsabile della "politica di pubblicazione" dei post sul blog, e per semplicità tale politica è basata esclusivamente sul contenuto del titolo del post:
package myenterprise;
public class BlogPolicy
{
public static boolean is_valid(String postTitle)
{
/* politica di pubblicazione molto "permissiva"... */
return true;
}
}
Supponiamo, inoltre, di avere questa classe all'interno di un package
più generico (myenterprise
), contenuto in un jar file (myenterprise.jar
).
Prima di tutto dobbiamo istruire Rails su come includere i file jar di nostro interesse. Per far ciò è sufficiente aggiungere il seguente codice in coda al file config/environment.rb
:
Dir["#{RAILS_ROOT}/lib/**/*.jar"].each do |jarfile| require jarfile end
quindi possiamo inserire i file jar necessari all'interno della directory lib
(partendo dalla directory radice del nostro progetto - "yab")
Finalmente possiamo usare la classe Java all'interno dei nostri controller:
class PostsController < ApplicationController include Java import 'myenterprise.BlogPolicy' # GET /posts/1 # GET /posts/1.xml def show @post = Post.find(params[:id]) # Applichiamo la "politica di pubblicazione" sui post # NOTARE l'uso della classe Java unless BlogPolicy.is_valid(@post.title) redirect_to(@post) end respond_to do |format| format.html # show.html.erb format.xml { render :xml => @post } end end ... end
Come possiamo notare, dopo aver incluso il mixin Java ed importato l'opportuna classe, siamo in grado di utilizzarla facilmente senza bisogno di particolari costrutti sintattici:
unless BlogPolicy.is_valid(@post.title) redirect_to(@post) end