acts_as_ferret does not handle transaction aborts properly. If a model is modified but something latter causes the transaction it was wrapped in to abort, the ferret index will not revert to the original record data. I have included a klunky patch to defer modifying the ferret index until after the current transaction commits. It would seem prudent to resolve this issue, though I don''t think I have an ideal solution. I have an acts_as_ferret model that has indexed properties that are derived from other models that it is associated with. As a side effect this patch ensures that if I wrap modifications to the model and the associated models in a transaction all the modifications to the associated models make it into the ferret index. Thoughts? Index: lib/acts_as_ferret.rb ==================================================================--- lib/acts_as_ferret.rb (revision 59) +++ lib/acts_as_ferret.rb (working copy) @@ -496,7 +496,8 @@ module InstanceMethods attr_reader :reindex - @ferret_reindex = true + @ferret_reindex = false + @defer_for_transaction = false def ferret_before_update @ferret_reindex = true @@ -505,9 +506,13 @@ # add to index def ferret_create - logger.debug "ferret_create/update: #{self.class.name} : #{self.id}" - self.class.ferret_index << self.to_doc if @ferret_reindex - @ferret_reindex = true + unless @defer_for_transaction + logger.debug "ferret_create/update: #{self.class.name} : #{self.id}" + self.class.ferret_index << self.to_doc if @ferret_reindex + @ferret_reindex = true + else + logger.debug "deferred ferret_create/update: #{self.class.name} : #{self.id}" + end true end alias :ferret_update :ferret_create @@ -522,6 +527,21 @@ end true end + + def at_start_transaction(name = nil) + @defer_for_transaction = true + end + + def at_abort_transaction(name = nil) + @defer_for_transaction = false + @ferret_reindex = false + end + + def at_commit_transaction(name = nil) + @defer_for_transaction = false + ferret_create + @ferret_reindex = false + end # convert instance to ferret document def to_doc @@ -786,4 +806,28 @@ end end +module Transaction + module Simple + alias :start_transaction_object :start_transaction + alias :abort_transaction_object :abort_transaction + alias :commit_transaction_object :commit_transaction + + def start_transaction(name = nil) + at_start_transaction(name) if respond_to?(:at_start_transaction) + start_transaction_object(name) + end + + def abort_transaction(name = nil) + at_abort_transaction(name) if respond_to?(:at_abort_transaction) + abort_transaction_object(name) + end + + def commit_transaction(name = nil) + at_commit_transaction(name) if respond_to?(:at_commit_transaction) + commit_transaction_object(name) + end + end +end + + # END acts_as_ferret.rb -- Posted via http://www.ruby-forum.com/.