Permalink
Browse files

AS guide: documents Proc#bind

  • Loading branch information...
1 parent d226287 commit f37c90a8758d4dc007ad6a3428769651981ea4f4 @fxn fxn committed Oct 26, 2009
Showing with 41 additions and 1 deletion.
  1. +41 −1 railties/guides/source/active_support_core_extensions.textile
@@ -1680,7 +1680,47 @@ The method +Range#overlaps?+ says whether any two given ranges have non-void int
h3. Extensions to +Proc+
-...
+h4. +bind+
+
+As you surely know Ruby has an +UnboundMethod+ class whose instances are methods that belong to the limbo of methods without a self. The method +Module#instance_method+ returns an unbound method for example:
+
+<ruby>
+Hash.instance_method(:delete) # => #<UnboundMethod: Hash#delete>
+</ruby>
+
+An unbound method is not callable as is, you need to bind it first to an object with +bind+:
+
+<ruby>
+clear = Hash.instance_method(:clear)
+clear.bind({:a => 1}).call # => {}
+</ruby>
+
+Active Support defines +Proc#bind+ with an analogous purpose:
+
+<ruby>
+Proc.new { size }.bind([]).call # => 0
+</ruby>
+
+As you see that's callable and bound to the argument, the return value is indeed a +Method+.
+
+NOTE: To do so +Proc#bind+ actually creates a method under the hood. If you ever see a method with a weird name like +__bind_1256598120_237302+ in a stack trace you know now where it comes from.
+
+Action Pack uses this trick in +rescue_from+ for example, which accepts the name of a method and also a proc as callbacks for a given rescued exception. It has to call them in either case, so a bound method is returned by +handler_for_rescue+, thus simplifying the code in the caller:
+
+<ruby>
+def handler_for_rescue(exception)
+ _, rescuer = Array(rescue_handlers).reverse.detect do |klass_name, handler|
+ ...
+ end
+
+ case rescuer
+ when Symbol
+ method(rescuer)
+ when Proc
+ rescuer.bind(self)
+ end
+end
+</ruby>
h3. Extensions to +Date+

0 comments on commit f37c90a

Please sign in to comment.