I decided to take a new job in San Francisco. Here’s a map. I postponed this “announcement” of it because people at my current company didn’t know, so I didn’t… well, actually I’m just lazy. So here it is! It’s called Attendio, it’s run by Gerardo Capiel, and I’m the first salaried employee. I finally get to do Rails full-time, and I couldn’t be happier about it.
I’ll post more info about it as it comes, but here’s some basics: I start around the 11th, I’m looking for apartments, but it’s kinda confusing - so many neighborhoods! Any suggestions?
There are a few tickets on the RoR trac asking for some sort of compression of the source (#5830, #4729, #4191). I’ve traditionally been against this, mainly because I’ve used third-party libraries that were minified, and found them impossible to work with when something goes wrong. With the most recent ticket, I found myself writing another comment and closing it, but I decided to look into it more before I did. I used the Dojo compressor (labeled rhino) and Dean Edward’s packer (labeled packed) to compress prototype.js.
55149 prototype.js (100%)
12479 prototype.js.gz (22.6%)
22541 prototype.packed.js (40.9%)
10450 prototype.packed.js.gz (18.9%)
38696 prototype.rhino.js (70.2%)
11208 prototype.rhino.js.gz (20.3%)
The Dojo compressor works with Prototype without any modification to the source. Dean Edward’s packer required adding semi-colons in a number of places, and took several run-throughs of the packer to debug the result. So you can beat regular ol’ gzipping by 2.3% of the original size (10.2% further reduction) easily with the Dojo compressor, or by 3.7% (16.3% further reduction) with some work on your part with Dean Edward’s packer. These rather modest gains strike me as simply not worth the effort. Anyone have different results?
I’ve used NewsFire for all my RSS needs for a while now. I don’t really like the fact that I had to pay for it, but I understand that there’s very little incentive for a developer to do a good job (or do anything) when he is not compensated for his work. So I paid for a license. Why? Because it looks great and is drop-dead simple to use (space bar and enter key are almost all you need), and none of the free alternatives worked as well, as much as I might have liked them to.
A feature that was added recently is the ability to watch video podcasts from within the app. So what? I don’t watch any - oh wait, I do watch Ze Frank. Hey that’s pretty cool! I can make it bigger without the silly cmd+opt+8 trick, and the space bar works.
If you’ve been itching to drop NetNewsWire Lite and go for a better app, this weekend people who buy NewsFire will get Inquisitor for free. And those who blog about the promo will get Inquisitor free too
.
You may have noticed code that looks like this:
What, you may ask yourself, does this do? Firstly, each, map/collect, select, reject, inject, etc. are all methods on Enumerable that are included by various classes, like Array. They are the basis for dealing with Arrays in Ruby, and each is the one on which all the others are built (whether literally true, I don’t know, but they could be).
All these methods expect to pass each element of the Array in turn to a block (anonymous function), which normally looks something like this:
array.each {|item| puts item.inspect}
However, there are times when you want to use the same block many times, in many different places. In such cases, you don’t really want your block to be repeated over and over again, so you encapsulate it in a Proc instance:
my_block = Proc.new {|item| puts item.inspect}
array1.each(&my_block)
array2.each(&my_block)
Notice that you use the method-passing syntax of parenthesis rather than block syntax when calling each, and that both calls prefix the block with an ampersand. This is the syntax Ruby uses to indicate that this argument (which must be the last) should be treated as the block for this method call.
In the above examples, my_block is a Proc instance, which is exactly what Ruby expects. So far, so good. However, what if you don’t pass it a Proc?
array.each(&"some string")
Aside from human confusion over exactly what is intended here, what will Ruby do? It will see that the object you’re saying to use as the block is not a Proc instance, and will try to convert it to one by calling the object’s to_proc method, if it exists.
I think that in the core language only Proc instances have this method (they return self), but Rails adds something:
# in active_support/core_ext/symbol.rb
class Symbol
# Turns the symbol into a simple proc, which is especially useful for enumerations. Examples:
#
# # The same as people.collect { |p| p.name }
# people.collect(&:name)
#
# # The same as people.select { |p| p.manager? }.collect { |p| p.salary }
# people.select(&:manager?).collect(&:salary)
def to_proc
Proc.new { |obj, *args| obj.send(self, *args) }
end
end
This to_proc method returns a Proc instance whose contained block takes a target object and any number of trailing arguments. So here’s what we get:
# these two are equivalent
:name.to_proc
Proc.new { |obj, *args| obj.name(*args) }
So we could do this:
block = :name.to_proc
array.map(&block)
However, as I said earlier, Ruby will call to_proc for us, so we can shorten it to this:
Remember that each, map, select, reject, etc. all only pass one argument: the item at the current point in the iteration. This means that in the block above args will be an empty array, so the block can usually be thought of as this:
Proc.new { |obj| obj.send(self) }
And remember that self here is the symbol itself.