如何通过ruby块传递数据?

如何通过ruby块传递数据?,ruby,block,webmock,Ruby,Block,Webmock,我试图将一些数据作为块传递给一些外部API。让它接受额外的参数将是一件麻烦的事。如果是javascript,我可能会这样做: var callback = function() { // do something } callback['__someData'] = options; someExternalAPI(callback); Ruby可以做到这一点吗?或者,我应该如何将一些数据与块关联起来 不确定对问题的编辑是否正确。首先,如果可能的话,我想特别传递一些数据和一个块。但我不

我试图将一些数据作为块传递给一些外部API。让它接受额外的参数将是一件麻烦的事。如果是javascript,我可能会这样做:

var callback = function() {
    // do something
}
callback['__someData'] = options;
someExternalAPI(callback);
Ruby可以做到这一点吗?或者,我应该如何将一些数据与块关联起来

不确定对问题的编辑是否正确。首先,如果可能的话,我想特别传递一些数据和一个块。但我不确定是不是。在ruby中实现这一点的唯一方法可能是将一些数据作为块传递

此外,可能还有一些有用的信息

好吧,展示整个画面可能是有道理的。我正在努力使webmock适应我的需要。我有一个函数,它检查请求的参数是POST参数还是GET参数与指定的条件匹配:

def check_params params, options
  options.all? do |k,v|
    return true unless k.is_a? String
    case v
    when Hash
      return false unless params[k]
      int_methods = ['<', '<=', '>', '>=']
      v1 = int_methods.include?(v.first[0]) ? params[k].to_i : params[k]
      v2 = int_methods.include?(v.first[0]) \
        ? v.first[1].to_i : v.first[1].to_s
      v1.send(v.first[0], v2)
    when TrueClass, FalseClass
      v ^ ! params.key?(k)
    else
      params[k] == v.to_s
    end
  end
end
通常情况下,我看不到有块条件输出的合理方法。但在我的特殊情况下,可以只输出选项散列。而不是这个:

registered request stubs:

stub_request(:post, "http://example.com")
要有这个:

stub_request(:post, "http://example.com").
  with(block: {"year"=>2015})

这就是我想做的。

好吧,我最后做了以下几点:

p = Proc.new {}
p.class.module_eval { attr_accessor :__options }
p.__options = {a: 1}                                                                                
# ...
pp p.__options
或者更具体地说:

def mk_block_cond options, &block_cond
  options = options.select { |k,v| ! k.is_a?(Symbol) }
  return block_cond if options.empty?
  block_cond.class.module_eval { attr_accessor :__options }
  block_cond.__options = options
  block_cond
end

module WebMock
  class RequestPattern
    attr_reader :with_block
  end
end

module StubRequestSnippetExtensions
  def to_s(with_response = true)
    request_pattern = @request_stub.request_pattern
    string = "stub_request(:#{request_pattern.method_pattern.to_s},"
    string << " \"#{request_pattern.uri_pattern.to_s}\")"

    with = ""

    if (request_pattern.body_pattern)
      with << ":body => #{request_pattern.body_pattern.to_s}"
    end

    if (request_pattern.headers_pattern)
      with << ",\n       " unless with.empty?

      with << ":headers => #{request_pattern.headers_pattern.to_s}"
    end

    if request_pattern.with_block \
    && request_pattern.with_block.respond_to?('__options') \
    && request_pattern.with_block.__options
      with << ",\n       " unless with.empty?

      with << "block: #{request_pattern.with_block.__options}"
    end

    string << ".\n  with(#{with})" unless with.empty?
    if with_response
      string << ".\n  to_return(:status => 200, :body => \"\", :headers => {})"
    end
    string
  end
end

module WebMock
  class StubRequestSnippet
    prepend StubRequestSnippetExtensions
  end
end

module RequestPatternExtensions
  def to_s
    string = "#{@method_pattern.to_s.upcase}"
    string << " #{@uri_pattern.to_s}"
    string << " with body #{@body_pattern.to_s}" if @body_pattern
    string << " with headers #{@headers_pattern.to_s}" if @headers_pattern
    if @with_block
      if @with_block.respond_to?('__options') \
      && @with_block.__options
        string << " with block: %s" % @with_block.__options.inspect
      else
        string << " with given block"
      end
    end
    string
  end
end

module WebMock
  class RequestPattern
    prepend RequestPatternExtensions
  end
end

另外

JavaScript示例中没有任何内容涉及到随回调一起传递数据。我不知道为什么它是相关的。事实上,我的措辞很糟糕,我更愿意将调用该块的参数存储在块本身中。UPD与否。lambda会做你想做的吗?在面向对象的语言中,将数据与函数相关联的方法是与对象相关联。@matt我的答案不是这样做的吗?我必须补充一点,我想做的是解决问题。
def mk_block_cond options, &block_cond
  options = options.select { |k,v| ! k.is_a?(Symbol) }
  return block_cond if options.empty?
  block_cond.class.module_eval { attr_accessor :__options }
  block_cond.__options = options
  block_cond
end

module WebMock
  class RequestPattern
    attr_reader :with_block
  end
end

module StubRequestSnippetExtensions
  def to_s(with_response = true)
    request_pattern = @request_stub.request_pattern
    string = "stub_request(:#{request_pattern.method_pattern.to_s},"
    string << " \"#{request_pattern.uri_pattern.to_s}\")"

    with = ""

    if (request_pattern.body_pattern)
      with << ":body => #{request_pattern.body_pattern.to_s}"
    end

    if (request_pattern.headers_pattern)
      with << ",\n       " unless with.empty?

      with << ":headers => #{request_pattern.headers_pattern.to_s}"
    end

    if request_pattern.with_block \
    && request_pattern.with_block.respond_to?('__options') \
    && request_pattern.with_block.__options
      with << ",\n       " unless with.empty?

      with << "block: #{request_pattern.with_block.__options}"
    end

    string << ".\n  with(#{with})" unless with.empty?
    if with_response
      string << ".\n  to_return(:status => 200, :body => \"\", :headers => {})"
    end
    string
  end
end

module WebMock
  class StubRequestSnippet
    prepend StubRequestSnippetExtensions
  end
end

module RequestPatternExtensions
  def to_s
    string = "#{@method_pattern.to_s.upcase}"
    string << " #{@uri_pattern.to_s}"
    string << " with body #{@body_pattern.to_s}" if @body_pattern
    string << " with headers #{@headers_pattern.to_s}" if @headers_pattern
    if @with_block
      if @with_block.respond_to?('__options') \
      && @with_block.__options
        string << " with block: %s" % @with_block.__options.inspect
      else
        string << " with given block"
      end
    end
    string
  end
end

module WebMock
  class RequestPattern
    prepend RequestPatternExtensions
  end
end
stub_request(:post, 'http://example.com/')
  .with &mk_block_cond(options) { |request|
    check_params Rack::Utils.parse_query(request.body), options
  }