A successful story of Ruby on Rails in the enterprise



Written by Anthony Heukmes on Fri May 29 11:24:37 UTC 2009

1 comment



Robert Martin gave a excellent keynote at RailsConf 09 "What killed Smalltalk could kill Ruby too" where he enforced that Rails must open his doors to the external world's needs.
There are a lot of good practices and conventions in the Ruby and Rails community and I really think it's the best framework for web development.
But our practices are not respected everywhere. Other people have different needs/visions and Rails should be a good solution for them too.

A simple example is related to primary keys. By default, database tables of a Rails application contain an auto-incremented ID acting like a primary key.
In his base version, Rails doesn't support composite primary keys. A plugin exists to add this functionality but it's not a core feature of ActiveRecord.
If you ask Rails fanatics for the reason of a such choice, they will tell you that composite primary keys is not a good practice and you should avoid them!
Unfortunately, those primary keys are everywhere in the professional world where a lot of big Oracle schemas don't respect our conventions. And they will of course not change to adapt to a new framework.

Rails have to adapt to that kind of needs if we want it to be a competitive choice for the enterprise.
And happily, Rails is more and more enterprise ready version after version.

I recently managed to integrate Rails in a big company which was only using Java. The goal of this article is to share the difficulties I met during the process. I hope it will maybe help you to accomplish the same "exploit" and make your dream comes true : using Rails on a daily basis!

Rails development on a legacy Oracle schema was my main fear. Until that day, my schema was always evolving with my Rails application and so, it was following the ActiveRecord conventions.
However, I rapidly discovered that it was easy as pie to configure an AR model to override these conventions. You can read my blog post on this subject. Executing stored procedures and other kind of boring stuff is also a piece of cake.

The scripting language term is scary for most people, mainly because of the slowliness idea associated to it.
Do not hesitate to reassure your customers by showing them many high traffic websites using Rails and enforcing that they don't encounter performance issues. Here is a list that will help you in this task.
Another argument to bring to light is JRuby on Rails. I think it's a great solution to integrate Rails more easily in the enterprise. Customers are very happy to learn that Rails can run on the JVM and that they will not totally leave the J2EE world.

Ruby and Rails skills is another major problem. If you suggest a new Java framework, chances are big that it will be accepted very easily. All developers in the company already know Java! But almost nobody knows Ruby and that means they will loose time because of the learning curve! And don't forget that many developers are not passionate by their job, they don't want to learn new technologies! Add to this the fact that it's already difficult to hire a good Java developer... how hard will it be to find Rubyists?

I personaly got rid of these fears by demonstrating how Ruby and Rails are easy to learn. Take the necessary time to prepare an attractive training during which you will share your excitement and your passion for this technology. I gave trainings to my colleagues and they quickly discovered Rails' benefits and how easy it is to learn. Most of my co-workers were then blowing the merits of Rails and I wasn't the only one to fight anymore.
"Awesome" was on every mouthes when my colleagues started their first test applications using our wonderful framework. What a pleasure to see their smiling faces!
I also compared pieces of Java and Ruby code if front of a customer so he can realize how Ruby syntax is clear and easy. And so, how Rails applications are easier to maintain over time.

Another issue is Rails development on Windows. I'm personally working on a Mac but I'm the only one.
We tried Aptana and Netbeans but it was clearly not a good solution. Happily, RubyMine released an excellent IDE. You have to try it!
A big problem is that Windows is even used for deployment. And we all know that deploying a Rails application on Windows is a pain in the ass. Plus, tools to monitor and deploy Rails applications are considered as toys compared to the powerful Java tools. One more time, I think that JRuby can be the perfect solution. The warbler utility makes it possible to create a war file from a Rails application. Once you have that, you can easily deploy your app on any J2EE application server. I'll talk about that in a next article.

The enterprise word is very often associated with portal. So a natural question is : "Is it possible to integrate a Rails application in a portlet?". I never personally tried but I read that it's possible to achieve.

The Java framework (Oracle ADF) that had been used since now by our customer was based on JSF so users were used to rich components like datagrids with sorting, pagination, etc. The kind of stuff we don't have out of the box with Rails. That why I created a Rails plugin based on jQuery to create full featured datagrids with just a few lines of code.

Finally, I will finish this article by giving a few arguments that convinced my customers.

RSpec was very appreciated! I simulated a failing test and the autotest-growl combo made a good impression.
Specs generation at the doc format was also an interesting point.
I was not using Cucumber at that time but I'm sure that it will impress too!

I aslo created a template for new projects creation. It contains the company layout (css, images, ...) and other shared functionalities. The possibility to generate a new application with just one command line was very appreciated.

Do not hesitate to share your experiences... I'll be happy to read them!

EdgeRails : rack router, protect_from_forgery & modules dependencies



Written by Anthony Heukmes on Fri Apr 17 16:16:01 UTC 2009

0 comment



The way towards Rails 3 is going on and you can find a lot of activity on GitHub these days.

First good news, Carl Lerche & Josh Peek are working on a new router (a Rack middleware, so it will not be only useful for Rails). According to Carl, performances are 2x faster than Merb router (and so, 4 times faster than Rails).

More information available on Rack GG group.

Another good news, we will not have to add authenticity tokens to our hand-written Ajax requests anymore!
You know, when you create a Javascript function that sends a POST request to your server and you get a nice "Invalid Authenticity Token" error message in return.
The solution is to add the token to your parameters or to disable CSRF attacks check in your controller using protect_from_forgery :except => :my_action.
This will not be required anymore with Rails 3!

The touch method has also been added to ActiveRecord models.
When called, it will save the record with the updated_at attribute set to the current time.

It can also be used as an option with the belongs_to association. So when the current instance is saved/destroyed, the associated object will be touched too.

belongs_to :company, :touch => true


If you follow the evolution of the Rails codebase you've probably been surprised by setup, depends_on and use keywords. You can see an example in this commit.

The source code for can be found in ActiveSupport (activesupport/ lib/active_support/core_ext/module/setup.rb) :


class Module
attr_accessor :_setup_block
attr_accessor :_dependencies

def setup(&blk)
@_setup_block = blk
end

def use(mod)
return if self < mod

(mod._dependencies || []).each do |dep|
use dep
end
# raise "Circular dependencies" if self < mod
include mod
extend mod.const_get("ClassMethods") if mod.const_defined?("ClassMethods")
class_eval(&mod._setup_block) if mod._setup_block
end

def depends_on(mod)
return if self < mod
@_dependencies ||= []
@_dependencies << mod
end
end


A cleaner way to organize modules inclusion and dependencies. Yehuda Katz wrote an article about that.

Add jQuery datagrids to your Ruby on Rails applications



Written by Anthony Heukmes on Mon Apr 13 14:53:33 UTC 2009

38 comments



It's now possible to add jQuery datagrids to your Ruby on Rails applications with just a few lines of code.

Have a look at the demo application of my new plugin : 2dcJqgrid.

Datagrids are based on a jQuery plugin and support the following features :

- Ajax-enabled
- Pagination
- Sorting
- Filters
- Multiple selections
- Master-Details
- Data manipulation (create, edit, delete)
- And more ...

Ruby : Establish a connection to an FTP server via a proxy



Written by Anthony Heukmes on Wed Apr 08 12:17:03 UTC 2009

0 comment



By default, it's not possible to connect to an FTP server via a proxy using the Net::FTP Ruby library.
To use your proxy, you have to send RAW commands to the server :

@ftp = Net::FTP.new

@ftp.connect("proxy_address")
@ftp.sendcmd("USER ftp_login@ftp_address proxy_login")
@ftp.sendcmd("PASS ftp_password")
@ftp.sendcmd("ACCT proxy_password")
@ftp.passive = true


Take the time to replace addresses and credentials by yours.
This code considers that access to your proxy server is secured by login/password.

Upload files in a BLOB field of an Oracle database



Written by Anthony Heukmes on Tue Mar 31 10:49:16 UTC 2009

0 comment



Customers used to the Java & Oracle worlds are often scared by the Ruby on Rails switch. They want to be sure that this new tool will do at least as much as the old one. This is a perfectly understandable reaction.
To do so, they regularly ask for a POC (Proof of Concept) development to confirm that a given functionality can be easily implemented using Ruby on Rails.

During one on my last meetings, the following reflexion came to my ears : "Are you sure that it will be possible to upload files in our Oracle database? I tried myself another scripting language (PHP) and I encountered many issues with BLOB!".

So here is my POC responding to this question.
I specified Oracle in the title of this article but the following Ruby code has nothing specific to this database.

First of all, we need a table and a model to store data related to our file. You'll aslo need a controller and views.
You can use the scaffold script provided by Rails to generate this structure :


$ ./script/generate scaffold FileUpload name:string content_type:string content_size:integer content:binary


Here is my migration file :

class CreateFileUploads < ActiveRecord::Migration

def self.up
create_table :file_uploads do |t|
t.string :name
t.string :content_type
t.integer :content_size
t.binary :content
t.timestamps
end
end

def self.down
drop_table :file_uploads
end
end


Note the type of the content column : binary. This will generate a BLOB field in your database during the migration :


$ rake db:migrate


Nothing special about the model :

class FileUpload < ActiveRecord::Base

end


You can then modify the creation form (new.html.erb) :



<% form_for @file_upload, :html => { :multipart => true } do |f| %>

<%= f.error_messages %>

<p>

<%= f.label :content %><br />

<%= f.file_field :content %>
</p>

<p>

<%= f.submit 'Create' %>

</p>

<% end %>


The form has been defined has a multipart and the content field is now a file_field.
You can then work on the create method of your controller :

def create

@file_upload = FileUpload.new(params[:file_upload])
if @file_upload.valid?
@file_upload.name = params[:file_upload][:content].original_filename
@file_upload.content = params[:file_upload][:content].read
@file_upload.content_type = params[:file_upload][:content].content_type
@file_upload.content_size = params[:file_upload][:content].size
@file_upload.save
flash[:notice] = 'FileUpload was successfully created.'
redirect_to @file_upload
else
render :action => "new"
end
end


Nothing complicated here, the params[:file_upload][:content] holds an instance of ActionController::UploadedStringIO on which you can perform various operations as reading data, get content type and size, ... All this information is then stored in the database.

In the show.html.erb page, replace the content by a download link :



<p>

<b>Content:</b>

<%= link_to "Download", :action => "download", :id => @file_upload.id
%>
</p>



Finally, insert the download method in your controller and you're done!

def download

file = FileUpload.find(params[:id])
if file
send_data(file.content, :type => file.content_type , :filename => file.name)
else
flash[:error] = "Invalid file ID!"
redirect_to :action => "index"
end
end


One more time, it's very simple! The FileUpload record is extracted from the database using his ID. The associated file is then returned thanks to send_data method.

You can now save any kind of file in your Oracle database!