From f37c90a8758d4dc007ad6a3428769651981ea4f4 Mon Sep 17 00:00:00 2001
From: Xavier Noria <fxn@hashref.com>
Date: Tue, 27 Oct 2009 00:11:22 +0100
Subject: AS guide: documents Proc#bind

---
 .../source/active_support_core_extensions.textile  | 42 +++++++++++++++++++++-
 1 file changed, 41 insertions(+), 1 deletion(-)

(limited to 'railties/guides/source/active_support_core_extensions.textile')

diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile
index 2df46a332f..147366c1a6 100644
--- a/railties/guides/source/active_support_core_extensions.textile
+++ b/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+
 
-- 
cgit v1.2.3

