如何在事务中进行DataMapper回调?

时间:2012-11-08 17:49:51

标签: ruby transactions callback datamapper

我希望能够在DataMapper中定义一个回调,并在事务中发生这种情况以及随附的更新。例如:

class Comment
  include DataMapper::Resource

  has n, :updates

  property :id,   Serial
  property :text, String

  after :update do
    self.updates.create(:text => self.text)
  end
end

我认为很清楚以上代码尝试做什么:每当Comment更新时,也会创建相应的Update记录。现在,可能的情况是您可以更新帖子,创建更新将失败 - 无论出于何种原因 - 因此某些历史记录将丢失。所以我真的希望在事务中发生这种操作。

这可能吗?我可以想到一些解决方法(例如,定义自定义update方法);但我很想知道是否有“正确”的方式,或者其他人是否可以想到优雅的方法。

1 个答案:

答案 0 :(得分:7)

要使用可测试和可扩展的设计对其进行归档,我建议使用如下服务对象:

class CommentUpdate

  private_class_method :new

  # Run comment update within transaction
  def self.run(*args)
    Comment.transaction do
      new(*args)
    end
  end

  # Initialize object
  #
  # @param [Comment]
  #   the comment to update
  # @param [String]
  #   the text to set
  # 
  def initialize(comment, text)
    @comment, @text = comment, text
    run
  end

  # Test if update was successful
  def successful?
    @comment.saved?
  end

private

  # Run update
  def run
    @comment.text = @text
    if @comment.save
      @comment.updates.create(:text => @text)
    end
  end
end

# usage
comment = Comment.first
update = CommentUpdate.run(comment, "Some new cool text")
update.successful? # Use this to steer your control flow...