Rails 2 – really good tutorial


Akita published two part tutorial that leads you through building the famous 15 minute blog application in Rails 2.0. Read the parts one and two – or follow the screencast by the same author.

Thanks a lot, Akita – very nicely done !

Showstopper issue with JRuby ?


After some break, I dusted off the Ruby to try out one interesting idea Peter presented yesterday that literally ASKS for Rails. So I grabbed the latest and greatest RubyNetBeans from Ruby Hudson. For some reason it stopped updates on January 26th so the latest version I have got was build 6327. It is bundled with JRuby 1.1RC1 and the Rails version that comes preinstalled is 1.2.6. Using the menu Tools -> Ruby Gems, they can be easily upgraded to latest and greatest 2.0.2.

The trouble begins when you want to install database connectivity gems such as sqlite3-ruby. The installer fails with the message:

trying to install

INFO:  `gem install -y` is now default and will be removed
INFO:  use --ignore-dependencies to install only the gems you list
Building native extensions.  This could take a while...
extconf.rb:1: no such file to load -- mkmf (LoadError)
ERROR:  Error installing sqlite3-ruby:
    ERROR: Failed to build gem native extension.

/Users/miro/Applications/<a href="http://RubyNetBeans.app/Contents/Resources/nbrubyide/ruby1/jruby-1.1RC1/bin/jruby" class="linkification-ext" title="http://RubyNetBeans.app/Contents/Resources/nbrubyide/ruby1/jruby-1.1RC1/bin/jruby">RubyNetBeans.app/Contents/Resources/nbrubyide/ruby1/jruby-1.1RC1/bin/jruby</a> extconf.rb install sqlite3-ruby --no-rdoc --no-ri --include-dependencies --version > 0

Gem files will remain installed in /Users/miro/Applications/<a href="http://RubyNetBeans.app/Contents/Resources/nbrubyide/ruby1/jruby-1.1RC1/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.2.1" class="linkification-ext" title="http://RubyNetBeans.app/Contents/Resources/nbrubyide/ruby1/jruby-1.1RC1/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.2.1">RubyNetBeans.app/Contents/Resources/nbrubyide/ruby1/jruby-1.1RC1/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.2.1</a> for inspection.
Results logged to /Users/miro/Applications/<a href="http://RubyNetBeans.app/Contents/Resources/nbrubyide/ruby1/jruby-1.1RC1/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.2.1/ext/sqlite3_api/gem_make.out" class="linkification-ext" title="http://RubyNetBeans.app/Contents/Resources/nbrubyide/ruby1/jruby-1.1RC1/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.2.1/ext/sqlite3_api/gem_make.out">RubyNetBeans.app/Contents/Resources/nbrubyide/ruby1/jruby-1.1RC1/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.2.1/ext/sqlite3_api/gem_make.out</a>

The missing file mkmf.rb is indeed missing from the JRuby distribution. This is entered as a bug in JIRA 1306 with resolution ‘Won’t fix’. Tough luck.

I understand the reasons and motivation for this decision – the JRuby team decided not to support native extensions in Gems, to keep the platform Java only. I also understand that in this particular case, there are workarounds – using ActiveRecord-DBC gem and JDBC drivers for the database will most likely work. Unfortunately, this decision makes choice of JRuby as platform very questionable.

I really liked JRuby for the comfort of having platform that is portable and safely wrapped within boundaries of the good old trusted JVM. I feel much more comfortable maintaining possibly several different versions of JRuby and corresponding Gems sets than maintaining same several configurations on the OS level and sudo-ing just to install Gems. I was more that happy to trade the lack of speed for this security.

The two main attractions of Ruby (from my point of view) are elegant, powerful language with beautiful syntax as well as sheer amount of code available as Gems to be reused. With the bug 1306, many of this code may not be available for JRuby – unless Gem authors make specific provisions for Java version of the Gem. I cannot think how this is a good idea and certainly not a good news for the future of the language.

One way out is use native Ruby interpreter, of course and make sure you do not mess up your installation by trying out new things. This does not allow the easy way into enterprise that JRuby was promising – by being basically ‘just another jar’ and running on Tomcat.
The other way out is to reconsider the Groovy. I still do not enjoy the syntax anywhere close to Ruby, but every Groovy class is Java class, there is no need for artificial bridges. It has own clone of Rails – GRails – that seems to provide lots of Rails magic and goodies and is based on Spring which I am very familiar and quite happy with. I still do not know whether the amount of “gems” in Groovy world is in the same league as Ruby (which is still limited compared to Python or even CPAN Perl bonanza) – but as long as I can find that what I need, it may be just enough.

For now, I will revert back to Ruby (no time to start learning Groovy+Grails), but I definitely will look at it later on.

JRuby – keeping your database.yml really DRY


I am experimenting in JRuby and use database in virtual machine (VMWare Fusion). This is great because you can have multiple versions of multiple databases ready without polluting the notebook. One downsize though is that IP address of the database will change between the VM restarts.

First important setting in Fusion is to use the ‘NAT’ option rather than ‘Bridged’. With NAT, you database host IP address will not follow the network. It was quite annoying to change it from 192.168.X to 192.168.Y everytime I reconnected at home from work or vice versa.

But even with this setting, the IP may change as you restart the VM and you will have to modify the database.yml. To keep the amount of editing minimal, here is my database.yml for the shoplet example:

<% dbhost = 'jdbc:mysql://' %>
common: &common
adapter: jdbc
driver: com.mysql.jdbc.Driver
password: shoplet

<< : *common
url: <%=dbhost%>/shoplet_dev
username: shoplet_dev

<< : *common
url: <%=dbhost%>/shoplet_test
username: shoplet_test

<< : *common
url: <%=dbhost%>/shoplet_prod
username: shoplet_prod

It will work in Ruby as well of course – with different (non-jdbc based) adapter..

JRuby trunk – issues with JDBC connectivity


Following the book on JRuby I am discovering small differences when trying the examples. After installing activerecord-jdbc gem which is available in version 0.5, the shoplet application fails with Rails 2.0, as soon as you click on the ‘About your application environment’ link.

=> Booting Mongrel (use 'script/server webrick' to force WEBrick)
=> Rails application starting on
=> Call with -d to detach
=> Ctrl-C to shutdown server
** Starting Mongrel listening at
** Starting Rails with development environment...
** Rails loaded.
** Loading any Rails specific GemPlugins
** Signals ready.  TERM => stop.  USR2 => restart.  INT => stop (no restart).
** Rails signals registered.  HUP => reload (without restart).  It might not work well.
** Mongrel 1.1.2 available at
** Use CTRL-C to stop.

Processing InfoController#properties (for at 2007-12-23 23:13:25) [GET]
Session ID: BAh7BiIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNo%0ASGFzaHsABjoKQHVzZWR7AA%3D%3D--9791be23205677745e457b5bf62c50eba6e3813f
Parameters: {"controller"=>"rails/info", "action"=>"properties"}
Exception in thread "Ruby Thread11043409" java.lang.NoSuchMethodError: org.jruby.runtime.builtin.IRubyObject.setInstanceVariable(Ljava/lang/String;Lorg/jruby/runtime/builtin/IRubyObject;)Lorg/jruby/runtime/builtin/IRubyObject;
at JdbcAdapterInternalService.set_connection(JdbcAdapterInternalService.java:122)
at JdbcAdapterInternalServiceInvoker$set_connection_FS1.call(Unknown Source)
at org.jruby.runtime.callback.FastInvocationCallback.execute(FastInvocationCallback.java:55)
at org.jruby.internal.runtime.methods.SimpleCallbackMethod.call(SimpleCallbackMethod.java:70)
at org.jruby.runtime.CallSite$InlineCachingCallSite.call(CallSite.java:158)
at org.jruby.runtime.CallSite$ArgumentBoxingCallSite.call(CallSite.java:103)
at org.jruby.evaluator.ASTInterpreter.fCallNode(ASTInterpreter.java:1092)
at org.jruby.evaluator.ASTInterpreter.evalInternal(ASTInterpreter.java:345)
at org.jruby.evaluator.ASTInterpreter.blockNode(ASTInterpreter.java:626)
at org.jruby.evaluator.ASTInterpreter.evalInternal(ASTInterpreter.java:293)
at org.jruby.evaluator.ASTInterpreter.eval(ASTInterpreter.java:168)
at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:147)
at org.jruby.runtime.CallSite$InlineCachingCallSite.call(CallSite.java:158)
at org.jruby.runtime.CallSite$ArgumentBoxingCallSite.call(CallSite.java:76)
at org.jruby.evaluator.ASTInterpreter.vcallNode(ASTInterpreter.java:1734)
at org.jruby.evaluator.ASTInterpreter.evalInternal(ASTInterpreter.java:474)
at org.jruby.evaluator.ASTInterpreter.blockNode(ASTInterpreter.java:626)
at org.jruby.evaluator.ASTInterpreter.evalInternal(ASTInterpreter.java:293)
at org.jruby.evaluator.ASTInterpreter.rescueNode(ASTInterpreter.java:1499)
at org.jruby.evaluator.ASTInterpreter.evalInternal(ASTInterpreter.java:442)
at org.jruby.evaluator.ASTInterpreter.eval(ASTInterpreter.java:168)

I found out that there is newer version of activerecord-jdbc, which is also renamed to activerecord-jdbc-adapter. It is important to uninstall the old gem as well as install the new one, otherwise the application will not work.

$ jruby -S gem install activerecord-jdbc-adapter
Successfully installed activerecord-jdbc-adapter-0.7
1 gem installed
Installing ri documentation for activerecord-jdbc-adapter-0.7...
Installing RDoc documentation for activerecord-jdbc-adapter-0.7...
$ jruby -S gem install activerecord-jdbcmysql-adapter
Successfully installed jdbc-mysql-5.0.4
Successfully installed activerecord-jdbcmysql-adapter-0.7
2 gems installed
Installing ri documentation for jdbc-mysql-5.0.4...
Installing ri documentation for activerecord-jdbcmysql-adapter-0.7...
Installing RDoc documentation for jdbc-mysql-5.0.4...
Installing RDoc documentation for activerecord-jdbcmysql-adapter-0.7...

$ jruby -S gem list activerecord

*** LOCAL GEMS ***

activerecord (2.0.2, 1.15.6)
ActiveRecord-JDBC (0.5)
activerecord-jdbc-adapter (0.7)
activerecord-jdbcmysql-adapter (0.7)

$ gem uninstall ActiveRecord-JDBC
Successfully uninstalled ActiveRecord-JDBC-0.5
miroslav-adamys-macbook-pro:shoplet miro$ gem list ActiveRecord-JDBC

*** LOCAL GEMS ***

activerecord-jdbc-adapter (0.7)
activerecord-jdbcmysql-adapter (0.7)

After this, everything works and shoplet connects to database – as you can see from the console log.