Archive for the 'Ruby' Category

Jobalytics - a Passenger on Dreamhost

After Ninh pointed out Dreamhost’s mod_rails news, I was tempted to get my hands dirty deploying a test application.

I revivied one of my long lost pets (that hated the FCGI it was running on), made some modifications, and capified it to my Dreamhost’s account.

And … It was a breeze.

The deployment process (including capistrano script modifications, and enabling mod_rails for the domain) took around 10 minutes. Dreamhost made a good effort making the deployment easy (just a checkbox to enable mod_rails for the domain). I’m sure this has taken some effort from both Dreamhost and Phusion guys, so, Kudos to them.

Maybe afterall Dreamhost isn’t that bad.

Here’s a snapshot of the one-page application - jobalytics (Ruby Job Trends).

Ruby Job Trends

Passenger (mod_rails) on Dreamhost

I got an update from Ninh Bui from Passenger fame about Dreamhost progress on mod_rails adoption.

We’re working closely with Dallas Kashuba (CTO of Dreamhost) on getting Passenger ‘dreamhost’ ready (even though we’ve inferred it was already production ready, taking on a huge hosting company is a challenge on its own, i.e. it’s in its own league :-)).
We’re making excellent progress, and maybe I’ve already said too much ;-)
Stay tuned for a little longer!

from the Passenger Discussion thread.

Rails deployment that suits Rails development

The guys from Phusion - The Computer Science Company - released mod_rails (Passenger) today. I’m just feeling unusually happy.

They made a great job not only producing that longly-awaited piece of software (years in the waiting), but also creating a great hype, marketing, documenting, testing, and nailing down the details that made Rails deployment as easy and as enjoyable as Rails development.

Thank you guys for giving us that peice of software; it sure will lower barriers to entry into Rails/Ruby world even further. I know that there are rough edges, yet, the community owes a lot to these guys.

After a journey of Webrick, Apache+FCGI, Mongrel, Apache+Mongrel, NGinx+Mongrel and deployment processes that are more suited for JavaEE applications, now I’m finally prepared to enjoy Rails to the last drop.

Dreamhost!? I’m waiting.

UPDATE: A donation was due. Although modest, I felt compelled.

Rocket Science

Obie Fernandez, the author of the now de facto Rails book, The Rails Way, have recently launched HashRocket, a Ruby on Rails consultancy with a unique business model:

Your application in 3 days or your money back

OK! That money-back part is of my imagination.

The reason I’m writing this is the “great” message on their homepage.

BUILDING A SUCCESSFUL WEB APPLICATION IS ROCKET SCIENCE

See the word “successful”? It’s a great marketing phrase that reflect how they perceive the value they give to their clients. Delivering a successful web application is indeed difficult, and HashRocket is conveying that message loud and clear.

Congratulations.

Rails vs The 7 Frameworks

This has nothing to do with comparing 8 different frameworks.

It’s just to tell the horror story of one of our down-the-drain projects.

The client came with an old product that he needed to add new features to. The product does, what is best described as CRUD operations. Nothing challenging, nothing difficult. It maintains a set of data for various client in a certain business domain. Their business model (at least what they’re trying to do) is through ad and subscription revenue. They were trying to move the business forward through enhancing the provided service.

The only challenge can best be described as that the product was a pure mess.

It has been built using (last time I counted) 7 different Java frameworks, some redundant, some obsolete. Apparently it has been the greatest learning experience for few individuals. The product took 8 years in the making, 4 different teams (non remained with the project), 14,000+ files, absurdly normalized 100+ tables database, absolutely 0 documents, No unit/function/otherwise tests to reach its current state.

To give some example of code horror that we had to go through, some Java classes contained business logic, HTML code, display logic, data access mechanisms, hard coded urls. The objects were then instantiated from within JSP pages (with lots of other embedded Java business logic/code) and passed parameters and servlet controls.

This is not to mention the build scripts that took 3 hours to update code off of the CVS, then threw numerous errors during the “real’ build.

That’s in addition to the project tree which was in a state of absolute mess (40+ different individual modules, with some exact modules placed in different locations).

And have I mentioned the “wrapper” PHP application that was delivering a CMS-like functionality (another set of mess, with no cross-application awareness of any kind).

Again, the product didn’t do anything challenging. Just basic CRUD and a couple background processes.

Our initial attempt was, of course, to build on top of the insanely absurd code-base, but after few days, we’ve decided (us, client, operations) that it might worth to venture into a new platform, in order to make it easier (and cheaper) to deliver new business service and at the same time, incrementally migrate features into a more robust code base.

Few months into the making; including the client formulating his requirement and reverse engineering the legacy system, we had our first release of the new business features (including the integration with the original application, modelling 70% of the legacy schema, a streamlined version of few original functions, documenting finds of the original application).

Few more months of client acceptance testing (and repetitive requests from our part for a feedback), client vacations, and [seemingly] client running out of budget, the client finally came back to us deciding that our solution was not accepted.

I frankly didn’t know whether to laugh or cry.

Despite the fact that the client admits, in his own words, the original Java application is a bag of “s$%t”, he refuses any attempt from our side to tell him that his application is non-maintainable.

He decided (and probably promised by some other individuals) to monkey-patch the code base that he has. He, of course, threw our choice of Ruby into the bag of reasons not to pursue this further.

Although I can defend our decision to resort to an incremental migration, and taking Rails as our vehicle quite well, yet, I now believe that the choice of technology should be the least of his worries. The business decision of incremental migrations (or even rather a rewrite) remains the optimum choice in my opinion, whether it’s done in Ruby, Java, PHP or brain*^%&.

The moral of the story is: As long as you care, never be a door mat, insist on getting your ideas through, always believe that you’ve been hired not for your typing speed, but for your intellectual abilities and what they can bring to the business.

Rails Sitemap

“When something is too hard, it means that you’re not cheating enough. it means that you’re doing it wrong“. Generating a Rails sitemap (hash of application controllers and actions) is as simple as placing and calling this method in your application:


  def controllers_and_actions
    require 'find'
    site_map = {}
    Find.find(RAILS_ROOT + '/app/controllers') do |file_name|
        if /_controller.rb$/ =~ file_name
          name = File.basename(file_name, ".rb")
          site_map[name] = []
          Object.const_get(name.classify).instance_methods(false).each do |act|
            site_map[name] << act
          end
        end
    end
    site_map
  end

Rails - multi selects for associated models

Handling Multiple Selects (or multiple associated attributes) can be quite cumbersome. Ryan Bates has recently wrapped it very nicely in his Complex Forms Screencast. As per that simple way, here’s a how I handle it:

Model:


class Project < ActiveRecord::Base
….
has_many :assigned_tasks
has_many :users, :through => :assigned_tasks
….
def assigned_task_attributes=(assigned_attributes)
assigned_attributes.each do |attributes|
assigned_tasks.build(attributes)
end
end
end

Controller:
def create
@project_task = ProjectTask.new(params[:project_task])
@project_task.save

New/Edit Views:
<%= select_tag("project[assigned_task_attributes][][user_id]“, options_for_select(@users.collect{|u| [u.full_name, u.id]}, @project.assigned_tasks.collect{|a| a.user_id} ), {:multiple =>true, :size => 5 }) %>

Adding the virtual attribute in the model saves a ton of (ugly) work in the controller.

UPDATE: Minor tweaks are required for the update operation (remove association collection before updating the model - wrap this in a transaction)

Blueprint-CSS

After using the CSS Framework from Content-with-style for a few years, I grew tired of how it’s structured, and how difficult it is to customize.

Along came Blueprint-CSS. A great concept, and wonderful implementation. And with the new BlueprintCSS Generator plugin for Rails from Ariejan.net, how can I resist using it. I’m rolling it out in my current project and starting to feel the ease of customization.

Stay tuned for more updates on how it would turn out.

Pyramids, Application. An Analogy

Working on maintaining and modifying a five year-old Java application, I came to realize there’s a strong relation between legacy and pyramids. Here’s an analogy:

  • Huge PyramidPyramids are HUGE monuments, built for the sole purpose of being a tomb to one person.
  • Although the project tree is HUGE (14000+ files), the purpose of the application is amazingly modest (CRUD + search)
Building the pyramid

  • Pyramids required a lots of resources to build (time, wealth, labor).
  • The application took 5 years, 4 teams and lots of $ to build.
Build Method

  • No one knows exactly how the pyramids were built.
  • Compiling/Building the application is a black box. “Just invoke those commands - twice - and you’ll get your ‘war’ files”, said the Build Master.
  • Ancient scripts are quite scarce inside the Pyramids.
  • Project documentations are almost non-existent
  • Sometimes you wonder what motivated people to build such a thing, in such a shape.
  • The schema is highly normalized (talk about contact information spanning across 4 different tables, with email field divided into name and fqdn) - WHY?!
  • When you look closely, Pyramids are built by stacking layers of stone blocks on top of each other.
  • The application is a grand collection of all sorts of frameworks (counted 4 so far), libraries (uncountable), tools, architectures.
  • Currently, some Pyramids aren’t structurally sound, and visits to them are quite limited in fear of falling rocks.
  • Dare adding new code to that monster?
  • Bent PyramidImperfect pyramids can be found along side perfect ones, proving that it took builders decades to master the way they were built.
  • The application contain all sort of “imperfect” code as a proof of how the builders gained experience over time (JSP files with Embedded Classes, with embedded Java code and hard coded urls, business logic, view logic and data access mechanisms)
  • People visit the Pyramids for few hours as a source of great admiration and respect. Then, continue on with their lives.
  • The application’s code is a source of respect and admiration, but when it comes to something functional, better build something else.
  • Pyramids can’t be maintained.
  • The great conclusion.
UPDATE:

  • Some people have been reported to complain about a sense of suffocation or claustrophobic symptoms when exploring the pyramid internal passageways.
  • The same is experienced while reading the application code.

:finder_sql - single vs double quotes

This is the trickiest part of Rails I came across so far:
In my has_many association I have a finder_sql that should reference the instance object id rather than the class object id.

has_many :breedtypes, :finder_sql => 'SELECT Breedtype.* FROM ... WHERE (cai = #{id})'

Now, who’d ever have thought that replacing the “double” quotes I had wrapping the “Select” statement, would change the context from which id is interpreted.

Single Quotes -> #{id} = Object ID
Double Quotes -> #{id} = Class ID

Here’s the quote that saved the day from Jeremy (on http://lists.rubyonrails.org/pipermail/rails/2005-February/002752.html)

When you use “double quotes” the string is interpolated immediately in Project class. When you use ’single quotes’ the string is interpolated by Rails in the context of a Project instance. Use single quotes & you’re good to go.

Phew!

Next Page »