web-dev-qa-db-ja.com

Rails 3検証とコールバックをスキップ

検証とコールバックが定義された特に複雑なモデルがあります。ビジネスニーズでは、新しいレコードを追加するときに検証とコールバックをスキップする必要がある特定のシナリオが必要になりました。これを行う最良の方法は何ですか?

70
Johnny Klassy

これはRails 3:

Model.skip_callback(:create)
model.save(:validate => false)
Model.set_callback(:create)

APIドキュメント および 関連する質問

118
Dinatih

ActiveRecord :: Persistence#update_column を次のように使用します。

Model.update_column(field, value)
29
bowsersenior

コールバックや検証なしで単純にレコードを挿入または更新することが目標であり、追加のGemに頼らず、条件付きチェックを追加したり、RAW SQLを使用したり、既存のコードを何らかの方法で変更したりせずにそれを実行したい場合は、既存のdbテーブルを指す「シャドウオブジェクト」を使用できます。そのようです:

class ImportedUser < ActiveRecord::Base
  # To import users with no validations or callbacks
  self.table_name = 'users'
end

これはRailsのすべてのバージョンで機能し、スレッドセーフであり、既存のコードを変更することなく、すべての検証とコールバックを完全に排除します。次のように、新しいクラスを使用してオブジェクトを挿入することを忘れないでください。

ImportedUser.new( person_attributes )
10
Brad Werth

私のテイクはこのようなものでした(注:これは、作成時、更新、削除、および配列に追加する必要があるその他のコールバックを無効にします)。

    begin
      [:create, :save].each{|a| self.class.skip_callback(a) } # We disable callbacks on save and create

      # create new record here without callbacks, tou can also disable validations with 
      # .save(:validate => false)
    ensure
      [:create, :save].each{|a| self.class.set_callback(a) }  # and we ensure that callbacks are restored
    end
2

スレッドセーフではないため、skip_callbackアプローチを使用しないことをお勧めします。 sneaky save gem は、SQLをそのまま実行するためです。これは検証をトリガーしないため、自分で呼び出す必要があります(例:my_model.valid?)。

ドキュメントのサンプルを次に示します。

# Update. Returns true on success, false otherwise.
existing_record.sneaky_save

# Insert. Returns true on success, false otherwise.
Model.new.sneaky_save

# Raise exception on failure.
record.sneaky_save!
1
Eric

検証をアドホックにスキップするための簡単なgemを作成しましたが、コールバックのスキップも含めるように更新される可能性があります。

https://github.com/npearson72/validation_skipper

can_skip_validation_forをgemに追加し、コールバックもスキップする機能を追加します。メソッドcan_skip_validation_and_callbacks_for

他のすべては同じように機能します。それを行うのに助けが必要な場合、私に知らせてください。

1
Nathan

コールバックをスキップできるメソッドをモデルに追加するのはどうですか?

class Foo < ActiveRecord::Base
  after_save :do_stuff

  def super_secret_create(attrs)
    self.skip_callback(:create)
    self.update_attributes(attrs)
    self.save(:validate => false)
    self.set_callback(:create)
  end
end

このようなものを使用することになった場合、名前の混乱を避けるために、モデル名の代わりにメソッドでselfを使用することをお勧めします。

私はまた、素敵に見えるスヴェン・フックスの要点に出くわしました、それは here

1
Caley Woods

このハックはついにうまくいきました(再定義された_notify_comment_observer_for_after_createオブジェクトのメソッド):

if no_after_create_callback
  def object._notify_comment_observer_for_after_create; nil; end
end
0
TuteC

検証がデータベース自体に書き込まれている場合、これらは機能しません。

+------------------------------------+--------------------------------------------------+------+-----+--------------------+----------------+
| Field                              | Type                                             | Null | Key | Default            | Extra          |
+------------------------------------+--------------------------------------------------+------+-----+--------------------+----------------+
| status                             | enum('Big','Small','Ugly','Stupid','Apologetic') | NO   |     | Stupid             |                |
0
Joshua Cook