2017-11-27 4 views
-1

複数のレコードを同時にレールに追加したい。複数のレコードをレールに保存し、失敗した場合は元に戻す

tax_rates.map {|tax_rate| TaxRate.new(tax_rate).save } 

しかし、これによっては一部のレコードが保存され、一部は拒否される可能性があります。

レコードの一部が失敗した場合、すべてのレコードを拒否する方法を誰に教えてもらえますか?

ありがとうございます。

+0

[ o ask "](https://stackoverflow.com/help/how-to-ask)をクリックしてください。 – mudasobwa

答えて

3

私はこのような何かをするだろう:

TaxRate.transaction do 
    tax_rates.map do |tax_rate| 
    raise ActiveRecord::Rollback unless TaxRate.new(tax_rate).save 
    end 
end 

またはあなたのモデルに新しいメソッドを追加したい場合があります読みやすさの理由のために:

# in models/tax_rate.rb 
def self.create_all(rates) 
    transaction do 
    rates.map do |rate| 
     raise ActiveRecord::Rollback unless TaxRate.new(rate).save 
    end 
    end 
end 

そして、あなたのコントローラで使用このように:

TaxRate.create_all(tax_rates) 
+0

また、単に 'create!'や 'save!'を使ってください。 –

+0

コントローラでトランザクションを使用できますか? – Avinash142857

+0

@ Avinash142857はい。 – jemonsanto

2

トランザクションを使用します。

ActiveRecord::Base.transaction do 
    model1.create! 
    model2.create! 
    model3.create! 
    anything that triggers an exception 
    or raise ActiveRecord::Rollback 
end 

[1] pry(main)> ActiveRecord::Base.transaction do [1] pry(main)* User.create(email: "[email protected]", password: "asdkfasdlfk") [1] pry(main)* Network.create(user_id: 1) [1] pry(main)* end
(22.9ms) SET NAMES utf8, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483 (6.4ms) BEGIN User Exists (24.3ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = BINARY '[email protected]' LIMIT 1 (0.2ms) ROLLBACK ActiveModel::UnknownAttributeError: unknown attribute 'user_id' for Network.

トランザクションはロールバックを経由して、レコードの状態をリセットします。 Railsでは、ロールバックは例外によってのみトリガされます。 したがって、使用しているメソッドがをトリガーしていることを確認してください。 http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

EDIT:それは黙ってDBには何もコミットしていないことを証明するために、コードを追加し、いくつかのAR法は、このに関する詳細情報については、障害例えばupdate_attribute

上の例外をトリガしません。

+0

問題は、特定の例が例外を発生させ、トランザクション全体を必要に応じて取り消しますが、トランザクションのブロックが例外を発生しない場合、ロールバックは発生しません。したがって、検証のために 'create'呼び出しの1つが失敗した場合、その失敗は暗黙のうちに無視されます。代わりに 'create!'を使用した場合、検証の問題から例外が発生し、トランザクションは必要に応じて機能します。データベースエラー(検証ではカバーしていないテーブル制約に違反するなど)によって例外が発生し、トランザクションは必要に応じて機能します。 –

+1

@muistooshortトランザクションをロールバックするには、常にActiveRecord :: Rollbackを呼び出す機会があります。 – mudasobwa

関連する問題