TL; DR:AR :: Baseセーブトランザクション内に重複するジョインテーブルレコードを挿入すると、(ユニークな制約のため)セーブおよびロールバックの原因となります。重複する結合テーブルレコードを追加しないでください。保存していないと悪いです。postgresデータベースエラーがトランザクションの再開を強制する
私はDBへの参加・テーブルをレコードを追加するのmysql-土地で、このようなパターンの何かを追跡するために使用...のpostgresにmysqlのアプリを移行しています:
呼び出さclass EventsSeries < ActiveRecord::Base
# UNIQUE KEY `index_events_series_on_event_id_and_series_id` (`event_id`,`series_id`)
belongs_to :event
belongs_to :series
end
class Series < ActiveRecord::Base
has_many :events_series
before_validation :add_new_event
private
def add_new_event
# boils down to something like this
EventSeries.new.tap do |es|
es.event_id = 1
es.series_id = 1
begin
es.save!
rescue ActiveRecord::RecordNotUnique
# Great it exists
# this isn't really a problem
# please move on
end
end
end
end
このように:
Series.first.save
# should not blow up on duplicate join record, cause i don't care
しかし、これでポストグレスが爆発します。ここで良い説明があります:
http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html
...「例外処理とロールバック」のセクションを中(警告を参照)
は基本的に#saveは、トランザクションを開始し、重複したレコードの挿入原因データベース例外。これは#saveのトランザクションを無効にします。これはsadfaceです。
これはポストグルーランドで使用できるより良いパターンがありますか?
ありがとうございます!
編集:
私はしっかりと取引を保存する、それはシリーズ内でこのロジックを保つために理にかなっていると信じて...パターンは次のようになります。
s = Series.new
s.new_event_id = 123 # this is just an attr_accessor
s.save # callbacks on Series know how to add the new event.
...それは私を作りますコントローラは超小型です。
SELECT ...のために、共有が心に浮かび、それがすでにあるかどうかを確認します。重複している可能性のあるデータに対して行ったことは、各INSERTを個別のトランザクションにすることだけでした。 – freeone3000
そうですが、すべてのロジックがセーブコールの内側にうまく包まれない – jsharpe
ActiveRecordは、savepointsのようなPostgreSQLのサブトランザクションにアクセスする方法を教えてくれますか? plpgsqlのhttp://www.postgresql.org/docs/current/interactive/sql-savepoint.html ...またはEXCEPTION節? http://www.postgresql.org/docs/current/interactive/plpgsql-control-structures.html#PLPGSQL-ERROR-TRAPPING – kgrittn