2012-07-27 9 views
6

私は登録フォームを持っています。Rails 3:a​​fter_createのロールバック

ユーザーが登録すると、アプリケーションはenrollmentsテーブルとusersテーブルにデータを保存することになっています。 (ユーザーのプロフィールは変更できますが、特定の登録のために入力したデータはアーカイブする必要があるため、この分離が必要です。ユーザーが自分の姓を変更しても、登録フォームに私の初期情報があります)

だから私はこのように、after_createコールを持っていenrollmentsその後、テーブル内のデータを保存することを考えていた...

class Enrollment < ActiveRecord::Base 

    after_create :save_corresponding_user 

    def save_corresponding_user 
    user = User.new 
    user.full_name = self.user_full_name 
    user.email = self.user_email 
    user.mobile_phone = self.user_mobile_phone 
    user.save 
    end 
end 

問題は、ユーザーが何らかの理由で失敗したセーブ何であれば、です。 enrollmentsテーブルから保存したばかりのデータをロールバックして破壊するにはどうすればよいですか?

+0

をユーザーが複数回登録することができますか?もしそうでなければ、私は追加のフィールドをusersテーブルに直接追加します。 –

+0

実は、それは子供を託児所に入学させる親/保護者です。はい、親は子供を何度か登録することができます。 – leonel

+0

私には、after_createのsave_corresponding_userを置くのが問題になるようです。ユーザーが再び登録するとどうなりますか?新しいユーザーオブジェクトを作成する必要はありません。また、登録テーブルにおそらくuser_id列がありませんか?それは上記のあなたのコードには入れられません。私の場合は、エラーが発生した場合に両方のロールバックを処理するトランザクションで、登録とユーザーの作成をラップします。 –

答えて

12

after_createは、現在のモデルを保存するトランザクションの一部です。したがって、コードがクラッシュしたり、after_createがfalseを返した場合は、現在のトランザクションをロールバックして、enrollmentの保存を無効にする必要があります。

あなたは、これをシミュレートし、あなたのafter_createにこれを追加し、すべてが期待どおりに動作するかどうかを確認したい場合:

raise Exception.new("CRASH") 
+0

mongodbのような非トランザクションデータベースを使用している場合、ロールバックは発生しません –

+3

after_createがfalseを返す場合、トランザクションはロールバックされません(例外のみ)。少なくともRails 4では。 – djburdick

+0

@djburdickデフォルトでトランザクションは、例外が発生した場合にのみロールバックする必要があります。これは期待される動作です。私は、この答えがその細部に関して少し間違っていると思う。 – leishman

1

@anthonyalbertoが述べたように、after_createはすでにトランザクションの一部です。トランザクションを定義するには、あなたのコントローラ内でこのようなものを使用します。

ある
Enrollment.transaction do 
    @enrollment.save! 
end 

本当にあなたがする必要があるすべて、入学の保存失敗したり、ユーザーの保存、それはあなたのトランザクション全体をロールバックします失敗した場合。詳細はこちらhttp://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

7

falseからafter_createには何も行われません。

全体のコールバックチェーンがトランザクションでラップされます。 beforeコールバックメソッドが正確にfalseを返すか、例外を発生させると、実行チェーンは停止し、ROLLBACKが発行されます。コールバックが例外を発生させることによってのみそれを達成することができます。

また、あなたはraise ActiveRecord::Rollback次の条件を満たす必要があります。

コールバックチェーンが停止された後のActiveRecord ::ロールバックがレールによって再提起されていない任意の例外。 ActiveRecord :: Rollback以外の例外を発生させると、例外を発生させるsaveやupdate_attributes(通常はtrueまたはfalseを返そうとする)のようなメソッドは期待できません。

http://guides.rubyonrails.org/active_record_callbacks.html#halting-execution

私はこのような何か:Railsの3のために

after_create do 
    if condition 
    errors.add(:attr, 'Blah blah blah.') 
    raise ActiveRecord::Rollback 
    end 
end 

http://guides.rubyonrails.org/v3.2.13/active_record_validations_callbacks.html#halting-execution