RSS

Monthly Archives: July 2010

>Rails3, Rack and "Where did my Metal go?"

>

Our Rails3 (beta4) application had one route mapped in config/routes to a Sinatra app, by means of the following route:

   match '/foo', :to => EndPointApp, :as => :endpoint

The route was being defined to run as a Sinatra Application

require 'sinatra'
class EndPointApp < Sinatra::Application
  post '/foo' do
    ...
  end
end

This was working mostly fine, but it was returning Set-Cookie header with the standard Rails sessions cookie, which in this case was preventing the client of this endpoint from successfully interpreting the result. As I could do nothing about the client side, I had to remove Set-Cookie from the headers, but only for this end-point and obviously not from the entire app. This proved to be somewhat more complicated than I had hoped, so let me share the solution here in hopes it might save someone else an hour or two.

First, I ran “rake middleware” and observed the following Rack stack:

use ActionDispatch::Static
use Rack::Lock
use ActiveSupport::Cache::Strategy::LocalCache
use Rack::Runtime
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::RemoteIp
use Rack::Sendfile
use ActionDispatch::Callbacks
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ParamsParser
use Rack::MethodOverride
use ActionDispatch::Head
run Kigster::Application.routes

As can be immediately seen from here, the routes execute very last after Session::CookieStore already wrapped the request. OK, so looks like I need to bypass the routes somehow, and so I started to look at Rails::Metal, which is supposed to run before all other processing.

Once I started to look for Rails::Metal, I realized pretty quickly that I am missing metal generator:

> rails g metal
Could not find generator metal.

After a few more rounds of digging around, it turns out that in Rails3 Beta4 Rails::Metal has been completely removed, because it is no longer needed in a Rack environment.

So I had convert my Sinatra module to a Rack module, and insert it into the Rack middleware stack before the Cookie/Sessions:

require File.expand_path('../../../config/environment',  __FILE__) unless defined?(Rails)

module Kigster
  class EndPoint
    def initialize(app)
      @app = app
    end
    def call(env)
      if env["PATH_INFO"] =~ /^foo/
        process_request(env)
      else
        @app.call(env)
      end
    end

    private
    def process_request(env) 
       req = Rack::Request.new(env)
       params = req.params
       # do stuff
       [ 200, 
         { "Content-Type"   => "text/html", 
           "Content-Length" => "0" }, 
         [""]   
       ]
    end
  end
end

I had add the following to my config/application.rb to enable this Rack module, and have it run before the ActionDispatch::Session::CookieStore:

# config/application.rb
# require the file directly
require File.join(File.dirname(__FILE__), '../app/metal/kigster_endpoint')
....
module Kigster
  class Application < Rails::Application
    config.middleware.insert_after Rails::Rack::Logger, 
                                   Kigster::EndPoint
  end
end

Now my handler executes before the session, and the result does not include Set-Cookie header.

Any other suggestions on how to make this any simpler, or more correct are as always welcome!

Advertisements
 
1 Comment

Posted by on July 26, 2010 in Ruby on Rails, Technology

 

>Rails3 and The Inevitable Fragmentation

>

I remember one of the early talks at the Canada On Rails in 2006 had a slide showing how many books one needs to read to be able to write web applications in Rails, versus Java.

Of course Java side had about 10 books: Java SE, Java EE, Hibernate, Struts/Tiles/JSF, WebServices, Ant, Maven, Eclipse, JUnit, etc, etc.

The Rails slide proudly showed the now hopelessly outdated “Agile Web Development With Ruby on Rails”, 1st edition.

Those were the times. Back then, during my work for Blurb.com myself and three other engineers managed to learn ruby, rails and build a fully functional e-commerce site in about 3 months. I was blown away by the productivity gains compared to Java, where months could be spent laying out the project, and creating all necessary infrastructure for builds, deployment, automated testing with or without the database, etc.

Fast-forward to 2010. We are on a brink of Rails3 release, and oh boy, has the landscape changed since back then. I would argue that in some ways, you may be better off with Java than with Rails today for a couple of reasons:

  • Rails moves very fast. Books published in 2009 are already outdated. That pretty much leaves blog posts and online documentation as the main source of information.
  • Blog posts are not written as well as books are, they are not edited and are often heavily biased. They are also often outdated, and they are also often hard to find.
  • Rails now supports swapping out view renderers (from Erb, to Haml for example), Javascript libraries (from Prototype to jQuery, etc), ORM layers.
  • Testing frameworks are now (I think) approaching on a dozen. Forget Test::Unit, now it’s all about RSpec, RSpec-Rails, Shoulda, Cucumber, WebRat, Selenium, TDD, BDD, ShmoDD. Hot Damn.
  • Finally, to make the matters “worse”, it’s become very trendy to replace RDBMS with a document-based databases such as MongoDB, CouchDB, or even a step further — with distributed data stores like Cassandra or Riak. As with any trend, people are doing this regardless of whether or not they actually need it. Although this part clearly has nothing to do with Rails.

As someone who is trying to “quickly” catch up on all the recent changes that happened in the last 18 months during which I did not do any major rails development, it feels like I have to learn a lot of things from scratch, and unlearn a lot of things too. Even though I had three-four years of production Rails experience building Blurb.com and Infectious.com. That makes me wonder, how the newbies feel now joining the “new” Rails ecosystem. I am very curious to find out. I am guessing there is a lot of frustration and a steep learning curve required to master all the frameworks in isolation, and then bring them all together into the project. And that brings us back to where Java was exactly four years ago, and still is today.

I am not at all advocating for you all to go back to coding Java or COBOL :=) And I am absolutely not against Rails. But it’s about time we pull the curtain of naiveté and realize that RoR has become the complex multifaceted enterprise framework it was claiming to replace back in 2006, and to become proficient in it may take just as long, if not longer, then with Java EE.

Ironic? I’ll let you decide.

 
6 Comments

Posted by on July 8, 2010 in java, Ruby on Rails, Technology