Acts_as_ferret transactions

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

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs