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

时间:2019-05-17 08:19:34

标签: ruby-on-rails ruby yield

我知道有几个SO问题以及有关在Rails中使用yield的在线文章。但是我仍然无法理解下面的代码出了什么问题,请多多指教。

在我的应用中,我有:

  • 一个controller,它将数据传递到command类的run方法,并根据Command.run的结果返回请求状态({{1 }} / true

  • 处理流程实际内容的false类,如果处理成功,则处理command yields,如果处理失败,则处理true

但是,false类似乎无法将结果command传递给我的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工作。

2 个答案:

答案 0 :(得分:2)

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

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

(编辑)

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

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

答案 1 :(得分:1)

编辑:啊,所以您有一个类方法run和实例方法run

  1. 按照Marlin的建议进行操作,并从类方法向实例方法显式提供该块。

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

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