Rails 3 Internals: Railtie & Creating Plugins »
Created at: 04.08.2010 19:58, source: igvita.com, tagged: Ruby on Rails plugin rails railtie
With the official Rails 3 release on the horizon, all of the edge features we have been hearing about for over a year are about to become the new standard, and it has definitely been worth the wait. One of the primary goals of the "big refactor" has been to modularize Rails to allow other frameworks to easily extend or entirely replace any of the previously "critical" components (ActiveRecord, ActionMailer, etc). At the centre of all this, is the new Railtie logic, which pieces all of these modules together.
Getting started with Railtie
The documentation for Railtie is a great place to get started, but the interesting observation is that each of the major Rails components (Action Mailer/Controller/View/Record) is itself a Railtie, and Rails as you know it is simply pieced together by requiring all of the independent components. Even better, if your plugin or gem needs to hook into the Rails initialization process, all you need to do is inherit from Railtie and you are ready to go!
So how does Railtie know to call your classes and initializers? Railtie defines a self.inherited method, which is called anytime a subclass of Railtie is created, and stashes a reference to this class in a @subclasses variable. From there, the framework can simply call Railtie.subclasses and perform all the initialization as usual - a clever use of the Ruby object model.
Creating a Rails 3 plugin: 0-60
As a result of the refactor, creating Rails 3 plugins is at least several orders of magnitude simpler. In fact, as a simple exercise, lets create a custom notification plugin to print all of the internal Rails logging by also hooking into the new Rails::Notification API:
module NewPlugin # namespace our plugin and inherit from Rails::Railtie # to get our plugin into the initialization process class Railtie < Rails::Railtie # configure our plugin on boot. other extension points such # as configuration, rake tasks, etc, are also available initializer "newplugin.initialize" do |app| # subscribe to all rails notifications: controllers, AR, etc. ActiveSupport::Notifications.subscribe do |*args| event = ActiveSupport::Notifications::Event.new(*args) puts "Got notification: #{event.inspect}" end end end end
Believe it or not, that is a fully functional Rails 3 plugin, in 10 lines of code. Simply drop this file into your load path and require it in your application. In fact, you can bundle this file into a gem, ship it to Gemcutter and with the help of Bundler, all your users have to do is specify "gem 'ournew-plugin'" in their Gemfile, and the rest is taken care of. With a little more imagination, and fun, we can extend our example above into a 'slowgrowl' plugin, which will - you guessed it - growl at the developer anytime it detects a slow code path in your app! Hat tip to Gavin Stark for the idea.
Getting started with Rails 3
Railtie while an important piece of Rails 3, is hardly the only component worth looking into. Also read up on the changes in ActiveRecord, the new router, watch the summary screencasts on the Rails site, and make sure to check out one of the many great Railscasts on the topic by Ryan Bates. It has been worth the wait, Rails 3 is easily head and shoulders above the competition.
more »
Speed Tracer Server-side Tracing with Rack »
Created at: 19.07.2010 22:42, source: igvita.com, tagged: ruby Ruby on Rails chrome rack speedtracer
As anyone who has ever developed an interactive web app will know, Firebug (Firefox) and Inspector (Webkit) are your best friends. In fact, in many cases these tools are the "IDEs of choice" for manipulating the DOM, debugging JavaScript, and even working with CSS. However, have you ever wondered how many CPU cycles that script really took, or how much time the browser spent in reflow, as compared to just parsing the data? That's where Google's Speed Tracer comes in. Provided as a Chrome extension, it instruments the V8 VM, and the rest of the browser to provide detailed data about the GC cycles, painting, parsing, network resource loading and more.
The low level data provided by Speed Tracer finally allows us to peek under the covers to understand what the browser is actually doing - think strace, but for your browser. However, what if we could also bridge the gap between client-side and server-side tools? Wouldn't it be nice if we could go beyond the simple latency and response time reporting for network resources to viewing a full server-side log of what happened, all in one tool? Well, that's exactly what the Speed Tracer team launched at Google IO, so lets take a look at how it works!
Server-side tracing with SpeedTracer

The actual mechanics of getting server-side performance data into Speed Tracer are clever and simple. Whenever the browser receives a network response, it looks for the X-TraceUrl header, which specifies the relative URL and the unique ID of the trace for that specific request. From there, if the developer expands the network resource which provided the X-TraceUrl, Speed Tracer makes a request for the server-side trace, parses the JSON and surface it in the UI. This means that the server-side data is brought in on demand and does not affect the actual load times of your resources, and also that you need a mechanism to record, store, and serve these traces later.
Server side tracing with Rack & Ruby
The original announcement at Google IO demoed this new functionality on top of GWT and the Spring TC server. However, this same functionality is also easily extracted into a Rack middleware - which is what I did. In fact, here is a preview of sample trace from a Rails 3 application using rack-speedtracer:

The middleware takes care of providing the headers, persisting the traces, and then serving all the data back to Speed Tracer in the format it expects and understands under the hood. As a developer, you simply need to require the middleware, and then instrument your code where you want performance data to be recorded. Let's take a look at a simple configuration for a Rails 3 application:
# in your Gemfile gem 'rack-speedtracer', :require => 'rack/speedtracer' # in development.rb environment config.middleware.use Rack::SpeedTracer # define a widgets controller class WidgetsController < ApplicationController def index env['st.tracer'].run('Widgets#index') do env['st.tracer'].run("ActiveRecord: Widgets.all") do Widget.all end env['st.tracer'].run('Render') { render :text => 'oh hai' } end end end
At the moment, you need to manually instrument your code to record this data, but there is also no reason why we couldn't automagically instrument Rails to provide detailed breakdowns of what is going on inside - rack/bug is a great example. Of course, this functionality is not limited to Rails, and will work for any Rack application. There are still a few missing pieces in rack-speedtracer (see readme - patches are needed and welcome!) before you can deploy it in production, but it will work great for development purposes.
Towards unified client & server debugging
Having both the server-side and client-side performance data in a unified view can make our lives, as developers, an order of magnitude simpler - tired of correlating server logs with your browser yet? Having a mechanism to view this data on-demand, and in a single place is exciting, and I hope that the Speed Tracer team continues to innovate in this direction. It would be great to see more metadata about code locations, exceptions, object instantiation, and so on from within the same UI. But in the meantime, do install it, play with it, and give rack-speedtracer a try.
more »
Moving onrails.org to Typo 5.4.x, Rails 2.3.8 on Heroku »
Created at: 13.07.2010 00:47, source: OnRails.org, tagged: Ruby on Rails
So why Heroku and why not leave my server on slicehost? I don’t have any issue with the slice but I want to upgrade the version of Typo just to stay uptodate and while at it wanted to explore a little. So of course I found an article on Getting Typo 5.4 running on Heroku So I gave it a try.
The interesting part is that onrails.org has been around since forever and I also had to migrate the database. Onrails.org was running on a version of Typo 4.
setting the blog up locally
First I’ve downloaded my older typo MySQL database and restored it locally. I’ve copied Typo from here or you can clone the Typo git repository.
$ git clone http://github.com/fdv/typo.git
I changed the database.yml to point to my database. Did a rake gems:install, followed by a rake db:migrate and had now a local install of my blog.
creating a heroku app
The goal was to try to deploy the blog to heroku. So here you can create an empty
$ heroku create onrails git@heroku.com:onrails.git $ git init $ git add . $ git commit -m "Adding onrails.org using typo 5.4.4"
I then followed joels’ article to "heroku"fy Typo. So I basically created a few empty folders and replaced FileUtils by FileUtils::NoWrite. Note sure if that last change would cripple Typo but things seems to work fine.
Then I created a .gems files that is used by heroku instead of Bundler.
.gems rails = 2.3.8 htmlentities json calendar_date_select bluecloth ~> 2.0.5 coderay ~> 0.8 mislav-will_paginate ~> 2.3.11 --source gems.github.com RedCloth ~> 4.2.2 panztel-actionwebservice = 2.3.5 addressable ~> 2.1.0 mini_magick ~> 1.2.5
Finally I deployed the app with an empty database:
$ git remote add heroku git@heroku.com:onrails.git $ git push heroku master $ heroku rake db:migrate # with empty db
That’s it that gets you an install of Typo on Heroku. Note, keep reading for a few gotcha’s I found in regards to Rails 2.3.8.
Rails 2.3.8 on heroku
At the time of this writing Rails 2.3.8 wasn’t the default on Heroku, but fortunately they support a different stack with Rails 2.3.8. To switch I just had to do the following:
$ heroku stack:migrate bamboo-ree-1.8.7
Migrating the local MySQL database to Heroku’s Postgres database.
It’s a rather straight forward process…just do
$ heroku db:push
This converted the database and replaced the remote database with my local data on Heroku. It converts my MySQL database to a Postgress database without having to specify anything…But there was on gotcha. The Sidebar table id column turned out as “text” instead of an “integer”. And this caused some of the admin functionality to fail, i.e. reconfiguring the sidebar. The other tables where converted correctly and I saw that the local Sidebar id column was slightly different than the other id columns. For some reasons the sidebar table id column type was a "signed int’ and that translated to a text field when doing the db:push. So I just unchecked the signed flag and the db:push went smoothly.
legacy permalinks
Somehow the articles and category links are all prefixed with “/articles” on onrails.org. I don’t know if that was due to some default setting in Typo 4 or due to the fact that I started with a way earlier version of Typo. In any case I preferred to use the new links formats that just drops the “/articles”, but that would also mean breaking a lot of incoming links. So I just configured Typo to support the legacy permalinks via these added routes
# Legacy permalink format support
map.connect '/articles/:year/:month', :controller => 'articles', :action => 'index', :year => /\d{4}/, :month => /\d{1,2}/
map.connect '/articles/:year/:month/page/:page', :controller => 'articles', :action => 'index', :year => /\d{4}/, :month => /\d{1,2}/
map.connect '/articles/:year', :controller => 'articles', :action => 'index', :year => /\d{4}/
map.connect '/articles/:year/page/:page', :controller => 'articles', :action => 'index', :year => /\d{4}/
# Legacy permalink format support
map.resources :categories, :except => [:show, :update, :destroy, :edit], :path_prefix => '/articles'
map.resources :categories, :as => 'category', :only => [:show, :edit, :update, :destroy], :path_prefix => '/articles'
map.connect '/articles/category/:id/page/:page', :controller => 'categories', :action => 'show'Now the blog supports both new and old formats. Note that the url for the articles can be modified in the settings, but I didn’t find settings for the category permalinks and supporting both old and new format gives me a smooth transition forward.
Rails and Issue with Typo workaround?
I was getting the following error when doing certain actions on the blog:
ActionView::TemplateError (undefined method `interpolate_without_deprecated_syntax' for #<I18n::Backend::Simple:0x2b8d1ef90700>) on line #5 of themes/scribbish/views/articles/_comment.html.erb:
So I assumed this was some compatibility between Typo and Rails and Typo had a workaround defined in the environment.rb file file. As I use Rails 2.3.8 I disabled that workaround and everything seems to work again:
So I just removed the followed lines from the enviroment.rb file:
environment.rb
class I18n::Backend::Simple
def interpolate(locale, string, values = {})
interpolate_without_deprecated_syntax(locale, string, values)
end
end
custom domain
I’m sure there are a few more details I missed and hope my readers will point them out, but let’s jump and turn the switch on.
So you need to switch on custom domains on heroku as follows:
$heroku addons:add custom_domains $ heroku domains:add www.onrails.org Added www.onrails.orgas a custom domain name to onrails.heroku.com $ heroku domains:add onrails.org Added onrails.orgas a custom domain name to onrails.heroku.com
Then I went on to pointed my dns to Heroku.
The move is complete but the dns change to point to heroku still may take some time. So if you see the Scribbish theme you are still on the old server and if you see the Elegant Grunge theme you are right here on Heroku.
Enjoy,
Daniel
UPDATE 1: the dns updated www.onrails.org and onrails.org at different time. And all the images of the new sites where using urls of the old site and everything looked pristine. No more…So a hidden issue is that Typo let’s you upload files like images which are stored in the resources table and also copied to to the public/files folder. This is a convenient way to serve files and images for your blog entries. Well, that won’t work very well while on heroku especially since we really made the file system read only. I need to read more on how to enable page caching on Heroku and see if it is compatible with Typo. If not… I will need to revert back to my previous host. For now I’ll just add the files via git…and that’s not a solution.
more »
Moving onrails.org to Typo 5.4.x, Rails 2.3.8 on Heroku »
Created at: 12.07.2010 18:10, source: OnRails.org, tagged: Ruby on Rails
So why Heroku and why not leave my server on slicehost? I don't have any issue with the slice but I want to upgrade the version of Typo just to stay uptodate and while at it wanted to explore a little. So of course I found an article on Getting Typo 5.4 running on Heroku So I gave it a try. The interesting part is that onrails.org has been around since forever and I also had tomigrate the database. Onrails.org was running on a version of Typo 4. h2. setting the blog up locally First I've downloaded my older typo MySQL database and restored it locally. I've copied Typo from here or you can clone the Typo git repository.
$ git clone http://github.com/fdv/typo.git
I changed the database.yml to point to my database. Did a rake gems:install, followed by a rake d:migrate and had now a local install of my blog. h2. creating a heroku app The goal was to try to deploy the blog to heroku. So here you can create an empty
$ heroku create onrails
git@heroku.com:onrails.git
$ git init
$ git add .
$ git commit -m "Adding onrails.org using typo 5.4.4"
I then followed joels' article to "heroku"fy Typo. So I basically created afew empty folders and replaced FileUtils by FileUtils::NoWrite. Note sure if that last change would cripple Typo but things seems to work fine. Then I created a .gems files that is used by heroku instead of Bundler.
.gems
rails = 2.3.8
htmlentities
json
calendar_date_select
bluecloth ~> 2.0.5
coderay ~> 0.8
mislav-will_paginate ~> 2.3.11 —source gems.github.com
RedCloth ~> 4.2.2
panztel-actionwebservice = 2.3.5
addressable ~> 2.1.0
mini_magick ~> 1.2.5
Finally I deployed the app with an empty database:
$ git remote add heroku git@heroku.com:onrails.git
$ git push heroku master
$ heroku rake db:migrate # with empty db
That's it that gets you an install of Typo on Heroku. Note, keep reading for a few gotcha's I found in regards to Rails 2.3.8. h2. Rails 2.3.8 on heroku At the time of this writing Rails 2.3.8 wasn't the default on Heroku, but fortunaely they support a different stack with Rails 2.3.8. To switch I just had to do the following:
$ heroku stack:migrate bamboo-ree-1.8.7
h2. Migrating the local MySQL database to Heroku's Postgres database. It's a rather straight forward process…just do
$ heroku db:push
This converted the database and replaced the remote database with my local data on Heroku. It converts my MySQL database to a Postgress database without having to speify anything…But there was on gotcha. The Sidebar table id column turned out as "text" instead of an "integer". And this caused some of the admin functionality to fail, i.e. reconfiguring the sidebar. The other tables where converted correctly and I saw that the local Sidebar id column was slightly different than the other id columns. For some reasons the sidebar table id column type was a "signed int' and that translated to a text field when doing the db:push. So I just unchecked the signed flag ad the db:push went smoothly. h2. legacy permalinks Somehow the articles and category links are all prefixed with "/articles" on onrails.org. I don't know if that was due to some default setting in Typo 4 or due to the fact that I started with a way earlier version of Typo. In any case I preferred to use the new links formats that just drops the "/articles", but that would also mean breaking a lot of incoming links. So I just configured Typo to support the legacy permalinks via these addd routes
# Legacy permalink format support map.connect '/articles/:year/:month', :controller => 'articles', :action => 'index', :year => /\d{4}/, :month => /\d{1,2}/ map.connect '/articles/:year/:month/page/:page', :controller => 'articles', :action => 'index', :year => /\d{4}/, :month => /\d{1,2}/ map.connect '/articles/:year', :controller => 'articles', :action => 'index', :year => /\d{4}/ map.connect '/articles/:year/page/:page', :controller => 'articles, :action => 'index', :year => /\d{4}/ # Legacy permalink format support map.resources :categories, :except => [:show, :update, :destroy, :edit], :path_prefix => '/articles' map.resources :categories, :as => 'category', :only => [:show, :edit, :update, :destroy], :path_prefix => '/articles' map.connect '/articles/category/:id/page/:page', :controller => 'categories', :action => 'show' ActionView::TemplateError (undefined method `interpolate_without_deprecated_syntax' for #<i18n::backend::simple:0x2b8d1ef90700>) on line #5 of themes/scribbish/views/articles/_coment.html.erb: </i18n::backend::simple:0x2b8d1ef90700>
environment.rb
class I18n::Backend::Simple
def interpolate(locale, string, values = {})
interpolate_without_deprecated_syntax(locale, string, values)
end
end
h2. custom domain I'm sure there are a few more details I missed and hope my readers will point them out, but let's jump and turn the switch on. So you need to switch on custom domains on heroku as follows:
$heroku addons:add custom_domains
$ heroku domains:add www.onrails.org
Added www.onrails.orgas a custom domain name to onrails.heroku.com
$ heroku domains:add onrails.org
Added onrails.orgas a custom domain name to onrails.heroku.co
Then I went on to pointed my dns to Heroku. The move is complete but the dns change to point to heroku still may take some time. So if you see the Scribbish theme you are still on the old server and if you see the Elegant Grunge theme you are right here on Heroku. Enjoy, Daniel UPDATE 1: the dns updated www.onrails.org and onrails.org at different time. And all the images of the new sites where using urls of the old site and everything looked pristine. No mre…So a hidden issue is that Typo let's you upload files like images which are stored in the resources table and also copied to to the public/files folder. This is a convenient way to serve files and images for your blog entries. Well, that won't work very well while on heroku especially since we really made the file system read only. I need to read more on how to enable page caching on Heroku and see if it is compatible with Typo. If not… I will need to revert back to my previous host. For now I'll jst add the files via git…and that's not a solution.
more »
RailsConf 2010 - Thank You! »
Created at: 11.06.2010 08:30, source: OnRails.org, tagged: Ruby on Rails
Wow, RailsConf is over. It ended nicely with @garyvee giving a powerful and entertaining keynote covering many subjects but mostly his standard spiel on connecting with your customers or audience. I read his book, crush it, a while back and enjoyed it. Note since, I haven’t been the most active on my blog or website??but I’m working on changing this.
Now of course RailsConf was way more that this keynote. I must admit I really enjoyed Baltimore and having the convention center, the hotel and the port at a five minutes walking distance. It’s a great area, I understand that not the whole city is like that, but that doesn’t remove anything from the fact that I really appreciate the place right now.
The best thing at this conference is the energy that transpires and I really feel energized and want to start some new Rails venture. It’s fun to see so many enthusiasts trying to learn, share, and push the community forward.
I must admit I usually enjoy smaller conferences, like the MoutainWest RubyConf or the forthcoming Moutain.rb, better as the tracks are more specialized and geekier. RailsConf tries to have several tracks for everybody but very few are very technical. Maybe the organizers should try to have an advanced track next time. That way the conference would stay appealing for the many people that have been doing Rails/Ruby for years and still be welcoming for beginners.
As usual there are always some talks that just suck. On the tutorial day I attended in the afternoon Rails 3 Deep Dive and it wasn’t about Rails 3 nor a deep dive. Another talk that didn’t turn out the way it should have been was Scaling Rails on AppEngine with JRuby and Duby where the speakers where knowledgeable but where note prepared enough and where counting on the wifi to work??The wifi never works at conference. This said the wifi was usually working pretty well at RailsConf this time.
I don’t wanna focus too much on the talks that didn’t work out as most of the talks where great and also not all my talks in the past always worked out they way they could have ;-)
One of the tutorial I really liked was Acceptance Testing With Cucumber. David Chelimsky rocked and just knows his stuff and Aslak hanged in there pretty well. They had an application prepared with multiple branches that let the audience follow right along. That was great. They didn’t have time to access a few of the advanced Cucumber subjects??next time make that a full day tutorial.
The first talk I attended on tuesday was Building an API with Rails which was a panel discussion with guys from Twitter, 37Signals, Github, the NYT and others. I really enjoyed that there was several distinct views on several aspects like on APIs like versioning, security, performance which relates exactly with some customer work I’m currently doing.
Then I went to the Metrics Magic by Aaron Bedra from Relevance which cover tools like RCov,Flog, Flay, Roodi, Reek and how to integrate them with your continuous integration build. For example why don’t you make your build fail when it reaches a certain threshold of uncovered code (let’s say 20%)??I like that idea. We do generate these stats in our ci builds but don’t fail the builds??yet.
Another great panel on tuesday was The State of Rails e-Commerce. I’m interested in ecommerce since the first of Rails project I worked on end of 2005.
Then I went to see Ilya Grigorik talk on “No callbacks, no threads: async & cooperative web servers with Ruby 1.9”??I just wish all the task where that awesome??Ilya tries to push the current stack of Ruby technologies to the next step to try to get the same benefits than what node.js provides??and he showed us how. Wow.
I’m not gonna list all the talks I attended here, but will provide a few more comments. There where two business oriented talks I enjoyed, the Million Dollar Mongo by Obie Fernandez and Durran Jordan from Hashrocket and the Agile the Pivotal Way talk by Ian MCFarland. Ian’s presented how his teams operates and I now see why Pivotal is on such a growth path. There are many cool aspects they are enforcing, one key I believe is to have really agile team members than can switch in an out of each team while still providing continuity to the customer by having one anchor member. Another essential aspect is the culture and how they propagate it buy doing peer programing to the extreme. Obie’s talk was an interesting retrospective on a very large project (10’0000 hours) they undertook. What surprised me is that he was pretty negative on his client and also went after some members of the Rails community??Well, maybe Hashrocket should stick to smaller projects ;-)
What else was cool? Rich Kilmer gave a nice talk about Authentication in a RESTful World. Again, that’s totally relevant to a customer project of mine. One of the best talks out there was Rocket Fueled Cucumbers by Joseph Wilk, but I saw only the last quarter as I selected another talk that I decided to leave??too late.
Matthew Deiters also gave a presentation I really enjoyed about “Recommendations in Rails”??something I may have to build in one of my apps very soon. I’m less exited about the fact that he recommends a java tool (Neo4j) to manage your graph of relations??but I trust him that it’s the best of the solutions out there for now.
Besides the talks Bluebox threw a party at a local bar, besides the fact that Fernand managed to get us lost on they way and I wasn’t sure we would survive the neighborhood we ended up in??the party was great and we met one of the Bluebox software developers and her mam and had a great time. At least I think so based on the trouble I had to wake up the next day.
I had fun with the keynotes. Derek Sivers gave a talk which I enjoyed even though it was not related to Rails but it was very entertaining. I really liked Yehuda Katz talk and he his certainly the driving factor behind Rails 3 but he gave a lot of credits to specific members of the community which took on many issues that most thought where impossible to address or change and fixed them.
The Ruby Heroe Awards Ceremony is always fun to watch, and Gregg puts lots of effort into making them happen. Next time just let the winners make a thank speech??that would stress them a little.
Overall there wasn’t enough coverage of Rails 3, I guess that’s gonna for next year when everyone migrated all there projects to it.
So reflecting on these 4 past days??it was a great conference. A big thanks to the organizers and all the presenters
Now time to kick off a new Rails 3 project.
Enjoy!
Daniel
more »
