Archive for the ‘Rails’ Category

h1

Rails Wanted Dead or Alive $2.500.000!

July 10, 2007

Wanted Rails

Rails success is not debatable. But this was not an easy battle (and still isn’t) and some projects are trying to keep the ewes into the JEE garden.

Rails SLOC 2004-2007

This represents the SLOC (Source Lines Of Code) of Rails since it was born 3 years ago.
What to say about this? Basically you can’t say much about SLOC (see the SLOC part of a previous post)… Except that the progress is regular (which can be explained by the fact that it is maintained by a company in contrast to open source projects which might have an important growing community of commiters)
Now sloccount gives us a summary:

Total Physical Source Lines of Code (SLOC) = 74,385 (100% Ruby)
Development Effort Estimate, Person-Years (Person-Months) = 18.45 (221.45)
(Basic COCOMO model, Person-Months = 2.4 * (KSLOC**1.05))
Schedule Estimate, Years (Months) = 1.62 (19.46)
(Basic COCOMO model, Months = 2.5 * (person-months**0.38))
Estimated Average Number of Developers (Effort/Schedule) = 11.38
Total Estimated Cost to Develop = $ 2,492,879
(average salary = $56,286/year, overhead = 2.40)

So the reward for Rails is $2,492,879!
This is based on 2004 salary…

Now if you want to have some fun and get some stats from your favourite svn repository, go get Ruby, go get Gruff, go get sloccount, go get a Beer, and relax!
Sorry for the format but WordPress really doesn’t help me…
# railssloccount.rb
# July 10, 2007

require 'date'
require 'rubygems'
require 'gruff'

DIR_DOWNLOAD = '/home/username/railssloccount/'
STEP = 15
FIRST_DATE = '2004-11-29'
GRAPH_SIZE = 400
GRAPH_HORIZONTAL_AXIS_SPACE = 16
axis = {}
datas = []
index = 0

puts "svn checkout --revision {#{FIRST_DATE}} \
\"hxxp://dev.rubyonrails.org/svn/rails/trunk\" \
#{DIR_DOWNLOAD}trunk"


`svn checkout --revision {#{FIRST_DATE}} \
\"hxxp://dev.rubyonrails.org/svn/rails/trunk\" \
#{DIR_DOWNLOAD}trunk`


(Date.parse(FIRST_DATE)..Date.today).step(STEP) do |date|
axis[index] = date.to_s \
if
index % GRAPH_HORIZONTAL_AXIS_SPACE == 0
index += 1
puts "svn update --revision {#{date}} \
\"hxxp://dev.rubyonrails.org/svn/rails/trunk\" \
#{DIR_DOWNLOAD}trunk"

`svn update --revision {#{date}} \
\"hxxp://dev.rubyonrails.org/svn/rails/trunk\" \
#{DIR_DOWNLOAD}trunk`

puts "sloccount #{DIR_DOWNLOAD}trunk"
result_cmd = `sloccount #{DIR_DOWNLOAD}trunk`
File.open("#{DIR_DOWNLOAD}sloccount_#{date}.txt", "w") { |f|
f << result_cmd
}
result = result_cmd[/ruby:\s*(\d+)/].gsub(/ruby:\s*/, '').to_i
puts "Date: #{date} - SLOC: #{result}"
datas << result
end

axis[index-1] = last_date.to_s

g = Gruff::Line.new(GRAPH_SIZE)
g.data('Rails SLOC', datas)
g.labels = axis
g.minimum_value = 0
g.title = 'Rails SLOC'
g.write("rails_sloc_#{STEP.to_s}day_#{GRAPH_SIZE.to_s}.png")

h1

A Controller DSL to Complement MVC

July 3, 2007

Bruce Williams has been working on the view pattern over the past years; Notably the problems it raises: heaviness, conciseness, complexity, depending on the solution you choose. The presentation he gave at RailsConf, When “V” is for “Vexing”, introduced a Controller DSL: folder_for. Bruce gave an exhaustive use case of it on his blog.
Starting from a simple example that will need Folder interfaces, he naturally chose to use a DSL: folder_for.

 class CarsController < ApplicationController

    # ...
    folder_for :show do
      tab "General Information" do
        @score = current_user.score_for_car(@car)
      end
      tab "History"
      tab "Photos"
    end
    # ...

 end

Bruce uses convention over the use of one view template to render each selected tab partial (cars/show.html.erb). His views will be structured this way then:

 cars/
    show.html.erb
    show/
      _general_information.html.erb
      _history.html.erb
      _photos.html.erb

Bruce doesn’t only bring a new plugin which is more like a sample code; But he showed that a hundred lines of code was enough to accomplish his task demonstrating that a DSL can be deployed effectively with Ruby. The code is cleaner even if breaking some rules:

There are likely several of you reading this that are disturbed to see a folder reference within a controller, as this amounts to some level of MVC “separation of concerns” blasphemy in your very strict, very well-worn code rulebook.

I’m here to tell you it’s okay, and you’ll recover in time.

Let’s keep in mind here that the MVC separation of concerns, while a great rule of thumb, is just that … it is not an ivory tower to be left unassailed in times of dire need. At times, it makes sense to allow abstractions to cross these boundaries for the sake of reducing our own overhead, and in the cause of developing your own app-wide domain specific language—something, that in my book, is the principal sign of a good Rails developer (for what it’s worth).

h1

Ruby / Rails IDE Comparison : Idea, Netbeans, RadRails

February 28, 2007

Starting BlocksWelcome early-early adopters!
Ruby and Rails are getting more and more popular in the community and well known editors start to get into the business for our pleasure!
While my editor of choice for Java has always been Idea (since v2.6 about 6 years ago) as I always found their product avantgardist and really userfriendly and codingfriendly, I wanted to see what was going on in the Rails / Ruby world where I was historically using RadRails and SciTe because of the lack of serious competitors. The simple editors like vim (for the nostaligcs) or SciTE are likely to fit your needs for short and simple scripts but a full IDE is always better to have when you are working on a more important project. The Ruby language itself eliminated a lot of features you would need from an IDE in other languages like Java (For example I am thinking about the Generating Getters / Setters from fields that you get directly with the attr accessors or some long live template public static final String …). The absence of type and the dynamism makes it also impossible for IDEs to do some operations you would do on typed static language (like Java).
Firstly you must notice that apart from RadRails which has been into Rails / Ruby editing for some time, Idea and NetBeans support for Ruby is really fresh (officially) so you should be lenient. You’ll also observe those IDEs tested here are all written in Java (as Plugins). Now you can wonder why not in Ruby ? There are several reasons I guess, notably a lack of serious good looking cross platform gui framework in Ruby (Tk is far from swing and swt quality and anyway it is not Ruby anyway even if that’s the easiest interface to plug with Ruby or Python); Also making an IDE from a well proven platforms guarantees that you’ll benefit from the history and quality of existing software features.
You should also try those IDEs by yourself as an IDE is a day-to-day tool that you learn to use and adopt with time and not with some simple test. That’s why here I’ll mainly compare features.

Read the rest of this entry ?

h1

Installing Eclipse with Ruby / Rails support

February 28, 2007

eclipse_logo.gifAs stated in my blog, I am having a look at the most well-known Ruby / Rails IDE competitors.
Thus I had a try on Eclipse platform as I couldn’t get RadRails 0.7.2 Standalone version to work with latest RDT plugins that come with refactoring notably.
Version we will install :
Eclipse 3.2.1 with RDT Stable Release (to have a stable environment) or Nightly Build Plugin (in my case 0.8.0.702111959NGT) to test latest RDT features, and RadRails Plugin 0.7.2
Once you installed Eclipse, you need to install those 2 plugins.
– Help Software Update / Find And Install / Search for new features to Install /
Then Add the new Remote sites :

Eclispe Install RadRails PluginEclispe Install RDT Plugin

Once you parametrized the Ruby SDK in the options, you are ready!

h1

Installing Idea with Ruby / Rails support

February 28, 2007

jetbrains_idea_logo.gifAs stated in my blog, I am having a look at the most well-known Ruby / Rails IDE competitors.
Thus I had a try on Idea which I have been using for years in Java/ JEE.
Version we will install :
Idea 6.0 (Support for Idea Selena (future 7.0) is in the pipes) with Ruby Plugin 0.1.1
You should notice that Idea doesn’t show up when you’re running Beryl on Linux, after switching back to KDE Windows Manager you’ll be able to see the window (You can switch back to Beryl Window Manager after), this a known issue with Java (either 1.5 and 1.6) and Beryl. Eclipse will show up as it is in native swt.
Once Idea installed, you’ll need to install to install Ruby Plugin :
– File / Settings / IDE Settings / Plugins / Right-Click on Ruby plugin.

Idea Install Ruby Plugin

You should also edit bin/idea.vmoptions and increase -Xmx192m

You’ll be prompted to set the Ruby SDK. You might encounter problem with symbolic links on linux when browsing to find your Ruby SDK, or when you generate a Rails project with older version of rails that creates symbolic links in vendor/ which will end in infinite parsing of the project.

h1

Installing NetBeans with Ruby / Rails support

February 28, 2007

NetBeans LogoAs stated in my blog, I am having a look at the most well-known Ruby / Rails IDE competitors.
Thus I had a try on NetBeans after seeing screenshot and features from Tor’s weblog, and after having played in Java with UML Module from NetBeans which I found good, I’ll blog about that later…
So, version we will install :
NetBeans 6 Daily Snapshot (I tried from 20070211 to 20070221). For the moment Ruby support is only available for early adopters in the snapshot releases. It was released lately as 6.0 Milestone 7 (and you’ll wait for M8 for some more features). Modules I installed (with version I have at the moment) :

  • Common Scripting Language API/Support 0.13.0/0.14.0.1.1.1.1.3
  • Embedded Ruby 0.10.0, JRuby Implementation 0.92.3, Rake-Based Project Support 0.10.0, Ruby IDE Support 0.16.0, Ruby On Rails 1.16.0, Ruby on Rails Project Support 0.13.0, Ruby Projects 0.14.0.1

But latest releases with some more fix/features come with :

  • Common Scripting Language API/Support 0.14.0/0.17.0.1.1.1.1.3
  • Embedded Ruby 0.11.0, JRuby Implementation 0.92.4, Rake-Based Project Support 0.10.0, Ruby IDE Support 0.20.0, Ruby On Rails 1.1600.0, Ruby on Rails Project Support 0.16.0, Ruby Projects 0.17.0.1

You should notice that NetBeans doesn’t show up when you’re running Beryl on Linux, after switching back to KDE Windows Manager you’ll be able to see the window (You can switch back to Beryl Window Manager after), this a known issue with Java (either 1.5 and 1.6) and Beryl.
Once you installed NetBeans Snpashot (or M07), you’ll need to install the Modules :
– Tools / Update Center / Development Update Center (If you don’t have it available you didn’t download a snapshot release).

NetBeans Install Ruby Plugin

After that for some older version of the module you would need to chmod properly the executable from the plugin directory but this has been fixed here.

When you will try to create a rails project directly after NetBeans install and plugin-install you would end with the error :
rubygems.rb:301:in `report_activate_error': Could not find RubyGem activesupport (= 1.3.1) (Gem::LoadError)
The gems activesupport and activerecord are missing, I found it rather strange as I had them installed on my machine.
In fact NetBeans Ruby Module is using an embedded JRuby, that come with some gems (rails, actionmailer…) used for your future NetBeans Ruby / Rails projects. I wonder why activesupport and activerecord have not been included, but anyway with our project we will need to complete this rubygems repository. It’s important to get that well set as it will be scanned and some features like autocompletion will be based on it.

There is an option in Tools / Options / Miscellaneous / Ruby Application to configure Ruby binaries used by the module.

NetBeans Tools / Options / Miscellaneous / Ruby Application

Still options won’t be saved on Windows, you have to manually edit \.netbeans\dev\config\Preferences\org\netbeans\modules\ruby\project.properties to point to your binaries :
ie, for me :
ruby=D:/bin/ruby/bin/ruby.exe
rails=D:/sa/bin/ruby/bin/rails
rdoc=D:/sa/bin/ruby/bin/rdoc
ri=D:/sa/bin/ruby/bin/ri

Congratulations! You are ready, you can relaunch NetBeans and enjoy!
At first launch, the plugin will index Ruby SDK and gems thus taking some minutes.

You’ll find Project Mailing List here.

[EDIT] You can ignore the following workaround as it seems to be corrected with latest versions of the Module since I reported it.[EDIT]

Read the rest of this entry ?

h1

Installing RadRails on Ubuntu Edgy amd64

February 13, 2007

For a future post about Ruby IDE I needed to install RadRails. I did it in the past without problem on windows. Unfortunately the official (and snapshot) versions come with a 32 bits shared library (libswt-pi-gtk-3232.so). So I was landing on an error message quoted later. The only solution I read while investigating on the net was to use RadRails the oldway : install Eclipse and add RadRails and RDT Plugin to it… I didn’t want to download the overbloated eclipse platform while a standalone RadRails version exists which is lighter (still 40MB…) So I convinced myself to get those bloody 64 bits shared libraries to work.
The laziest way is to find a solution without any compilation (compilation of such libraries can be a nightmare when they depend on zillions of projects and I have no fun messing with that anymore).
So let’s go!
Download Eclispe RPC eclipse-RCP-3.2.1-linux-gtk-x86_64.tar.gz from eclipse site.
wget http://sunsite.informatik.rwth-aachen.de/eclipse/downloads/drops/R-3.2.1-200609210945/eclipse-RCP-3.2.1-linux-gtk-x86_64.tar.gz
Untar
tar xzvf eclipse-RCP-3.2.1-linux-gtk-x86_64.tar.gz
Get RadRails (0.7.2 or snapshot) from RadRails site
wget http://www.web20.com/downloads/radrails-0.7.2-linux-gtk.tar.gz
Untar
tar xzvf radrails-0.7.2-linux-gtk.tar.gz
Launch RadRails once (you need to do that to init RadRails configuration)
./radrails/RadRails
An error message will popup :
An error has occurred. See the log file
/del/radrails/workspace/.metadata/.log.

By editing this file you’ll read that a 32 bits shared library is doing some mess
!STACK 1
java.lang.UnsatisfiedLinkError: /del/radrails/radrails/configuration/org.eclipse.osgi/bundles/59/1/.cp/libswt-pi-gtk-3232.so: /del/radrails/radrails/configuration/org.eclipse.osgi/bundles/59/1/.cp/libswt-pi-gtk-3232.so: wrong ELF class: ELFCLASS32
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1751)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1660)
at java.lang.Runtime.loadLibrary0(Runtime.java:822)

Backup the existing faulty jar containing the bloody 32 bits library.
mv radrails/plugins/org.eclipse.swt.gtk.linux.x86_3.2.0.v3232m.jar radrails/plugins/org.eclipse.swt.gtk.linux.x86_3.2.0.v3232m.jar.backup
And replace it with the jar you downloaded from eclipse site containing 64bits shared libraries (like libswt-pi-gtk-3235.so)
cp eclipse/plugins/org.eclipse.swt.gtk.linux.x86_64_3.2.1.v3235.jar radrails/plugins/org.eclipse.swt.gtk.linux.x86_3.2.0.v3232m.jar
You can finally relaunch RadRails!

h1

How to make a simple image page counter / spyer in 20 minutes with Rails ?

January 27, 2007

At work I was a bit disappointed there is no counter on atlasian confluence wiki. I wanted to know whether my wiki page was being read by people and didn’t want to bug the admin to install the plugin for confluence. And this would be a good occasion to play with my beloved rails.

Prerequisites for your system (here kubuntu) :
I consider that you have rails installed (else sudo apt-get install rails), and mysql (else have a look here). You’ll also need to install mysql driver. First you need to install ruby packaging system : rubygems :
wget http://rubyforge.org/frs/download.php/16452/rubygems-0.9.1.tgz
tar xzvf rubygems-0.9.1.tgz
cd rubygems-0.9.1/
sudo ruby setup.rb

Gem needs dev package aswell else you’ll land with a
ruby extconf.rb install mysql
extconf.rb:1:in `require': no such file to load -- mkmf (LoadError)
from extconf.rb:1

To fix that :
sudo apt-get install ruby1.8-dev
You’ll also need libmysqlclient12 and libmysqlclient-dev :
sudo apt-get install libmysqlclient12
wget http://security.ubuntu.com/ubuntu/pool/main/m/mysql-dfsg/libmysqlclient-dev_4.0.20-2ubuntu1.7_amd64.deb
sudo dpkg -i libmysqlclient-dev_4.0.20-2ubuntu1.7_amd64.deb

Finally you can install the driver :
sudo gem install mysql

Create your application skeleton by :
rails counter
Edit counter/config/database.yml and fill your database settings.
Now we will think about the model, what we need to keep ? IP, Browser, when the page was visited and the image visited, can’t be simpler.
ruby counter/script/generate \
model visit

Now you can edit counter/db/migrate/001_create_visits.rb that will be responsible for the database creation and future upgrades.
We will add the column we need :
class CreateVisits < ActiveRecord::Migration
def self.up
create_table :visits do |t|
t.column "ip", :string, :limit => 50, :default => "", :null => false
t.column "created_on", :timestamp, :null => false
t.column "browser_agent", :string, :limit => 100, :default => "", :null => false
t.column "resource", :string, :limit => 30
end
end
def self.down
drop_table :visits
end
end

Create the schema in mysql (either by commandline or with MySQLQuery Browser for example). Now you can create database table and columns by just running the rake goal :
cd counter
rake db:migrate

If you land on getaddrinfo: Name or service not known it’s likely that you didn’t install the mysql driver (detailed in Prerequisites section).
Ok, we have our db ready, our model, and skeletons.
We will need an image library to create the counter image. I’ll use the popular and easy to use RMagick :
sudo apt-get install libmagick9-dev
sudo apt-get install imagemagick
sudo gem install rmagick

And after some minutes you’ll end with : Successfully installed rmagick-1.15.0 On windows you’ll just need to gem install rmagick-win32

What will be doing our CounterController ? We will render an image showing number of people that requested this image, and add a line to the visits in database. I created an image with framebox public/images/frame_small.jpg to make the counter look a little bit better than a simple number. (Yeah I know I could have created it with RMagick too).
Let’s create our controller CounterController :
script/generate controller Counter
We will add the method show in CounterController (app/controllers/counter_controller.rb) :
def show
@target = @params[:id]
counter_image = \
Magick::ImageList.new("public/images/frame_small.jpg")
text = Magick::Draw.new
# We count the visitor for the given target resource
counter = Visit.count(:conditions => \
[ "resource = ?", @target])
# puts "Counter for " + @target + " - " + counter.to_s
text.annotate(counter_image, 0, 0, 0, 0, counter.to_s) {
self.gravity = Magick::CenterGravity
self.pointsize = 16
self.font_family = "Verdana"
self.stroke = 'transparent'
self.fill = 'red'
self.font_weight = Magick::BoldWeight
}
counter_image.format = "GIF"
counter_image = counter_image.to_blob
# The image is created, we can render it as is.
render :text => counter_image, \
:status => 200, :content_type => 'image/gif'
end

Let’s add a filter to add a line to database, with IP… from the visitor (here we resolve the IP to get the dns which is more talkative in local network as here it contains the name of the user) :
before_filter :complete_stats, :only => :show
private
def complete_stats
@visit = Visit.new({:browser_agent => \
request.env['HTTP_USER_AGENT'], \
:ip => Resolv.getname(request.remote_ip.to_s).to_s, \
:resource => @params[:id]})
if @visit.save
#puts "Visit created"
else
#puts "Visit creation failed"
end
end

Finally you can test it (-p 80 will specify the port it turns on).
ruby script/server -p 80
You can now browse http://localhost/counter/show/imageA.gif, http://localhost/counter/show/imageB.gif, each time you visit one of them it gets incremented. Now you can insert in any confluence page a link to one of those virtual counter images and keep tracks of your visitors!

Of course this is a really simple version, but enough for my needs. You might check the referrers, count only one visit per ip per day…
You can get rails sources here (easier to read than from this wiki).