It seems to work now as i want. I only rewrote a method update in Buddy
and created a ‘second_key’. It’s not all perfect but it works for me.
To wrap up what i have:
The 2 tables:
users:
-id
-username
-activated
-…
buddy:
-user_id
-user_buddy_id
-b_activated (0: at creation 1: when the user identified by
user_buddy_id has accepted to be buddy of the user identified by
user_id)
note: as you have a field also in user called ‘activated’, you have to
use another name otherwise one is dropped, you cannot access to both
‘activated’
The 2 models:
class User < ActiveRecord::Base
has_and_belongs_to_many :buddies,
:join_table => ‘buddies’,
:foreign_key => ‘user_id’,
:association_foreign_key => ‘user_buddy_id’,
# i don’t need those because the relation is
#directional:
#:after_add => :create_reverse_association,
#:after_remove => :remove_reverse_association,
:class_name => ‘User’,
:conditions => ‘b_activated=1’
other convenient access
has_and_belongs_to_many :sent_buddy_requests,
:join_table => ‘buddies’,
:foreign_key => ‘user_id’,
:association_foreign_key => ‘user_buddy_id’,
:class_name => ‘User’,
:conditions => ‘b_activated=0’
has_and_belongs_to_many :received_buddy_requests,
:join_table => ‘buddies’,
:foreign_key => ‘user_buddy_id’,
:association_foreign_key => ‘user_id’,
:class_name => ‘User’,
:conditions => ‘b_activated=0’
has_and_belongs_to_many :is_buddy_of,
:join_table => ‘buddies’,
:foreign_key => ‘user_buddy_id’,
:association_foreign_key => ‘user_id’,
:class_name => ‘User’,
:conditions => ‘b_activated=1’
end
class Buddy < ActiveRecord::Base
I have added a ‘second_key’ and copied more or less the code as it
came from
the ‘primary_key’. Only problem: in the update code
def self.second_key
reset_second_key
end
def self.set_second_key( value=nil, &block )
define_attr_method :second_key, value, &block
end
def reset_second_key
key = ‘id2’
I don’t understand what this code is doing:
case primary_key_prefix_type
when :table_name
key =
Inflector.foreign_key(class_name_of_active_record_descendant(self),
false)
when :table_name_with_underscore
key =
Inflector.foreign_key(class_name_of_active_record_descendant(self))
end
set_second_key(key)
key
end
set_primary_key “user_id”
set_second_key “user_buddy_id”
def update
att_quoted = attributes_with_quotes(false)
att_quoted.delete(self.class.second_key)
connection.update(
"UPDATE #{self.class.table_name} " +
"SET #{quoted_comma_pair_list(connection, att_quoted)} " +
“WHERE #{self.class.primary_key} = #{quote(id)} " +
" AND #{self.class.second_key} = #{quote(user_buddy_id)}”,
“#{self.class.name} Update”
)
end
end
Now I can do this:
a = User.find_by_username ‘agathe’
n = User.find_by_username ‘newthing’
a.buddies.push_with_attributes(n,{:b_activated => 0})
n.received_buddy_requests.size
=> 1
a.sent_buddy_requests[0]
=> #<User:0x3b45008 @attributes={“user_buddy_id”=>“11”,
“username”=>“newthing”, “id”=>“11”, “user_id”=>“3”,
“b_activated”=>“0”}>
n.received_buddy_requests[0]
=> #<User:0x3b6d538 @attributes={“user_buddy_id”=>“11”,
“username”=>“agathe”, “user_id”=>“3”, “id”=>“3”, “b_activated”=>“0”}>
b= Buddy.find_first
=> #<Buddy:0x3aa38f0 @attributes={“user_buddy_id”=>“11”, “user_id”=>“3”,
“b_activated”=>“0”}>
b.b_activated = 1
=> 1
b.save!
=> true
Note: you never get a Buddy object if you do ie a.buddies[0], you get a
user object, so the changes made on that object won’t be real. You need
to make the changes on the Buddy object directly, i.e on b =
Buddy.find_first
heepee