为什么 yield 不将结果传递给块 (Rails)?

Why is yield not passing the result to block (Rails)?

我知道有几个 SO 问题以及关于在 Rails 中使用 yield 的在线文章。但是我仍然无法理解我下面的代码有什么问题,如果有任何建议,我将不胜感激。

在我的应用程序中,我有:

不过,command class 似乎没能 yield 结果到我的 controller。根据我 运行 测试时的错误消息,我在 controller 中的块似乎没有被识别为块:

# If I use "yield result": 
LocalJumpError: no block given (yield)

# If I use "yield result if block_given?":
# (This is because I have "assert_response :success" in my tests)
Expected response to be a <2XX: success>, but was a <400: Bad Request>

我应该如何重写块(下面控制器中的 do ... end 部分)以便 yield 正常工作?或者,如果问题出在其他地方,我做错了什么?

我在下面提供了我的代码的简化版本。提前致谢!

# controller

def create
  Command.run(params) do
    render json: { message: 'Successfully processed request' }
    return
  end
  render json: { message: 'Encountered an error' }, status: :bad_request
end
# command class

def run(params)
  # Do some stuff, then send HTTP request
  # "result" below returns true or false
  result = send_http_request.parsed_response == 'ok'
  yield result
end

def self.run(params)
  new.run(params)
end

注意:如果我在控制器中使用 if true... else... 而不是块,并且只是 return 布尔结果而不是 yielding,则此代码有效。但在这里我想知道如何使 yield 工作。

在您的控制器中,您需要为结果设置一个变量。

def create
  Command.run(params) do |result|
    if result
        render json: { message: 'Successfully processed request' }, status: :success
    else
        render json: { message: 'Encountered an error' }, status: :bad_request
    end
    return
  end
  render json: { message: 'Encountered an error' }, status: :bad_request
end

(编辑)

此外,您正在调用调用实例方法的 class 方法。您必须将块从调用代码传递到您正在调用的实例方法。

def self.run(params, &block)
  new.run(params, &block)
end

编辑:啊,所以你有一个 class 方法 run 和实例方法 run.

  1. 要么按照 Marlin 的建议进行操作,要么显式地将块从 class 方法提供给实例方法。

  2. 或者只使用我最初建议的 class 方法(它不 在你的情况下似乎有任何理由实例化 Command):

    def self.run(params, &block)
      result = send_http_request.parsed_response == 'ok'
      block.yield(result)
    end