获取Rails ActiveJob结果以在控制器中作为JSON返回的最佳方法?

时间:2018-08-26 18:20:01

标签: ruby-on-rails json api rails-activejob

我正在构建一个接受字符串,解析它并将其返回为JSON的Web服务。在我的控制器中,我正在调用ActiveJob来运行服务以解析数据。我想将ActiveJob的结果返回给我的控制器,以便以JSON的形式返回它,但我不确定该怎么做。最简单的方法是什么?

class GeocoderService
  require 'ruby_postal/parser'

  def initialize(address)
    @address = address
  end

  def parse_address
    address_group = {}
    result = Postal::Parser.parse_address(@address)
    result.each do |r|
      address_group[r.values[0]] = r.values[1]
    end
    address_group
  end

class ParseAddressJob < ApplicationJob
  queue_as :default

  def perform(address)
    geo = GeocoderService.new(address)
    result = geo.parse_address
  end

end

class LocationsController < ApplicationController



def create
    if geo_params[:address]
      ParseAddressJob.perform_later(geo_params[:address])
      render json: result
    else
      render json: { error: "Invalid address"}, status: 400
    end
  end

  private

  def geo_params
    params.require(:geo).permit(:address)
  end
end

1 个答案:

答案 0 :(得分:3)

ActiveJob用于创建在后台运行的任务,并与HTTP请求/响应流异步运行。控制器将任务移交给ActiveJob,然后控制器在将来运行作业时返回。如果您因为某个用户需要的东西而立即需要该作业的输出,那么您不应该使用该作业-您应该直接调用该作业直接调用的代码,并阻塞直到该代码完成为止,这样您才能获得输出。

def create
  if geo_params[:address]
    geo = GeocoderService.new(geo_params[:address])
    result = geo.parse_address
    render json: result
  else
    render json: { error: "Invalid address"}, status: 400
  end
end

如果您确实担心在等待地理位置API的响应时控制器操作将执行的阻止操作,则可以为API使用者建立自己的排队系统。流程看起来像这样:

  1. 用户向您的端点发出请求
  2. 您的端点将一条记录插入到名为GeoResults的数据库表中,状态为“处理中”,并且响应文本为空。获取此记录的ID。
  3. 您的端点会像现在一样触发工作,但是现在您还需要传入创建的GeoResults记录的ID。
  4. 您的端点为用户提供了一个URL,以检查GeoResults中的此记录。
  5. 您的消费者开始轮询此端点,直到他们看到“完成”状态
  6. 后台作业完成后,它将更新其在GeoResults中的记录(因为它具有ID),状态为“完成”,并分配地理位置响应文本。
  7. 您的消费者看到更新,并获取响应。