title: Dynamically replace method implementation on an object in Ruby
body: <p>I'd like to replace the implementation of a method for an object with a block that the user specifies. In JavaScript, this is easily accomplished:</p>
  
  <pre><code>function Foo() {
      this.bar = function(x) { console.log(x) }
  }
  foo = new Foo()
  foo.bar("baz")
  foo.bar = function(x) { console.error(x) }
  foo.bar("baz")
  </code></pre>
  
  <p>In C# it is also quite easy</p>
  
  <pre><code>class Foo
  {
      public Action&lt;string&gt; Bar { get; set; }
      public Foo()
      {
          Bar = x =&gt; Console.WriteLine(x);
      }
  }
  
  var foo = Foo.new();
  foo.Bar("baz");
  foo.Bar = x =&gt; Console.Error.WriteLine(x);
  foo.Bar("baz");
  </code></pre>
  
  <p>But how can I do the same in Ruby? I have a solution that stores a lambda in an instance variable and the method calls the lambda, but I don't really like the overhead and syntax</p>
  
  <pre><code>class Foo
    def initialize
      @bar = lambda {|x| puts x}
    end
  
    def bar x
      @bar.call x
    end
  
    def bar= blk
      @bar = blk
    end
  end
  
  foo = Foo.new
  foo.bar "baz"
  foo.bar= lambda {|x| puts "*" + x.to_s}
  foo.bar "baz"
  </code></pre>
  
  <p>I'd like to have a syntax like that:</p>
  
  <pre><code>foo.bar do |x|
      puts "*" + x.to_s
  end
  foo.bar "baz"
  </code></pre>
  
  <p>I came up with the following code</p>
  
  <pre><code>class Foo
    def bar x = nil, &amp;blk
      if (block_given?)
        @bar = blk
      elsif (@bar.nil?)
        puts x
      else
        @bar.call x
      end
    end
  end
  </code></pre>
  
  <p>But this is kinda ugly for more than one parameter and still doesn't feel 'right'. I could also define a set_bar method, but i don't like that either :).</p>
  
  <pre><code>class Foo
    def bar x
      if (@bar.nil?)
        puts x
      else
        @bar.call x
      end
    end
  
    def set_bar &amp;blk
      @bar = blk
    end
  end
  </code></pre>
  
  <p>So question is: Is there a better way do to do this and if not, what way would you prefer</p>
  
  <p>Edit:
  @welldan97's approach works, but i loose the local variable scope, i.e.</p>
  
  <pre><code>prefix = "*"
  def foo.bar x
      puts prefix + x.to_s
  end
  </code></pre>
  
  <p>doesn't work. I suppose I have to stick with lambda for that to work?</p>