Ruby 1.9.3

Hooray – Ruby 1.9.3 is out.

So inquiring minds (at least my inquiring mind) wanted to know – does it really help with the rake issues related to the ruby require code?

Yes.

$ rvm get head$ rvm install 1.9.3$ rvm use 1.9.3@exrails31 --create$ gem install bundler$ cd project; bundle install

Results of a time rails console with immediate exit with a patched 1.9.2 (it’s a little slower than my previous post due to additional gems we’ve put in our project):

rubydev:learn (ruby-1.9.2@exrails31)$ time rails consoleexitLoading development environment (Rails 3.1.1)>> exit    real	0m13.684suser	0m12.257ssys	0m1.452s

In Ruby 1.9.3:

rubydev:learn (ruby-1.9.3@exrails31)$ time rails consoleexit/Users/jayoung/.rvm/gems/ruby-1.9.3-p0@exrails31/gems/activesupport-3.1.1/lib/active_support/dependencies.rb:240:in `block in require': iconv will be deprecated in the future, use String#encode instead.Loading development environment (Rails 3.1.1)>> exit    real	0m10.803suser	0m10.020ssys	0m0.777s

Here’s a mention of the deprecation warning. – but I’m not sure it’s reported yet (I honestly have a little trouble following the rails issues).

I’m personally still trying to get my app started – going to have to install my own rails_config for a few days until a new gem is released, so I’m not all sure what else might be a problem in 1.9.3 yet. But that will all work out, and I’ll take the three seconds!

[Update: everything’s working in our current under-development app with my own rails_config, and I’m not sure the iconv error is a rails issue as I trace through things]

[Update 2: The deprecation warning is coming from css_parser which is required by inline-style which we have forked in order to provide specific functionality we apparently need to reference an external mobile stylesheet but still convert inline styles.]

[Update 3: if you are landing on this post from search for the iconv error – you’ve got something requiring it in your app – see this stack overflow post]

Speeding up Rake and Rails in Ruby 1.9.2

Our team at work is currently in the beginning stages of a new project, that we started on Ruby 1.9.2 and Rails 3.1.  Most of our previous work was all Ruby 1.8.7 (Ruby Enterprise Edition) and Rails 2, though I have worked on a couple of REE 1.8.7 + Rails 3.0 apps.

I’ve also jumped with both feet (and not in the fun, fancy, parkour sense, in the 37-year old, flat arched, off a perfectly good one-story building onto concrete sense) into testing, and tenuously into TDD – and I think my first comment was “man, these tests are hella slow.”.  Only it’s not the tests that are slow (yet) – it’s rake.  That was my second comment – “what the hell is wrong with rake?”  My co-workers even looked at me a little funny when I brought it up.

As we were getting started last month, Rails 3.1 was still in RC status – and I would spend time browsing the Rails issues keeping track of the progress – and I remember reading this issue about Rails 3.1 boot performance – and reading the comment about the “require issue”.   That led me via Google to this stack overflow post and this rubyonrails core post – which I basically chalked up “core problem, it’ll be fixed one day”

Well that “one day” is now, because I can’t take it anymore.

This is the rails console startup in REE-1.8.7/Rails 2.3.14

rubydev:darmok (ree-1.8.7@extension_production)$ time script/consoleLoading development environment (Rails 2.3.14)>> exit    real	0m5.820suser	0m4.847ssys	0m0.787s

This is the rails console startup in 1.9.2/Rails 3.1

rubydev:knappsack (ruby-1.9.2@exrails31)$ time rails consoleLoading development environment (Rails 3.1.0)>> exit    real	0m18.766suser	0m17.020ssys	0m1.444s

Just a flat out “rake –tasks” takes over 9 seconds in 1.9.2/Rails 3.1!

So thankfully, google, the internet, and other irritated developers to the rescue. Thanks to this blog post from Xavier Shay (via: Peter Cooper at Ruby Inside, that I missed in my feeds the first time because “1.9.3” is not on my radar) – and especially this gist from Todd Fisher – and I have a glimmer of relief.

The quick instructions for the above:

1) grab the patch from the gist

curl https://raw.github.com/gist/1008945/4edd1e1dcc1f0db52d4816843a9d1e6b60661122/ruby-1.9.2p290.patch > load.patch

2) patch ruby

$ rvm cleanup all; rvm install 1.9.2 --patch ./load.patch -n patched

3) copy my gemset(s) over

rvm gemset copy 1.9.2@exrails31 1.9.2-p290-patched@exrails31

4) change my .rvmrc for the project…and voila!

rubydev:knappsack (ruby-1.9.2@exrails31)$ time rails consoleLoading development environment (Rails 3.1.0)>> exit    real	0m9.722suser	0m8.607ssys	0m1.081s

rake –tasks is now 6 seconds instead of 9, and test initialization is correspondingly faster as well.

It’s not REE 1.8.7/Rails 2 – but I’ll take any speedup I can get.

Refactoring my Rails devserver script

So with the last post – after I found out (while writing the post) that with the changes to Passenger 3 standalone – it (understandably) doesn’t support a debugger option – I needed a backup, like say, thin.

So, I refactored rewrote my script

This one will now run your choice of server (where your choice is passenger, thin, or mongrel, but it could be extended to anything. Since passenger doesn’t support –debug/–debugger – it will use one of the others.

I pulled the “–daemonize” option – because that doesn’t make a whole lot of sense for a devserver environment – and I haven’t used it yet since I’ve switched away from my Cocoa-based launcher. If you want another terminal for tailing the development log (passenger will pipe the development log to stdout for you), or running memcached, just open one.

One thing I’ve wanted to do for a while is get away from using “getoptlong” and over to something else for command-line option parsing. There’s where trollop comes in. I like trollop (and love the built-in –help, which I never write with getoptlong) – the only thing I don’t like very much is that because its “opt” method takes a block as the third parameter – so I can’t do something like opt(:setting,’description’,:default => @config[:setting]) – because that @config gets passed as part of a block and gets evaluated inside trollop’s library when it’s creating dynamic methods for the options. This would be fine if I had a set of hardcoded defaults that I wanted to override, but I want to read those from a config file as well as get overrides from the command line. That’s the reason for all the local variable assignments for the defaults. I’m sure there’s a better way of handling that, I’m just not sure what.

Update: 2011/01/07 The script has become its own gem

Heading into Rails TOOOOOO-TOOOOOO-TOOOOOO!

When I played little league baseball we had announcers for the game, one of which was some nice old guy in a ramshackle shelter behind home plate that was the “booth” – and every time there’d be two outs, two strikes and two balls – he’d croon “TOOOOO-TOOOOO-TOOOO”. Which of course, has little to do with this post other than version numbers.

Rails 2.2 was just released – so of course, I’m taking the most critical application we have (well, maybe the second critical, and that’s really only because other apps depend on it, it’s not critical in terms of features) – and upgrading it first, because, well, that’s how system administrators roll.

The release notes are great. Seriously. Really great. So great I shouldn’t even be writing this post. Which I am anyway – because here are some of the highlights of what I had to change to make my app work.

NoMethodError for Association Methods

Getting exceptions when you go to Rails 2.2.2 that don’t say anything more than NoMethodError when you know good and damn well the method that it’s saying no method on exists? Yeah, me too. And I bet it’s a method in an associated model. And if it is, you probably should be ashamed of yourself.

Rails 2.2 now enforces privacy on private methods called through associations. So in my case, I had two issues, 1) I was calling “update” on an associated model in some code I blindly copied and pasted a long time ago, and 2) I have a few of my own SQL queries that I’m not entirely sure how to do using Rails associations and named scopes, and I was cheating by calling self.connection.sanitize_limit to take advantage of Rails’ own function for cleaning up provided “LIMIT” params. And sanitize_limit, like the instance method update is private.

Update Rails Footnotes

If you use Rails footnotes in development mode – you’ll want to update for this change for Rails 2.2 compatibility.

Aside… Piston 1.9.5

A great way to stay current with Rails plugins is to use Piston – which has a new 1.9.5 release. You can build your own.

“quoted_table_name” and Has Many Polymorphs

If you start getting some error about undefined method quoted_table_name’` and you use has_many_polymorphs – you’ll want this change.

I don’t use the plugin, I use the gem. So I built my own has_many_polymorphs 2.12.1 gem – by doing: ` gem install echoe git clone git://github.com/fauna/has_many_polymorphs.git cd has_many_polymorphs `

edit CHANGELOG with a “v2.12.1 line” (e.g. v2.12.1. Cloned GitHub project and rebuilt gem for our nefarious purposes.)

rake manifest rake package rake install

add_joins! and Has Many Polymorphs (or anything else for that matter)

HMP includes a ‘tagged_with’ method for finding collections ‘tagged_with’ a set of tags. I use a heavily modified version of that. The method supports custom scopes, in theory. (well, probably more than theory, I’ve just never tried it). While, I don’t have any scopes on models that call my functions – I still had some of the private ActiveRecord method calls in mine – particularly add_joins!.

Well, this change changed the params for the method to make sure that the scoped joins were merged, and not overwritten – which changes calls into it. If you are calling it with your own options use options[:joins]. My code doesn’t use the scopes in combination with my tagged_with method, so I just pulled them.

And…. thankfully that’s it

Other than cleaning up deprecations like number_with_precision now preferring (number, :precision => myprecision) instead of (number, myprecision) – and ActiveRecord::Base.verification_timeout no longer valid, and mb_chars being preferred over chars – we seem to be good to go for Rails 2.2. I still need to test some crons, but I imagine that our app will go production as 2.2 shortly.

TOOOOOO-TOOOOOO-TOOOOOO!

Rails 1.2 Route Changes Are a Pain in the Arse

So, the rails routing changes that have apparently happened in Rails 1.2? Yeah – not a fan.

Thankfully, last night, the night before we plan a production transition to Rails 1.2, we got spidered by crawlers looking for old, vulnerable copies of phpMyAdmin – they hit a systems testing server.

I don’t think I’ve ever said “thankfully” with regard to a spider ever. This is a first.

That generated well over a hundred emails – where Rails oops with:

A ActionController::RoutingError occurred in application#index:      no route found to match "/whatever" with {:method=>:get}

We were able to find some information about using a catchall route at the bottom of routes.rb:

map.connect '*path', :controller => 'application', :action => 'show404', :requirements => { :path => /.*/ }

With a happy little trees show404 method to show a 404.rhtml and return a 404.

This really isn’t the annoying part, I like the routes idea, I like how easy it is to fix this.

What I don’t like is that between Rails 1.1.6 (or even the “edge rails” for 1.2) and 1.2.x – the routing changed such that requests to URLs that are not handled with a default route (e.g. :controller/:action/:id) result, not in a nice, happy, proper “404 – Not Found” but the “500 Internal Error”

I’m sure that this can all devolve into semantics, but if the URL isn’t handled – return not found, don’t crash.