Self.id in model

Happy holidays all!

I have a has_many line in my Members.rb model:

has_many :friends, :class_name => “Member”, :finder_sql => “SELECT
members.* FROM members, friends WHERE friends.member_id = #{self.id}”

when I run this line: @member.friends, the following query is ran:

select members.* from members, friends where friends.member_id =
53930410

Ignore the logic, the point is, self.id keeps translating to some
crazy number like 53930410 instead of what it should be, 2.

Any ideas why?

What is happening is that you are getting the object’s object_id instead
of
it’s saved id. To see what I am talking about, load up irb and make an
object, say:
a = “A String”
then type:
a.id
It will say this is deprecated, and that you should use object_id
instead,
but it will also show you the object_id. These numbers vary greatly,
but
the one returned to you seems to fit right in with this.

However, I am not sure why this is happening in your specific case.
Hopefully this will at least help you look into the problem further.

Good luck and happy holidays,
Tyler P.

hi,

self is Members not an instance of Members
thus with self.id it translates to object_id aka self.id =>
Members.id

might help

regards
gaurav

Makes sense… so that begs the question, how can I access the
objects id field as opposed to the object_id?

Makes sense… so that begs the question, how can I access the
objects id field as opposed to the object_id?

Try self[:id]

undefined method `[]’ for Member:Class

On Dec 25, 1:09 pm, Victor G. [email protected]

hi,

irb(main):034:0> class A
irb(main):035:1> p self
irb(main):036:1> def g
irb(main):037:2> p self
irb(main):038:2> end
irb(main):039:1> end
A
=> nil
irb(main):043:0> a=A.new
=> #<A:0x2c59570>
irb(main):044:0> a.g
#<A:0x2c59570>
=> nil

this might give clear picture whats happening

regards
gaurav

Ignore the logic, the point is, self.id keeps translating to some
crazy number like 53930410 instead of what it should be, 2.

Any ideas why?

According to documentation simple #{id} should work, but it does not.
I think it is a bug. Can anyone confirm this?

Regards,
Rimantas

http://rimantas.com/

Try self[:id] or self.send(:id).

You’re probably getting Ruby’s object id for the object denoted by self.

–steve

self[:id] raises the error listed above… self.send(:id) draws the
same object_id as before, not the objects id field from the database

hi,

I doubt you can do it that way.
As id you want is an instance variable and the way you want it is
without instantiation.

p=Place.new
=> #<Place:0x3406dc8 @attributes={“place”=>""}, @new_record=true>

p.id
=> nil

Place.id
(irb):8: warning: Object#id will be deprecated; use Object#object_id
=> 28166940

you can even try p.methods.sort and see the result
where you find id and id= methods similar to attr_accessors…

regards
gaurav

Now that I look at your code, I think it’s a context issue. Consider
this, when you call a class method, what is the definition of self?
Out of curiosity, why do you need to be so specific in your
finder_sql? Wouldn’t it be better to do something along the lines of

has_many :friends, :class_name => ‘Member’, :foreign_key => ‘member_id’

Then when you find a member, there is an association to that member’s
friends. You can simply select within them or use scope.

Am I on the right track?

app/models/member.rb
class Member < ActiveRecord::Base
has_many :my_friends, :class_name => “Friend”, :foreign_key =>
“member_id”
has_many :friends, :through => :my_friends, :source => :member
end

app/models/friend.rb
class Friend < ActiveRecord::Base
belongs_to :member
end

db/migrate/001_create_members.rb
class CreateMembers < ActiveRecord::Migration
def self.up
create_table :members do |t|
# t.column :name, :string
t.column :username, :string
end
end

def self.down
drop_table :members
end
end

db/migrate/002_create_friends.rb
class CreateFriends < ActiveRecord::Migration
def self.up
create_table :friends do |t|
# t.column :name, :string
t.column :member_id, :int
end
end

def self.down
drop_table :friends
end
end

ruby script/console

Member.new(:username => “edbond”).save
=> true

Member.find(:first).friends
=> []

will generate (from log/development.log):
Member Load (0.000361) SELECT members.* FROM members INNER JOIN
friends ON members.id = friends.member_id WHERE (friends.member_id = 1)

In through associations on edge rails you can use << method to add new
friends.
In rails 1.1.6 you can’t. You need to create model for join table
see:
http://blog.hasmanythrough.com/articles/2006/08/19/magic-join-model-creation

“”“s.ross ( ):
“””

Yes you are on the right track… although I removed the difficult
logic to simplify the explanation of my problem.

Although at this point, I think I understand the context issue and why
it’s not working, so I think I’ll switch my strategy around and
eliminate the use of finder_sql.

Thanks all,
Chad

On Dec 25, 2006, at 3:39 AM, Chad A. wrote:

select members.* from members, friends where friends.member_id =
53930410

Ignore the logic, the point is, self.id keeps translating to some
crazy number like 53930410 instead of what it should be, 2.

Any ideas why?

Sure, you are getting the wrong self. Try:

has_many :friends, :class_name => “Member”, :finder_sql => ‘SELECT
members.* FROM members, friends WHERE friends.member_id = #{self.id}’

Note the change from "-quotes to '-quotes. You want the #{self.id}
to be evalulated later when the SQL is needed, not while you’re
defining the :finder_sql. (That is, when self is an instance of
Member not the class itself.)

You could also have escaped the interpolation “SELECT … #{self.id}”

Do you really need :finder_sql in this case? If a member can really
have more than one friend, wouldn’t you need another table to hold
the relationship (i.e., the friendships table)?

class Member < ActiveRecord::Base
has_many :friendships, :dependent => :destroy
has_many :friends, :through => :friendships
end
class Friendship < ActiveRecord::Base
belongs_to :member
belongs_to :friend, :class => ‘Member’, :foreign_key => :friend_id
end

-Rob

Rob B. http://agileconsultingllc.com
[email protected]

Sure, you are getting the wrong self. Try:

has_many :friends, :class_name => “Member”, :finder_sql => ‘SELECT
members.* FROM members, friends WHERE friends.member_id = #{self.id}’

Note the change from "-quotes to '-quotes. You want the #{self.id}
to be evalulated later when the SQL is needed, not while you’re
defining the :finder_sql. (That is, when self is an instance of
Member not the class itself.)

Thank you for pointing this out! I think this is quite a gotcha and
deserves a word or two in
documentation…

Regards,
Rimantas

http://rimantas.com/