user3149093
user3149093

Reputation: 21

Ruby - how to pass some context to a block that I'm wrapping with another block

I'm trying to pass some context (binding? To a block, since I'm wrapping a block into another. No idea how to do this.

Here is the code that demonstrates this. The problem happens at the wrap - when I don't wrap the proc gets the context as it should.

require 'sinatra'

class MyWebApp < Sinatra::Base

  @@help = {}
  def processing_policy(policytag)
    ## do special stuff here that might end in halt()
  end

  def self.api_endpoint(http_method, uri, policytag, helptext)
    @@helptext[uri] = { policy: policytag, help: helptext }

    if policytag.nil?
      ## It's an open endpoint. Create as-is. This part works
      send(http_method, uri, &block)
    else
      ## This is an endpoint with policy processing
      send(http_method, uri) do |*args|
        processing_policy(uri,policytag,request)
        # I probably need to do some kind of binding passthru for passed block
        # How do I do that???
        block.call(*args) # Block doesn't get context things like request etc
      end
    end
  end

  api_endpoint(:post, '/open_endpoint', nil, 'Some open endpoint') do
    "Anyone can view this - you posted #{request.body.read}"
  end

  api_endpoint(:post, '/close_endpoint', 'mypolicytag', 'Closed endpoint') do
    "This is closed = #{request.body.read}"
    # Doesn't work - block.call doesn't know about request since 
    # it doesn't have context
  end

  api_endpoint(:get, '/help', nil, "Help") do
    "Help:\n\n" + 
    @@help.map do |uri, data|
      "  #{uri} - policytag: #{data[:policy]} - #{data[:help]}\n"
    end.join()
  end
end

run MyWebApp

Any insights?

Upvotes: 0

Views: 265

Answers (1)

user3149093
user3149093

Reputation: 21

OK so I found the answer. Instead of block.call(*args) I can use instance_exec(*args, &block) and it works.

Upvotes: 2

Related Questions