1

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

上記のコードが何をしようとしているのかは明らかだと思います: aCommentが更新されるたびに、対応するUpdateレコードも作成します。ここで考えられるシナリオは、投稿を更新することができ、何らかの理由で更新の作成が失敗し、一部の履歴が失われるというものです。したがって、この種の操作がトランザクション内で発生することを本当に望んでいます。

これは可能ですか?updateいくつかの回避策を思いつくことができます (たとえば、カスタムメソッドを定義するなど)。しかし、「正しい」方法があるかどうか、または他の人がエレガントなアプローチを考えられるかどうかを知りたいです。

4

1 に答える 1

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...
于 2012-11-18T21:49:09.070 に答える