2016-05-25 4 views
1

ユーザーモデルと会社モデルのデータを記録するサインアップフォーム用のサービスオブジェクトを作成しています(参考までに、nested_attributesの使用を拒否しました)。2つの異なるモデルインスタンスを1つのトランザクションとして保存するレール

ユーザーは会社(belongs_to)の存在なしでは存在できません。

IF会社が成功し、ユーザーが保存に成功しない場合、会社の作成を元に戻すにはどうすればよいですか?

私は現時点では私が持っているコードは、この

class SignUp 

    ...... 

    def save_resources 
    ActiveRecord::Base.transaction do 
     save_company 
     save_user 
    end 
    end 

    def save_company 
    company = new_company 
    self.company = company if company.save! 
    end 

    def save_user 
    user = new_user 
    self.user = user if user.save! 
    end 
end 

ようになり、私はActiveRecord::Base.transactionブロックではないと確信してポイントを証明するために、以下のコピーテスト..

context 'when both are valid?' do 
    subject { -> { sign_up_object.save } } 
    it { should change(Company, :count).by(1) } 
    it { should change(sign_up_object, :company).to be_a Company } 
    it { should change(User, :count).by(1) } 
    it { should change(sign_up_object, :user).to be_a User } 
    end 
    context 'when COMPANY is invalid' do 
    subject { -> { sign_up_object.save } } 
    before { allow_any_instance_of(Company).to receive(:save!).and_return false } 
    it { should change(User, :count).by(0) } 
    it { should change(Company, :count).by(0) } 
    end 
    context 'when USER is invalid' do 
    before { allow_any_instance_of(User).to receive(:save!).and_return false } 
    subject { -> { sign_up_object.save } } 
    it { should change(User, :count).by(0) } 
    it { should change(Company, :count).by(0) } ->>>> this one fails!!! 
    end 

を持っています実際に何かしているのは、私のテストでは、会社の数が1ずつ増えているので、失敗した唯一のものとしてユーザー仕様が示されているからです。

+0

あなたはエラーを発生させるためにビッグバン方式のバリエーションを使用する必要があります'user.save!'と 'company.save!' –

+0

私は悪いアップデートを持っています –

+0

@ j-dexxでも、同じテストでも失敗します。ユーザーがエラーをスローしている間も会社は作成されます。 –

答えて

1

であるユーザーが作成されていない場合は、手動でトランザクションをロールバックできます。

をあなたの例を取り上げ:

class SignUp 

    ...... 

    def save_resources 
    ActiveRecord::Base.transaction do 
     save_company 
     save_user 
     raise ActiveRecord::Rollback if self.user.nil? 
    end 
    end 

    def save_company 
    company = new_company 
    self.company = company if company.save! 
    end 

    def save_user 
    user = new_user 
    self.user = user if user.save! 
end 
end 
+0

あなたは精巧にできますか? –

+0

私の編集した回答を見て、それがあなたのために働くのか、それとももっと説明が必要なのかを教えてください –

0

ユーザー.SAVEがunsuccsessful

def save_resources  
    company = save_company 
    user = save_user 
    company.destroy if user.nil? 
end 
+0

これは、より良い言葉がほしいと思っているように思えます。あなたは同意しないでしょうか?確かに、イベント全体をアトミックにするよりエレガントな方法があります。 –

+0

@rico_macまったくありません。あなたは、エッジケースのアーキテクチャ全体を変更しようとしています。 'if'は0.1%の確率をカバーします。 –

関連する問題