0

我有一个Composition模型,它有一个has_and_belongs_to_many :authors.

我需要在组合更改其作者后触发一个方法,但是,由于它涉及创建 PDF 文件(使用作者的姓名),我只想调用此方法一次,而不管添加的作者数量/删除。

当然,我可以从作品中添加/删除现有作者,因此before_save/after_save在这里不起作用(它以某种方式识别添加到作品中的新作者,但不是现有作者)。

所以我尝试使用after_add/ after_remove,但这里指定的回调将为添加到组合中/从组合中删除的每个作者项目调用。

有没有一种方法可以让每个从这种关系中添加/删除项目的“批处理操作”只调用一次方法?

4

1 回答 1

0

以下是服务的外观

class UpdateCompositionAuthorsService

  attr_accessor *%w(
    args
  ).freeze

  class << self 

    def call(args={})
      new(args).call
    end

  end # Class Methods

  #======================================================================================
  # Instance Methods
  #======================================================================================

    def initialize(args={})
      @args = args
      assign_args
    end

    def call
      do_stuff_to_update_authors
      generate_the_pdf
    end

  private

    def do_stuff_to_update_authors
      # do your 'batch' stuff here
    end

    def generate_the_pdf
      # do your one-time logic here
    end

    def assign_args
      args.each do |k,v| 
        class_eval do 
          attr_accessor k
        end
        send("#{k}=",v)
      end
    end

end

你可以这样称呼它:

UpdateCompositionAuthorsService.call(composition: @composition, authors: @authors)

我厌倦了记住要发送给我的服务类的参数,所以我创建了一个名为ActsAs::CallingServices. 当包含在一个class想要调用服务的模块中时,该模块提供了一个调用的方法call_service,让我可以执行以下操作:

class FooClass
  include ActsAs::CallingServices

  def bar
    call_service UpdateCompositionAuthorsService
  end

end

然后,在服务类中,我包含一些额外的类级数据,如下所示:

class UpdateCompositionAuthorsService

  SERVICE_DETAILS = [
    :composition,
    :authors
  ].freeze

    ...

    def call
      do_stuff_to_update_authors
      generate_the_pdf
    end

    ...

end

调用类(FooClass在本例中为 )用于UpdateCompositionAuthorsService::SERVICE_DETAILS构建适当的参数散列(省略详细信息)。

我的服务类中还有一个名为good_to_go?(省略详细信息)的方法,因此我的调用方法通常如下所示:

class UpdateCompositionAuthorsService

    ...

    def call
      raise unless good_to_go?
      do_stuff_to_update_authors
      generate_the_pdf
    end

    ...

end

因此,如果参数集不好,我会立即知道,而不是nil在我的服务中间的某个地方遇到错误。

于 2018-04-19T01:47:12.867 回答