I’m in love with :symbol.to_proc

Posted by unixmonkey on August 06, 2010

I’ve been crawling over this Rails project and lately finding lots of places where clarity could be increased by using symbol_to_proc, so I thought I would share it a bit for those not in the know on this handy ruby shortcut.

Rails added symbol_to_proc shorthand in version 1.1, and it is such a nice shortcut, that it became part of the Ruby language in version 1.8.7

So, anywhere you would normally use an iterator with a block like so:

people.collect { |p| p.name }

could be shortened to call like:

people.collect(&:name)

The difference may not look so dramatic in the above example, but how about this one:

   # classic
   prison.inmates.select{ |i| i.repeat_offender? }.select{ |i| i.offsenses }.collect{ |o| o.prosecution_fees }.sum

   # to_proc
   prison.inmates.select(&:repeat_offender?).select(&:offenses).collect(&:prosecution_fees).sum

Some people, including Rails core member pratik (http://m.onkey.org/2007/6/30/let-s-start-with-wtf)
Have criticized and advised against using this shortcut because it is roughly 4 times slower than doing without its syntax sugar.

Now, I would rather have a beautiful, understandable code base than a particularly fast one (after all, I *am* using Ruby), but the reason for the slowness is largely because of the implementation as shown below:

  class Symbol
    def to_proc
      Proc.new { |*args| args.shift.__send__(self, *args)
    end
  end

This implementation looks for arguments passed in and shifts self off of them before calling.
This allows for calling a method with arguments like so:

[1,2,3].inject(&:+)

I believe this represents a real edge case at the expense of a lot of speed, and Luke Redpath (http://lukeredpath.co.uk/blog/optimising-symbol-to_proc.html) has a lot of good to say about the topic, and even goes as far to present a patch for how this should be implemented for pure speed:

  class Symbol
  def to_proc
    @to_proc_proc ||= Proc.new { |obj| obj.__send__(self) }
  end
end

I’ve patched this in to my Rails project and not a single one of my tests failed, your mileage may vary, but even without the speed boost, I’ll continue to use :symbol.to_proc because I love it so.

Rails respond_to rendering wrong format in IE 2

Posted by unixmonkey on August 02, 2010

I ran into an interesting issue today where a client viewing my Rails site would go to a link; and instead of seeing the html view rendered, it was skipping right to an alternate format in the respond_to block.

Clicking a link going to /orders, was instead taking them to /orders.xls, which I have in a respond_to block like so:

  def orders
    @orders = Order.all
    respond_to do |format|
      format.html # new.html.erb
      format.xls   # new.xls.erb
    end
  end

The client in question was using Internet Explorer. This provided a major clue.
It turns out that IE will send an HTTP_ACCEPT header listing all the stuff it can accept in the browser, and thus, because it can accept .xls files, it requests that format.

I’m experiencing this in a Rails 2.3.8 app, but documentation at railsguides.info states this behavior was changed in Rails 2.2. Perhaps an older plugin is switching it back on, I’ll have to investigate.

In any case, adding this line to application.rb solves the problem:

config.action_controller.use_accept_header = false

This causes it to behave as expected, where it uses the file extension alone to determine the format when there is a question which format to use.