Techioz Blog

Rails: オブジェクトの永続性を一時的に無効にする方法は?

概要

同様に、フリーズするとオブジェクトの値を更新する機能が (ある程度まで) 無効になります。直接呼び出し (User.save) と間接呼び出し (User.children << child) の両方で、そのオブジェクトおよび関連オブジェクトの作成/保存/更新の機能を無効にするメソッド User.disable_persistence を作成するにはどうすればよいでしょうか。

以下のような宝石、または簡単な方法はありますか?

class User < ...
  def disable_persistence
    # magic here (nullify save, and other methods, prevent callbacks etc.)
    class_eval :before_save do 
      errors.add(:base, "Persistence has been disabled for this object")
    end
  end
end

解決策

問題は簡単そうに思えます。ただし、注意が必要な部分は、間接的に (User.children << child) の部分です。 これは、親オブジェクト (User) が新しいレコードである場合に簡単に対処できます。しかし、そうでない場合はそう簡単にはいきません。 これは、user#children << child のようなステートメントは、ユーザーのレコードが新しいときに親レコードと子レコードを保存するためです。 ただし、そうでない場合は同じことは行いません。後者の場合、子供だけが保存されます。この問題は解決されていません このプロジェクトは、少なくとも今のところは自動的に行われます。開発者は最初に子オブジェクトの永続性を無効にする必要があります 後者のケースでこれを達成するためです。

author_spec.rb ファイルを参照してください。全体のストーリーを教えていただけると非常に助かります。

SOW の質問に答えるタスクとして私が開発したプロジェクト全体はここにあります: https://github.com/pmatsinopoulos/disable_persistence

それに貢献したい人は、自由にどうぞ。

読者の便宜のために、すべてのトリックを実行するコードをここでも引用します。

disable_persistence.rb ファイル:

module DisablePersistence
  extend ActiveSupport::Concern

  def disable_persistence
    @persistence_disabled = true
  end

  def enable_persistence
    @persistence_disabled = false
  end

  module ClassMethods
    def disable_persistence
      @@class_persistence_disabled = true
    end

    def enable_persistence
      @@class_persistence_disabled = false
    end

    def persistence_disabled?
      @@class_persistence_disabled ||= false
    end

    def persistence_disabled
      persistence_disabled?
    end
  end

  included do
    attr_reader :persistence_disabled
    alias :persistence_disabled? :persistence_disabled

    before_save :can_persist?

    after_initialize do |base|
      base.instance_variable_set(:@persistence_disabled, false)
    end

    def can_persist?
      !persistence_disabled? && !self.class.persistence_disabled?
    end

    protected :can_persist?
  end
end

ActiveRecord::Base.send :include, DisablePersistence

ノート:

A. インスタンスは以下に応答します。

B. クラスは次のことに応答します。

C. インスタンスが永続化できるかどうかをチェックする、保護された before_save メソッドがあります。インスタンスとクラスの両方の永続性が有効であることを確認します。いずれかが無効になっている場合、インスタンスを永続化できません。

D. この機能は、すべての ActiveRecord::Base クラスに自動的に組み込まれます。これは上の最後の行です。それは望まないかもしれません。それを望まない場合は、この機能を必要とするすべての ActiveRecord::Base クラスで include DisablePersistence を呼び出す必要があります。

E. リンク先の Rails プロジェクトには、このコードを含むファイルを必要とするイニシャライザーがあります。設定/イニシャライザを調べてください。それ以外の場合は、自分で要求する必要があります。

使用例のいくつか (著者とその書籍を想定):

最初の例:

author = Author.new
author.disable_persistence
author.save # will return false and nothing will be saved
author.enable_persistence
author.save # will return true and author will be saved

2 番目の例:

author = Author.new
author.disable_persistence
book = Book.new
author.books << book
author.save # false and nothing will be saved

3 番目の例:

author = Author.new
author.save
book = Book.new
book.disable_persistence
author.books << book # nothing will be saved

4 番目の例:

author = Author.new
author.save
book = Book.new
author.disable_persistence
author.books << book # will be saved indeed, because the book has enabled persistency

5 番目の例:

author = Author.new
Author.disable_persistence
author.save # will return false and will not save

上記があなたの質問の答えになるか、少なくとも何らかの形で役立つことを願っています。