AJcodez
AJcodez

Reputation: 34186

call a proc in the context of the surrounding block

I have an array of Procs, and I want to call all of them in the context of the enclosing block, and return the last value. Specifically:

require 'sinatra/base'

class App < Sinatra::Base
end

procs = [ proc{ status 200 }, proc{ 'Success!' } ]
App.send('get', '/') do
  procs.map(&:call).last
end

App.run!

It errors with No method 'status'. I expected it to behave like:

class App < Sinatra::Base
  get '/' do
    status 200
    'Success!'
  end
end

Any idea how I might do that?

Upvotes: 0

Views: 237

Answers (2)

Patrick Oscity
Patrick Oscity

Reputation: 54684

You can use instance_eval to change the binding of the procs:

App.send('get', '/') do
  procs.map{|p| instance_eval(&p) }.last
end

Upvotes: 3

mlibby
mlibby

Reputation: 6734

You are setting procs outside the scope of App, which is where the status method is defined. So you're not getting the binding you expect. Move the definition into the class and switching to lambdas works for me. Lambdas are true closures, so this makes sense.

Consider

  class App < Sinatra::Base
    procs = [ -> { status 200 }, -> { 'Success!' } ]

    get '/' do
      procs.map(&:call).last
    end
  end

Upvotes: 0

Related Questions