Sunday, December 27, 2009

Making a gem out of your ruby-on-rails plugin

Generally, now, when we have the gemcutter service, making a gem is not a brainer. Just find a similar project on github, copypaste its gemspec, then say gem build my.gemspec and gem push my.gem and you're basically done.

But there are some options you might want to know about.

First of all to that gemspec business, as I said, if you never did that before, you'd better just find a famous plugin on github that is more or less close to your project, copy its spec in a file named my-plugin.gemspec in the root of your plugin and fill it up with descriptions of your project.

You might find the gemspec option descriptions here and here. For example if you need to show the user some post install message, use the post_install_message option like that

spec.post_install_message = %Q{
Warning! Warning! Annoying message!

And one more, some gemspecs on github use plain lists of files that should go into the spec, sometimes with several dozens of entries. Don't do that. First of all, it will be pain in the ass for you, because you might just forget to update the list when you create a new file, second of all it will be pain for another people who might be interested in evolving your project. Ruby is a nice language and has everything you need to process those stuff automatically. For example like that

spec.files = Dir['lib/**/*'] + Dir['spec/**/*'] + %w{

For the second thing, you need to understand how rails hooks up plugins and gems.

When you create a ruby-on-rails plugin there is a file called init.rb in the plugin directory. When rails fires up, it adds your plugin lib/ directory to the load-path and then includes this init.rb file. Basically that's a good idea, you can keep the actual code clean in one place, and the dirty monkey patching script in another. This way you can test them separately and use separately, like say you want your module be available as is, outside of the rails stack, say with Rack apps or something.

But when it comes to a gem, it's a bit different story. Gem supposed to be just a standalone piece of code which you require from your application. It doesn't know anything about initialization, and when ruby-on-rails hooks it up, it just requires a file with the same name as the rubygem.

Say you have a plugin named super_duper then you will have a file lib/super_duper.rb, which rails will include when the gem is specified in the config. So, if you want to convert your plugin into a gem, you basically have two options. Include your init script into the super_duper.rb file, probably with some additional dirty conditions, or create another file like lib/super_duper_lib.rb and make your user define the gem in rails config like that

conf.gem 'super_duper', :lib => 'super_duper_lib'

Both are quite dirty and yet pretty common.

But, there is another, nicer option that lets you avoid disadvantages of those two approaches.

The trick is simple. All you need is to name your ruby-gem in a dashed style. Like say you have a plugin super_duper, so you create a ruby-gem named super-duper, after that you just create a file named lib/super-duper.rb with one simple line of code in it

require File.dirname(__FILE__) + '/../init.rb'

When ruby-on-rails hooks up the gem it will load the dashed file, which will load your init script. This way you can share your initialization script between plugin and gem, and you still keep your actual code clean and easily available outside of the rails stack with the standard require 'super_duper' call.

Friday, December 18, 2009

Meet Shakker The Mano-A-Mano JavaScript Performance Testing Suite

I've started this project after several months of using Peter Higgins's TaskSpeed library as the main regression testing utility during the RightJS framework development.

TaskSpeed is a pretty well done library, but many people (including me) were complaining about its tendency to mix different tasks in one, mainly the css-selectors and stuff, so sometimes it wasn't clear what's going on. Another problem was that it provides just a total time as the summary, which is not an exactly clean way of judging about frameworks relative speed.

So I started my own little script, which become a bit bigger script and that one become even bigger one, and bigger and bigger. And now we have for ourselves practically an alternative solution for the TaskSpeed library.

Meet The Shakker!

The first difference between Shakker and TaskSpeed is that, Shakker has a two-level tests structure, the first one drives the test and keeps the data, the second one keeps the actual framework test. This way we have real-live like data separation on one side, and a blunt feature-to-feature comparison on the other. Shakker counts only the actual feature run-time for every framework, skipping utility operations like elements search, preparing collections, and stuff.

Another difference is that, Shakker not just collects the time summary, it collects differences between framework results for every test and then calculates average values between all the tests. It also let you choose one framework and evaluate it against others. This way you can have an approximated relative frameworks speed comparison.

It also keeps the original by-summary results, so that if your love sucks, you always can choose another result.

So what all this gives to you? See for your self. I'm posting results for all the modern browsers below, browsing through them you can actually see now what's going on. For example, you can clearly see, that say RightJS slows down in the building and finding operations under IE7,6 because it has to extend all the nodes manually on those browsers. You also can see where optimizations for jQuery 1.4 go, and you can see how Dojo fastly unbinds event listeners, because it doesn't have an internal events registry and makes the developer keep all the pointers manually. You also can clearly see how RightJS rips off everything under Chrome and Safari, because it doesn't uses any special proxy for dom operations, and uses common Arrays, which those browsers heavily optimize.

Lots of interesting stuff.

Google Chrome

Firefox 3.5.6

Safari 4.0.4

Opera 10.10

Konqueror 4.3.2 (Ubuntu on VMWare)

Internet Explorer 8 (WinXP on VMWare)

Internet Explorer 7(WinXP on VMWare)

Internet Explorer 6(WinXP on VMWare)

All the tests were performed in OS X 1.6.2, on 2Hz macbook with 4GB of memory.

Sunday, December 13, 2009

FrontCompiler With Rubygem And Console Tool

FrontCompiler is a Ruby based JavaScript/CSS/HTML compressing tool of mine. It can create albeit packed JavaScript, works with DRYed CSS, can inline css in javascript, works as a Rails plugin, etc.

And as I use it quite a lot on my projects, finally, I've created a rubygem for it. It's available at the gemcutter service now.

So if you use the project, you might just install it from there.

gem sources -a
gem install front-compiler

Along with the rubygem I've added a simple console tool to work with the compressor

$ frontcc file1.js file2.js ....

It will automatically recognize the file type by its extension, so you can feed it with javascript or css or html. It will read them all, compress in a single string and spit it in the stdout. You also can mix javascript and css in one command to make the css be inlined in javascript.


Saturday, December 12, 2009

RightJS vs. jQuery, Mano A Mano

After the RightJS 1.5 release, there was people hyping about RightJS being 6-8x times faster than jQuery. After that there was quite a fight about that and then funny boy Felix had posted an article which kinda says it's a bull.

Some people got it seriously, some people were complaining about the original test saying that the TaskSpeed util is not really representative case affected by css-selecters and stuff.

So I sat down and had written my own simple test, you can get it over here. This test eliminates any unnecessary disturbances, like elements selection, gets the questionable elements building process to the minimum and creates clean, pure functionality one-on-one performance test results.

The result is predictable and actually correlates pretty closely with the original TaskSpeed based benchmarks.

Google Chrome

Firefox 3.5.6

Opera 10.10

As you can see, in a blunt, face to face performance test, RightJS does murk jQuery several times.

Get use to it.

UPD: As I'm working on the test suite, I've added the pure-dom test and also publishing results for Opera.