Hi,<br>
<br>
following the discussion about acts_as_ferret on the Rails mailinglist,
there was an issue about transactions, which could result in beind the
database and ferret out of sync. I have taken a different approach from
acts_as_ferret trying to resolve the transaction problem. Instead of
adding things to the ferret index in the model, I have added it in the
controller. I have only the create part for now and it's very rough,
but it works.<br>
<br>
&nbsp; def create<br>
&nbsp; &nbsp;&nbsp;&nbsp; if request.get?<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; redirect_to :action =&gt; 'new'<br>
&nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @user = User.find(session[:user_id])&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @ad = Ad.new(params[:ad])<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @listing = Listing.new(params[:listing])<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @listing.listing_type = &quot;ads&quot;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; index ||= Index::Index.new(:key =&gt; [:id, :table],<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
:path =&gt; &quot;#{RAILS_ROOT}/db/index.test&quot;,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
:auto_flush =&gt; true)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Listing.transaction(@ad) do<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @ad.listings &lt;&lt; @listing<br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if @ad.save<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session[:last_addition] = @<a href="http://ad.id">ad.id</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #ferret create a new entry in the index<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doc = Ferret::Document::Document.new<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doc
&lt;&lt; Ferret::Document::Field.new(&quot;id&quot;, @<a href="http://ad.id">ad.id</a>,
Document::Field::Store::YES,&nbsp; Document::Field::Index::UNTOKENIZED)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doc
&lt;&lt; Ferret::Document::Field.new(&quot;table&quot;, @listing.listing_type,
Document::Field::Store::YES, Document::Field::Index::UNTOKENIZED)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doc
&lt;&lt; Ferret::Document::Field.new(&quot;content&quot;, @ad.title + &quot; &quot; +
@ad.text,&nbsp; Document::Field::Store::NO,
Document::Field::Index::TOKENIZED)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; index &lt;&lt; doc<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; index.flush<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flash[:notice] = 'Ad was successfully created.'<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; redirect_to :action =&gt; 'list'<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; index.close<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; render :action =&gt; 'new'<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rescue<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if session[:last_addition]<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; logger.error &quot;We verwijderen ad met id: #{session[:last_addition]}&quot;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; index.query_delete(&quot;+id:#{session[:last_addition]} +table:ads&quot;)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; index.flush<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session[:last_addition] = nil<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flash[:notice] = 'An error occurred.'<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; redirect_to :action =&gt; 'new'<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end<br>
&nbsp;&nbsp;&nbsp; end<br>
&nbsp; end<br>
<br>
How does it work, or at least how do I think it works. If everything
goes well, the entry gets in the Ferret index. I had to use
index.flush, because without I got a lock. Don't know why this happens,
because I set autoflush to true.<br>
When I have a validation error (field of form is empty, or...) in my
model, the else part of @ad.save is taken, there I close the index. I
don't know if this is necessary, but just to be sure.<br>
When their is another error: ferret index is not available, trying to
add wrong field or something. Transaction - rescue kicks in. If there
are no validation errors, the ad should get saved, so I set a session
variable last_addition to hold the id of the ad that is being saved,
when an error occurs I have the id of the ad just added. In the rescue
block I check if the session variable last_addition is set. If it is, I
search ferret and delete the addition, afterwhich I flush index (had to
add it, otherwise I would get a lock).<br>
<br>
Is my solution waterproof or am I missing something. All feedback is welcome.<br>
<br>
Kind regards,<br>
<br>
Nick<br>