ActiveRecord::Baseを拡張するいくつかのモデルクラスを持つRailsアプリに取り組んでいます。データベースの内容を更新するために使用できるこれらのモデルクラスのいくつかにさまざまなメソッドを実装しましたが、これらのメソッドはすべて、希望どおりに機能しています。たとえば、TeamStats
さまざまな統計値をデータベースに格納するクラスがあり、ゲームの結果を適用してこれらの属性を更新できるメソッドを定義しました。
class TeamStats < ActiveRecord::Base
belongs_to :team
def << game_result
# Lots of stuff here to update persisted attributes for
# wins, losses, total points scored, etc
end
end
class Team < ActiveRecord::Base
has_one :stats, :class_name => TeamStats, :dependent => destroy
end
今、私はそのロジックを再利用したいと思っていますが、データベースにコミットしたくない一時的なデータがいくつかあります。たとえば、ゲームのすべてではなくサブセットを使用して、チームの統計を再計算したいと思います。だから私はこのようなことをするコードを持っています:
# relevant_game_results is an array containing game results I want considered
teams.each do |team|
new_stats = TeamStats.new(:team => team)
relevent_game_results.each do |results|
new_stats << results
end
end
# Do stuff to choose a team based on these un-persisted stats that have been
# assigned to the team
# After I'm done, through all the team_stats I created and make sure all of the
# related team model objects still reference their original team stats values
これに対する私の最初の計画は、モデルインスタンスを変更し、reload
完了したらそれらのインスタンスを呼び出すことでした。例えば:
teams.each do |team|
team.reload
end
それでうまくいくと思いますが、たくさんのオブジェクトに対してやらなければならないので、できれば1回の操作でやりたいと思います。
私が本当に必要としているのは、コミットされるのではなく、常にロールバックされるトランザクションのようです。これを行うための最も適切な「レールの方法」は何ですか?ブロック内でこれを行い、transaction
ブロックの最後でを上げることになっていActiveRecord::Rollback
ますか?言い換えれば、このようなものですか?
Team.transaction do
teams.each do |team|
new_stats = TeamStats.new(:team => team)
relevent_game_results.each do |results|
new_stats << results
end
end
# Do stuff to choose a team based on these un-persisted stats that have been
# assigned to the team
raise ActiveRecord::Rollback
end
それは私には少し「汚い」ように思えますが、それは私のJavaのバックグラウンドが通過しているだけです;)Railsの方法にもっと一致するよりクリーンなアプローチはありますか?
更新:これをトランザクション内でラップしてロールバックするのは見苦しいだけでなく、正しく機能させるのは非常に難しいようです。このコードを実行するメソッド自体が別のトランザクションにある可能性があり、ActiveRecordリレーションシップオブジェクトへの変更が自動保存される傾向があるため、それを機能させるために多くのフープを飛び越えなければなりませんでした。
受け入れられた回答の提案に基づいて、新しいTeamStatsオブジェクトを完全に作成し、保存しないというアプローチを採用しました。私にとってはずっとうまくいくようです。