ActiveRecord through Drb: problem with ids

Hi,

I’m trying to use ActiveRecord objects through Drb, and I’m facing a
strange thing:

Firstly, I’m using the following database:


– SQL

CREATE TABLE gardens
(
lock_version integer DEFAULT 0,
id integer NOT NULL AUTO_INCREMENT,
name varchar(50),

PRIMARY KEY (id)
) TYPE=INNODB;

CREATE TABLE flowers
(
lock_version integer DEFAULT 0,
id integer NOT NULL AUTO_INCREMENT,
garden_id integer NOT NULL,
name varchar(50),
color varchar(50),

PRIMARY KEY (id),
FOREIGN KEY (garden_id) REFERENCES gardens (id)
) TYPE=INNODB;

Now if I launch this server code:


– Drb / ActiveRecord Server

#!/usr/local/bin/ruby
require ‘rubygems’
require ‘drb’
require ‘active_record’
require ‘active_record/transactions’

ActiveRecord::Base.establish_connection(
:adapter => “mysql”,
:username => “root”,
:host => “localhost”,
:password => “”,
:database => “flowers”
)

We build the ActiveRecord objects

class Garden < ActiveRecord::Base
include DRbUndumped
has_many :flowers
end

class Flower < ActiveRecord::Base
include DRbUndumped
belongs_to :garden
end

We add some data

Garden.transaction do
g = Garden.new(“name” => “garden1”)
g.flowers << Flower.new(“name” => “flower1”, “color” => “color1”)
g.flowers << Flower.new(“name” => “flower2”, “color” => “color2”)
g.save
g = Garden.new(“name” => “garden2”)
g.flowers << Flower.new(“name” => “flower3”, “color” => “color3”)
g.save
end

We create the server and instanciate it

class Server
def find(i)
Garden.find(i)
end
end

s = Server.new

We query the server

g = s.find(1)
puts “#{g.id} | #{g.name}”
g.flowers.each do |f|
puts “#{f.id} | #{f.garden_id} | #{f.name}”
end

We make the server available thruogh Drb

DRb.start_service(‘druby://localhost:9000’, s)
DRb.thread.join

… I get what I was expecting, that is:


1 | garden1
1 | 1 | flower1
2 | 1 | flower2

Now I’m trying to call the server through Drb, with exactly the same
code:


– Drb / ActiveRecord Client, version 1

#!/usr/local/bin/ruby
require ‘drb’

DRb.start_service()
obj = DRbObject.new(nil, ‘druby://localhost:9000’)

g = obj.find(1)
puts “#{g.id} | #{g.name}”
g.flowers.each do |f|
puts “#{f.id} | #{f.garden_id} | #{f.name}”
end

… I get:


ar_client.rb:8: warning: Object#id will be deprecated; use
Object#object_id
67884862 | garden1
ar_client.rb:10: warning: Object#id will be deprecated; use
Object#object_id
67882632 | 1 | flower1
ar_client.rb:10: warning: Object#id will be deprecated; use
Object#object_id
67880122 | 1 | flower2

Where do these warnings come from? And why these ids?

II follow the warning message, and change the code a little bit:


– Drb / ActiveRecord Client, version 2

#!/usr/local/bin/ruby
require ‘drb’

DRb.start_service()
obj = DRbObject.new(nil, ‘druby://localhost:9000’)

g = obj.find(1)
puts “#{g.object_id} | #{g.name}”
g.flowers.each do |f|
puts “#{f.object_id} | #{f.garden_id} | #{f.name}”
End

… I get:


67884862 | garden1
67882642 | 1 | flower1
67880142 | 1 | flower2

Warning disappeared, but Ids are still wrong.

Does anyone understand what happens here?


Philippe L., Ing. Dipl. EPFL
Attik System
rte de la Fonderie 2
1700 Fribourg
Switzerland
http://www.attiksystem.ch

Tel: +41 (26) 422 13 75
Fax: +41 (26) 422 13 76

On Fri, 25 Aug 2006, Philippe L. wrote:

… I get:


ar_client.rb:8: warning: Object#id will be deprecated; use Object#object_id
67884862 | garden1
ar_client.rb:10: warning: Object#id will be deprecated; use Object#object_id
67882632 | 1 | flower1
ar_client.rb:10: warning: Object#id will be deprecated; use Object#object_id
67880122 | 1 | flower2

certain methods are treated specially by drb. it was a mistake for
rails to
override Object#id for exatly this kind of scenario - many peice of code
require it.

you need to do something like

class << ActiveRecord
alias “id__”, “id”
end

and then use this method.

Warning disappeared, but Ids are still wrong.

Does anyone understand what happens here?

you are calling Object#id/object_id - no ActiveRecord#id - check out the
drb
source to see why.

-a

On Aug 25, 2006, at 9:56 AM, Philippe L. wrote:

Warning disappeared, but Ids are still wrong.

Does anyone understand what happens here?

This is a total guess but it seems like DRB is not proxying
the call to ‘id’ across the net to the remote object. Instead
you seem to be getting the object_id
of the local proxy object instead of the Active Record version
of ‘id’ from the real object at the server.

Warning, I don’t have any special knowledge of DRB or AR internals,
this was just the first thing that came to mind when I saw your post.

Gary W.

On 25-aug-2006, at 16:38, [email protected] wrote:

certain methods are treated specially by drb. it was a mistake for
rails to
override Object#id for exatly this kind of scenario - many peice of
code
require it.

Consdering that Object#id is marked deprecated - I think it was a
good decision. I’d rather say it’s a problem with DrB that it doesn’t
use object_id instead

hi,

I just found this thread because I had a similar problem. I don’t think
it has something to do with drb, in fact my problem was that a “find” on
an activerecord returned a nil object. Here is the gotcha : nil is still
an object and has an id … which has nothing to do with database id’s.
As ruby’s author knows it’s an usual pitfall, calling that method
produces a warning.

I think the alias workaround is great, here is the syntax I used :

class ActiveRecord::Base
alias_method :id__, :id
end

This way you can use the method id__ for any ActiveRecord::Base
descendant. Useful to spot some bugs !