【问题标题】:Calling the service class from the active job class in rails从 rails 中的活动作业类调用服务类
【发布时间】:2020-06-29 10:05:48
【问题描述】:

我有我的 rails 控制器类,它调用我的活动作业类

class Api::V2::Events::WegSessionsController < Api::V2::Events::ApplicationController
before_action :load_service

.... some code

def synchronize
@service.keep_cancelled = params[:keep_cancelled].to_b
if @service.valid_connection?

  WegJob.perform_later

  render json: {
    status: :ok,
    message: @service.message
  }, status: :ok
else
  render json: {
    status: :unprocessable_entity,
    errors: @event.errors.full_messages
  }, status: :ok
end
end

... some code

def load_service
  @service = WegService.new(event: @event)
end
end

我已在 Rails 项目中配置我的作业类以使用 Sidekiq 并在此处调用服务方法

class WegJob < ApplicationJob
queue_as :default

def perform(*args)
 WegService.synchronize
end
end

这个服务类实现了我将从我的工作类调用的“同步”方法

class WegService
 include ActiveModel::Model

... some code

def synchronize
 if event.weg_synced_at.present?
  update
 else
  create
 end

 event.update(weg_synced_at: Time.current)
end

... some code along with update and create method implementations.
end

当我这样做时,我收到以下错误

[ActiveJob] [WegJob] [fd7c1869-6909-471c-bf32-9b2270a8c39c] Error performing 
WegJob (Job ID: fd7c1869-6909-471c-bf32-9b2270a8c39c) from Async(default) in 
2556.3ms: NoMethodError (undefined method `synchronize' for WegService:Class):

我知道我从 Job 类调用服务方法的方式是错误的。我哪里可能出错了?

【问题讨论】:

    标签: ruby-on-rails background-process jobs sidekiq


    【解决方案1】:

    您正在 WegService 中定义一个实例方法:

    class WegService
     include ActiveModel::Model
    
    ... some code
    
    def synchronize
     if event.weg_synced_at.present?
      update
     else
      create
     end
    
     event.update(weg_synced_at: Time.current)
    end
    
    ... some code along with update and create method implementations.
    end
    

    然而你却把它当作一个类方法来调用:

    class WegJob < ApplicationJob
      queue_as :default
    
      def perform(*args)
        WegService.synchronize
      end
    end
    

    当然不行。要么将方法重新定义为类方法,要么创建工厂方法:

    class WegService
      include ActiveModel::Model
    
      #.. some code
    
      def synchronize
        if event.weg_synced_at.present?
          update
        else
          create
        end
    
        event.update(weg_synced_at: Time.current)
      end
    
      def self.syncronize
        WegService.new.synchronize
      end
      # ... some code along with update and create method implementations.
    end
    

    但它对于服务对象的设计非常有问题。这个名字很模糊,服务对象真的应该只有一个调用方法。 include ActiveModel::Model 还告诉我,你创造的其实只是一个模型。

    【讨论】:

    • 有没有办法可以将我的服务类的对象实例(@service)从控制器传递到我的作业类,以便我仍然可以将“同步”方法作为实例方法调用?
    猜你喜欢
    • 2014-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-03
    • 2021-09-09
    • 1970-01-01
    相关资源
    最近更新 更多