Do delegates work properly in Drb mode?

Hi folks,

I have several models that index well in Drb mode.

However, I have one scenario where it works in normal mode, but not in
Drb mode.

model A
field :one
end

model B
belongs_to :a

field :two
delegate :one, :to => :a

acts_as_ferret :fields => { :one => {}, :two => {} }, :remote => true
end

If I leave off the :remote parameter, it works. Or, if I don’t index
field :one it works in remote mode. But I can’t use Drb to index the
delegate.

Am I doing something wrong?

Thanks
Joerg

On Wed, Jun 13, 2007 at 03:08:54PM +0200, Joerg D. wrote:

If I leave off the :remote parameter, it works. Or, if I don’t index
field :one it works in remote mode. But I can’t use Drb to index the
delegate.

Am I doing something wrong?

I’m not sure, but I don’t think so :slight_smile:

What exactly is your problem? Field :one just not being indexed or an
exception?

Could you try to replace the degate with a normal method call in a
method named ‘one’ and see what happens then?

A possible cause for this might be that the DRb server doesn’t see your
:a relationship when b gets indexed. To check this, you could i.e.
override aaf’s to_doc instance method in class B and have a look at the
:a relationship or try to call the delegated method yourself.

Jens


Jens Krämer
webit! Gesellschaft für neue Medien mbH
Schnorrstraße 76 | 01069 Dresden
Telefon +49 351 46766-0 | Telefax +49 351 46766-66
[email protected] | www.webit.de

Amtsgericht Dresden | HRB 15422
GF Sven Haubold, Hagen Malessa

Hi Jens - ok - that’s a lot of meat to work with for now. Thanks. I’ll
post back here once I’ve figured it out or got more info.

(The error message I receive is that Ferret cannot find the “add” method
on model b.)

A possible cause for this might be that the DRb server doesn’t see your
:a relationship when b gets indexed. To check this, you could i.e.
override aaf’s to_doc instance method in class B and have a look at the
:a relationship or try to call the delegated method yourself.

Jens

One other thing that is WEIRD is that I have a unit test, with a single
line:

assert B.create!(:a => a, :two => “Test”)

  1. This line fails every time I run it (the Ferret error about there not
    being a method called “add” on model B).

  2. When I then comment out the delegate field in the acts_as_ferret
    declaration, and rerun the test, it works.

  3. But now this is the INTERESTING bit: If I re-include (uncomment) the
    delegate in the acts_as_ferret declaration, and run the test again …
    then the test passes!

  4. And when I delete the index folder and rerun the test, it still
    works.

  5. Then I top and start Ferret and the tests FAIL.

  6. Now I do step 2. again, and the tests pass.

  7. Step 3. and the test FAILS.

  8. Run the test again, and it PASSES.

So … yeah. Sometimes it works - other times it doesn’t.

class Employee
belongs_to :person
delegate :name, :to => :person

acts_as_ferret( :fields => { :employee_no => {},
:name => {}
}, :remote => true)
end

test_create(EmployeeTest):
NoMethodError: undefined method `add’ for Employee:Class
at top level in localhost at line 9009
at top level in localhost at line 9009
at top level in localhost at line 9009
method << in remote_index.rb at line 31
method ferret_create in instance_methods.rb at line 73
method send in callbacks.rb at line 333
method callback in callbacks.rb at line 333
method each in callbacks.rb at line 330
method callback in callbacks.rb at line 330
method create_without_timestamps in callbacks.rb at line 255
method create_without_user in timestamp.rb at line 30
method create in user_monitor.rb at line 22
method create_or_update_without_callbacks in base.rb at line 1792
method create_or_update in callbacks.rb at line 242
method save_without_validation! in base.rb at line 1554
method save_without_transactions! in validations.rb at line 762
method save! in transactions.rb at line 133
method transaction in database_statements.rb at line 59
method transaction in transactions.rb at line 95
method transaction in transactions.rb at line 121
method save! in transactions.rb at line 133
method create! in validations.rb at line 727
method test_create in employee_test.rb at line 165

On Wed, Jun 13, 2007 at 04:30:59PM +0200, Joerg D. wrote:

Hi Jens - ok - that’s a lot of meat to work with for now. Thanks. I’ll
post back here once I’ve figured it out or got more info.

(The error message I receive is that Ferret cannot find the “add” method
on model b.)

strange, do you have a stack trace of this error?

Jens


Jens Krämer
webit! Gesellschaft für neue Medien mbH
Schnorrstraße 76 | 01069 Dresden
Telefon +49 351 46766-0 | Telefax +49 351 46766-66
[email protected] | www.webit.de

Amtsgericht Dresden | HRB 15422
GF Sven Haubold, Hagen Malessa

I have the same problem using the Drb Server but mine is consistent, I
get this everytime once I switch to remote mode:

NoMethodError: undefined method add' for User:Class from (druby://localhost:9010) /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:1236:inmethod_missing’
from (druby://localhost:9010)
./script/…/config/…/vendor/plugins/acts_as_ferret/lib/ferret_server.rb:70:in
send' from (druby://localhost:9010) ./script/../config/../vendor/plugins/acts_as_ferret/lib/ferret_server.rb:70:inmethod_missing’
from
./script/…/config/…/config/…/vendor/plugins/acts_as_ferret/lib/remote_index.rb:31:in
<<' from ./script/../config/../config/../vendor/plugins/acts_as_ferret/lib/instance_methods.rb:73:inferret_update’

The acts_as_ferret line for the User model is very basic:
acts_as_ferret :fields => [‘lastname’,‘firstname’], :remote =>
true

Ahh, after some investigation, I found that starting the ferret server
puts the following in the Rails log:

Asked for a remote server ? true, ENV[“FERRET_USE_LOCAL_INDEX”] is nil,
server is not_running
Will use remote index server which should be available at
druby://127.0.0.1:9010

Which was only vaguely suspicious, but then the code revealed:

Usually the automatic detection of server mode works fine, however if

you

require your model classes in environment.rb they will get loaded

before the

DRb server is started, so this code is executed too early and

detection won’t

work. In this case you’ll get endless loops resulting in "stack level

too deep"

errors.

To get around this, start the server with the environment variable

FERRET_USE_LOCAL_INDEX set to ‘1’.

Now the comments claim that we would get “stack level too deep” but
because RemoteIndex::add modifies the argument with a to_doc, we
actually get a NoMethodError from the second call to to_doc:

undefined method `to_doc’ for {“firstname”=>“Seggy”,
“lastname”=>“Umboh”, :id=>1}:Ferret::Document

This effectively cuts the infinite loop, and avoids the “stack level too
deep” error.

So, the solution, at least in my case, is to run the server with:

FERRET_USE_LOCAL_INDEX=1 script/ferret_start

Hope that helps…

By setting the environment variable this way, it only takes effect for
that command, which is the ferret server. The server needs to use the
LocalIndex internally.

Your regular Rails app will not have FERRET_USE_LOCAL_INDEX set, and
thus use RemoteIndex.

Try it out…

Joerg D. wrote:

Hmm … that means though that I am not using the remote server?

So, the solution, at least in my case, is to run the server with:

FERRET_USE_LOCAL_INDEX=1 script/ferret_start

Hope that helps…

Hmm … that means though that I am not using the remote server?

So, the solution, at least in my case, is to run the server with:

FERRET_USE_LOCAL_INDEX=1 script/ferret_start

Hope that helps…

I should also add that this environment variable is only being read
after http://projects.jkraemer.net/acts_as_ferret/changeset/180

So if you are using the gem, you will either need to backport this fix
as an extension or use the plugin in trunk.

Seggy Umboh wrote:

By setting the environment variable this way, it only takes effect for
that command, which is the ferret server. The server needs to use the
LocalIndex internally.

Your regular Rails app will not have FERRET_USE_LOCAL_INDEX set, and
thus use RemoteIndex.

Try it out…

Joerg D. wrote:

Hmm … that means though that I am not using the remote server?

So, the solution, at least in my case, is to run the server with:

FERRET_USE_LOCAL_INDEX=1 script/ferret_start

Hope that helps…

Did it all, but the trunk version complains that it cannot find my
index/test/my_model directory when I run the test … :frowning:

Seggy Umboh wrote:

I should also add that this environment variable is only being read
after http://projects.jkraemer.net/acts_as_ferret/changeset/180

So if you are using the gem, you will either need to backport this fix
as an extension or use the plugin in trunk.

Seggy Umboh wrote:

By setting the environment variable this way, it only takes effect for
that command, which is the ferret server. The server needs to use the
LocalIndex internally.

Your regular Rails app will not have FERRET_USE_LOCAL_INDEX set, and
thus use RemoteIndex.

Try it out…

Joerg D. wrote:

Hmm … that means though that I am not using the remote server?

So, the solution, at least in my case, is to run the server with:

FERRET_USE_LOCAL_INDEX=1 script/ferret_start

Hope that helps…

On Fri, Jun 15, 2007 at 01:00:46AM +0200, Seggy Umboh wrote:

Did it all, but the trunk version complains that it cannot find my
index/test/my_model directory when I run the test … :frowning:

I usually run Model.rebuild_index once per test class, or even in set_up
before every test method. That will create the index dir.

However the directory should be created by aaf automatically, I just
committed a fix for this.

Jens


Jens Krämer
webit! Gesellschaft für neue Medien mbH
Schnorrstraße 76 | 01069 Dresden
Telefon +49 351 46766-0 | Telefax +49 351 46766-66
[email protected] | www.webit.de

Amtsgericht Dresden | HRB 15422
GF Sven Haubold, Hagen Malessa

Thanks Jens.

However the directory should be created by aaf automatically, I just
committed a fix for this.

Jens

Oh yeah I had that too, I just added another extension to create the
directory if it does not exist. It might be more correct to rebuild the
index for the model instead of just creating an empty directory, I’m not
sure.

Right now, I have moved back to the gem for production use so
unfortunately I don’t have the code that I used to do the above.

Joerg D. wrote:

Did it all, but the trunk version complains that it cannot find my
index/test/my_model directory when I run the test … :frowning:

Seggy Umboh wrote:

I should also add that this environment variable is only being read
after http://projects.jkraemer.net/acts_as_ferret/changeset/180

So if you are using the gem, you will either need to backport this fix
as an extension or use the plugin in trunk.

Seggy Umboh wrote:

By setting the environment variable this way, it only takes effect for
that command, which is the ferret server. The server needs to use the
LocalIndex internally.

Your regular Rails app will not have FERRET_USE_LOCAL_INDEX set, and
thus use RemoteIndex.

Try it out…

Joerg D. wrote:

Hmm … that means though that I am not using the remote server?

So, the solution, at least in my case, is to run the server with:

FERRET_USE_LOCAL_INDEX=1 script/ferret_start

Hope that helps…