The Ultimate .htaccess File
This is a thing of beauty: My Webapplication Firewall Tutorial.
Note that if you’re going to use it with a Rails app you’ll probably want to remove DELETE from line 5.
Blaine Cook on Scalability
In this very interesting interview with Blaine Cook (once of Twitter fame) Blaine provides the best analogy for describing “performance” vs. “scalability” I’ve yet to read:
Performance and scalability are very different things. Performance is like the speed limit; it’s a question of how quickly you can get from point A to point B. In this case, we’re talking about how quickly you can get a page rendered and delivered to the user.
Scalability is a question of how many users you can handle. Highways intrinsically don’t scale, for example, because when they’re full, you get traffic jams. In web architectures, what we aim to provide are systems that will expand (usually by adding more hardware) to handle more traffic.
Obviously they’re related – if you have a traffic jam, then the effective speed limit is lower than the theoretical limit. But increasing the speed limit won’t make traffic jams any better.
There are a whole bunch of ways to make traffic less congested – adding more lanes to the highway, encouraging people to use public transit, or better yet encouraging people to work closer to home.
Likewise, there are many techniques for making web sites more scalable, and most of them don’t involve making things much “faster”.
As an aside, I continue to be impressed by Blaine’s grace under the seemingly relentless “Tw/ails doesn’t scale and it’s your fault” onslaught. Good on you sir.
Unread Messages Count in LovdByLess
Recently Less Everything released their “social network in a box” platform Lovd by Less, built upon the Rails framework, and it’s pretty nice. Very easy to set up and get running. I’m enjoying hacking around in it.
One of the first things I noticed was that users weren’t told how many unread messages they have when in their dashboard. Easy enough to add, just make these two small changes:
1. In _private.html.erb change the Messages link to:
<%= link_to( "Messages (#{@p.unread_messages.length.to_s})", messages_path ) unless @p.received_messages.empty? && !@p.has_network? %>
2. In profile.rb change the has_many association to:
has_many :unread_messages, :class_name => 'Message', :conditions => ["messages.read=?",false], :foreign_key => 'receiver_id'
(I suspect the change above is actually a fix to an existing bug since calling @p.unread_messages as-is throws a SQL error).
Ruby 1.9: Not For Rails
Do NOT install or upgrade to Ruby 1.9 if you’re using Ruby for Rails development.
There, that warning ought to suffice.
On Dec. 25 Matz announced that a development release of Ruby 1.9 was available in which the Ruby 1.9 spec has been frozen:
We are happy to announce of the release of the 1.9.0 the development
release.We hope this helps you to enjoy hacking. Happy Holidays.
matz.
However, Ruby 1.9.0 is not a drop-in replacement for Ruby 1.8.* with more good stuff inside, many fundamentals have changed, often in incompatible ways. As Dave “PickAxe” Thomas notes:
This is a development release, not a production release. It has known bugs, and there’ll be more to come.
It contains several incompatible changes (block parameters are now block-local, String is no longer Enumerable, “cat”[1] now returns “a”, rather than 65)
It is more rigorous that 1.8 when it comes to detecting invalid code. For example, 1.8 accepts /[^\x00-\xa0]/u, while 1.9 complains of invalid multibyte escape
the likes of which are guaranteed to break either Rails, some critical gem, a required plugin or your own code. Honestly, it’s guaranteed.
As example from the Rails list:
just now i installed ruby 1.9 and rails 2.0.2 on it. when i create new rails application
username@ubuntu7.04:~/project$ rails app
can’t convert Enumerable::Enumerator into Array
and
Agreed. I just upgraded to 1.9 and found all my applications totally
hosed. I had to delete 1.9 and reinstall 1.8.6, along with Ruby Gems (on
Leopard).I’ll be waiting for the official announcement of compatibility on the
Rails blog.
and from Rick DeNatale:
I just answered a post from someone on the TextMate forum who
installed Ruby1.9 as ruby. Now he gets a syntax error inside textmate
when he tries to run a ruby program, since Textmate uses ruby
internally, and some of that code ran into one of the syntax
incompatibilities.
Anyway, you get the idea.
If you really want to play around with Ruby 1.9, perhaps to help with the testing or just to get an idea of what cool stuff will be landing in Ruby 2.0, Dave Thomas’ post, cited above, provides great details in just how to do that.
Congrats to Matz and all the ruby-core team on 1.9.
Update: Should you need even more proof of the current “dev” state of Ruby 1.9.0, a fairly significant string encoding bug was bound found, isolated and fixed just four days after release.
Jump-start on Rails 2.0: Rails2 PeepCode
Ruby on Rails 2.0 was released on Dec 6, 2007 and fortunately for me I had the luck of starting a brand new Rails project on Dec 9. A brand new slate on which to try out all the new Rails toys.
Invaluable in this has been Ryan Daigle’s Rails2 PDF, a well-written compendium of what’s new, what’s changed and examples thereof. It also contains the complete Rails changelog, which seemed silly to me at first glance but has since been surprisingly useful as a desktop, keyboard-side reference in its own right.
Admittedly all the information contained within can probably be found on the web and piece-meal if you manage to read all the major Rails blogs each day but for $9 having it summarized like this has made it well worth the price as a bridging document until the Rails 2.0 books start to appear.
Rails Functionality Into Plugins
With the release of Rails 2.0 quite a bit of core functionality has been pushed out into plugins, presumably to lighten the core and allow for these plugins to take development paths and release schedules independent of that of Rails itself.
I just ran head-first into this while trying to use in_place_edit_for which generated this error:
undefined method `in_place_edit_for’ for FaqQuestionController:Class
The docs don’t make it immediately obvious (or rather, they’re completely obtuse) about which plugin the functionality has been moved to. Fortunately one can figure this out for one’s self via the Svn repository:
· CHANGELOG
· account_location/
· acts_as_list/
· acts_as_nested_set/
· acts_as_tree/
· atom_feed_helper/
· auto_complete/
· continuous_builder/
· deadlock_retry/
· exception_notification/
· http_authentication/
· in_place_editing/
· javascript_test/
· legacy/
· localization/
· open_id_authentication/
· scaffolding/
· scriptaculous_slider/
· ssl_requirement/
· token_generator/
· tzinfo_timezone/
· tztime/
· upload_progress/
(Thanks to Ryan Bigg via the rubyonrails-talk list.)
Don’t Preface Partials With Numbers
I just learned today that it’s a bad idea to name your Rails partials starting with a number, ie: _4_happy_places.html.erb. Turns out Rails throws the following error if you do:
`@4_happy_places’ is not allowed as an instance variable name
This has been tested against Rails 2.0.1.
Google Map Markers in YM4R/GM
When using YM4R/GM, by Guilhem Vellut, in your Rails app chances are you’ll want to mark points on the map using custom icons. The means to do so is not readily apparent or straight-forward. I’ve found that this works well:
map = GMap.new( Constants::GM_DIV_ID, Constants::GM_NAME )
# Define the start and end icons
map.icon_global_init( GIcon.new( :image => "/images/google_maps/icong.png", :icon_size => GSize.new( 24,38 ), :icon_anchor => GPoint.new(12,38), :info_window_anchor => GPoint.new(9,2) ), "icon_start")
map.icon_global_init( GIcon.new( :image => "/images/google_maps/iconr.png", :icon_size => GSize.new( 24,38 ), :icon_anchor => GPoint.new(12,38), :info_window_anchor => GPoint.new(9,2) ), "icon_stop" )
icon_start = Variable.new("icon_start"); icon_stop = Variable.new("icon_stop")
if respond_to?( "start_lat" ) && respond_to?( "start_long" )
map.center_zoom_init( [start_lat, start_long], Constants::GM_ZOOM )
map.overlay_init( GMarker.new( [start_lat, start_long], { :icon => icon_start, :title => name + " start", :info_window => "start" } ) )
end
if respond_to?( "end_lat" ) && respond_to?( "end_long" )
map.overlay_init( GMarker.new( [end_lat, end_long], { :icon => icon_stop, :title => name + " end", :info_window => "end" } ) )
end
Of Sivers, CDBaby, Rails and PHP
A couple days ago Derek Sivers of CDBaby (disclosure: I’m a big fan of the site, though perhaps not the current design) wrote an O’Reilly article titled ’7 reasons I switched back to PHP after 2 years on Rails’ about how he spent two years trying to rebuild his site in Ruby on Rails before switching back to his tried-and-true PHP to finish the job. If you’re a developer give it a read, it’s well worth it. Unfortunately the article has also stirred up a hornet’s nest of comments and criticisms, many from respectable blogerati and quite a few in response to the comments received both on the O’Reilly article and on the Slashdot post.
To preserve my sanity and faith in humanity I don’t read Slashdot comments – those I leave for fools and masochists – but I did decide to go back and re-read the original article and then the subsequent comments. I gotta say: I’m really disappointed in the tech community in general. You’d think someone just walked up to them and said “Damn, your kid is stupid and ugly, and that’s his good side” by the way we’ve reacted. I just don’t get it.
After re-reading the article I was struck with a number of thoughts that just wouldn’t leave, first and foremost: why wasn’t Rails suitable? As a Rails developer when a really smart, successful developer comes along, spends two years trying to work with my (currently) favourite framework and finds a problem with it, I sure as hell want to know what those problems were because chances are they found limitations and edge cases I haven’t even begun to explore yet and some day they might bite me on the ass. I want this guy to write more articles about his project; about the Rails aspect, the PHP aspect, the failures, the successes. How many other projects of this magnitude can claim to have been developed in two competitive platforms like this?
Caveat: I’ve been a PHP developer for years before I was a Rails developer and I really like PHP, warts and all. I really like Ruby too, but I don’t yet profess to know it nearly as well as I do PHP. I’ve only built three production sites in Rails so far so my experience is still limited.
I also wondered: Rails of two years ago (before my time) strikes me as an perhaps an immature platform from what I know of it, primarily usable only by those intimately familiar with it and for a specific types of applications. Derek clearly knew this because he hired Jeremy Kemper so how does the Rails of yore stack up against the Rails of today? Does Jeremy still think the barriers would be there?
I wondered: how did Derek reduce the PHP codebase by so much? It’s not magic, he clearly knows what he’s doing and understood his system to an impressive level (he reduced by a factor of 8). I want technical details about his optimizations.
I wondered: where does a guy find the balls to scrap two years of work and start all over from scratch? As the client he clearly had the authority to do so but man, how many of us can say we’d step up and do that instead of continuing to try and shoe-horn our “solution” just a little bit longer. There’s some lessons in the thought processes and decisions that went into that choice, I’d like to hear them.
Even a second time through I was having fun with this article.
But then I got to the comments. So much venom levied against a guy who basically said “Huh, a Torx wrench doesn’t work as well as my trusty Phillips screwdriver for this project, guess I’ll use the Phillips.” Are we developers really so fragile that we can’t stand the thought of someone doing something that isn’t our way? Are we really so arrogant as to think our experience the only one worth having?
Comments like this are just pathetic, they shame us all:
Useless post without a concrete illustration.
Looks like you among many out there had a poor team. Poor development environment where you were working on several projects at once and putting priorities in wrong order among several projects. I will have to say being stuck in one mental framework can be hard to overcome, especially when learning to code in a new and cleaner manner as per Ruby on Rails. But you actually could have coded so much more faster had you stuck to your guns and not given up, or not, since you prioritized among so many projects.
Why didn’t you hire a Rails core member? Who is Jeremy Kemper? I have been programming in Ruby for 4 years now and I have never heard of him.
(I wanted to not comment on the comments but this one take the cake. Not only did this poster obviously not read the article – the answer is only in the second paragraph – his gross arrogance and incredible lack of knoweldge and Google-fu would immediately make him a “never hire” for me. Aaron, Google up a clue.)
Reading your reason #6, I see that you totally don’t get what rails is. And thats pretty sad as a resumee after 2 years.
Oh and I just checked out your site. What an ugly P.O.S! 2 years and you can’t build craigslist for CD’s using rails. Jesus.
Etc. etc. etc.
We’re developers. We build things. We create from nothing the beautiful things that the rest of the world uses, uses without ever thinking about how those things were built. Only we care about the creation process but I think in this case we’ve lost sight of where we developers end and our tools and processes begin. We are not our tools, we’re the sum of our output. To become emotionally attached to a tool or methodology is to limit ourselves in a terrible way. They’re just lines of code, collections of bytes, arrangements of magnetic dust on metal platters. Geez.
This guy scrapped his original site to rebuild it from scratch on a hunch it might go better. When that failed he didn’t get religion and scream and cry, rend his hair, curse the gods. He scrapped it and found a better way. And then he built it.
That, ladies and gentlemen, is the essence of a real developer.
Reloading dispatch.fcgi
Rails development is usually done using dispatch.cgi so changes are readily apparent. However dispatch.cgi is painfully slow for a production environment so it only makes sense to use dispatch.fcgi. You can check which you’re using by looking into your /public/.htaccess file. In this case I’m running dispatch.cgi and .fcgi is commented out:
RewriteRule ^$ index.html [QSA]
RewriteRule ^([^.]+)$ $1.html [QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ dispatch.cgi [QSA,L]
#RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
Problem is dispatch.fcgi won’t immediately recognize changes made to content. In order to force a flush of all dispatch.fcgi instances we could kill all the processes but this seems better to me:
[chris@enki ticklist]$ touch public/dispatch.fcgi