Почему yield не передает результат в block (Rails)? - PullRequest
1 голос
/ 17 мая 2019

Я знаю, что есть несколько вопросов SO, а также онлайн-статьи по использованию yield в Rails.Но мне все еще трудно понять, что не так с моим кодом ниже, и буду признателен за любые советы.

В моем приложении у меня есть:

  • A controllerкоторый передает данные в метод run класса command и возвращает статус запроса на основе результата Command.run (true / false)

  • Acommand класс, который имеет дело с фактическим содержанием процесса, затем 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 it,Но здесь я хотел бы знать, как заставить yield работать.

Ответы [ 2 ]

2 голосов
/ 17 мая 2019

В вашем контроллере вам нужна переменная для результата.

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

(EDIT)

Кроме того, вы вызываете метод класса, который вызывает метод экземпляра.Вы должны передать блок из вызывающего кода в вызываемый вами метод экземпляра.

def self.run(params, &block)
  new.run(params, &block)
end
1 голос
/ 17 мая 2019

РЕДАКТИРОВАТЬ: ах, так что у вас есть метод класса run и метод экземпляра run.

  1. Либо сделайте, как предложил Марлин, и передайте блок явно из метода класса вметод экземпляра.

  2. Или используйте только метод класса, как я и предлагал изначально (не похоже, что есть причина для создания экземпляра Command в вашем случае):

    def self.run(params, &block)
      result = send_http_request.parsed_response == 'ok'
      block.yield(result)
    end
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...