Yuval
2007-Aug-26 15:31 UTC
Looking for advice on table/model relationships for "adding friends", user-to-user relationship
Hi folks. I am developing a simple system where users can add other
users as friends. I have everything working, but after poring over
Agile Web Development With Rails, I feel like there must be a more
Active Recordy way of going about it. Something just seems off. Here''s
what I''ve got
A User model and associated users table that contains all the typical
user stuff (name, address, etc). The User class has_many :friends.
A Friend model and table that contains two columns: user_id and
linked_user_id. The Friend class belongs_to :user.
So for example if I have user 1 and user 2, and user 1 wants to add
user 2 as a friend, I do the following:
friend = Friend.new
friend.user_id = session[:user_id] # session[:user_id] is the
source user, 1
friend.linked_user_id = params[:id] # params[:id] is the target user,
2
if friend.save
render :whatever
end
Then, when I want to get a user''s list of friends as user objects, I
make a call to an instance method in the User class as follows:
def linked_users
users = []
friends.each do |v|
users << User.find(v.linked_user_id)
end
users
end
Can anyone spare any advice? Much appreciated.
Cheers
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---
Yuval
2007-Aug-26 20:25 UTC
Re: Looking for advice on table/model relationships for "adding friends", user-to-user relationship
I wanted to note that in addition to this seeming like too manual a process, it runs a sql statement for every user rather than one join. I tried the following declaration in the User model but it didn''t work: has_many :users, :through => :friends, :foreign_key => "linked_user_id" --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
wolfmanjm
2007-Aug-26 21:13 UTC
Re: Looking for advice on table/model relationships for "adding friends", user-to-user relationship
I have implemented a friendship system, which happens to be
polymorphic, but that is not really relevant.
This handles invitations and the status of the invitation as well
(open, accepted, rejected).
It requires a table called friends (ignore the ..._type fields if not
polymorphic)...
CREATE TABLE friends (
id serial NOT NULL,
inviter_id integer,
inviter_type character varying(255),
invitee_id integer,
invitee_type character varying(255),
status integer DEFAULT 0,
created_at timestamp without time zone,
updated_at timestamp without time zone
);
Here is what would go into the User model....
this_class_name= ''User''
has_many :invites,
:class_name => "Friend",
:as => :inviter,
:order => ''created_at DESC'',
:dependent => :destroy
has_many :outgoing_invites,
:class_name => "Friend",
:as => :inviter,
:conditions => "friends.status = 0",
:order => "created_at DESC"
has_many :accepted_invites,
:class_name => this_class_name,
:through => :invites,
:source => :invitee,
:source_type => this_class_name,
:conditions => "friends.status = 1"
has_many :invites_to,
:class_name => this_class_name,
:through => :invites,
:source => :invitee,
:source_type => this_class_name,
:conditions => "friends.status = 0"
has_many :rejected_invites,
:class_name => this_class_name,
:through => :invites,
:source => :invitee,
:source_type => this_class_name,
:conditions => "friends.status = -1"
has_many :rejections,
:class_name => "Friend",
:as => :invitee,
:conditions => "friends.status = -1",
:order => "created_at DESC"
has_many :invitations,
:class_name => "Friend",
:as => :invitee,
:order => ''created_at DESC'',
:dependent => :destroy
has_many :incoming_invitations,
:class_name => "Friend",
:as => :invitee,
:conditions => "friends.status = 0",
:order => "created_at DESC"
has_many :accepted_invitations,
:class_name => this_class_name,
:through => :invitations,
:source_type => this_class_name,
:source => :inviter,
:conditions => "friends.status = 1"
has_many :invitations_from,
:class_name => this_class_name,
:through => :incoming_invitations,
:source_type => this_class_name,
:source => :inviter
has_many :rejected_invitations,
:class_name => this_class_name,
:through => :invitations,
:source => :inviter,
:source_type => this_class_name,
:conditions => "friends.status = -1"
An inefficient method to get all friends is...
# finds friends regardless of who was inviter or invitee, and
status is accepted
def friends
accepted_invites + accepted_invitations
end
A more efficient (untested) method is...
def friends
find_by_sql(''SELECT p.* FROM users p, friends f WHERE f.status 1
AND ( (f.invitee_id = #{id} AND p.id = f.inviter_id) OR
(f.inviter_id = #{id} AND p.id = f.invitee_id) )'')
end
The advantages of this method are that only one entry per friendship
is required in the friends table (rather than two each way).
I''ll be blogging in far more detail on this soon in my blog...
http://blog.wolfman.com
Hope that helps
On Aug 26, 1:25 pm, Yuval
<uberll...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
wrote:> I wanted to note that in addition to this seeming like too manual a
> process, it runs a sql statement for every user rather than one join.
> I tried the following declaration in the User model but it didn''t
> work:
>
> has_many :users, :through => :friends, :foreign_key =>
> "linked_user_id"
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---
Yuval
2007-Aug-26 22:00 UTC
Re: Looking for advice on table/model relationships for "adding friends", user-to-user relationship
Lots to look over, as your system is a lot more in depth than mine, but I''ll pore over it tonight. Thanks wolfman. :) --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Michael Bannister
2007-Aug-27 00:07 UTC
Re: Looking for advice on table/model relationships for "adding friends", user-to-user relationship
have you considered using acts_as_tree? then, for instance you could do: some_user.friends << some_other_user -mike On 8/26/07, Yuval <uberllama-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > Lots to look over, as your system is a lot more in depth than mine, > but I''ll pore over it tonight. Thanks wolfman. :) > > > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Yuval
2007-Aug-27 01:30 UTC
Re: Looking for advice on table/model relationships for "adding friends", user-to-user relationship
Mike, give you give me a few more details? Cheers. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Michael Bannister
2007-Aug-27 01:54 UTC
Re: Looking for advice on table/model relationships for "adding friends", user-to-user relationship
Check it out in your book in section 18.6. Acts As Tree is designed
for creating a hierarchy of objects but it''s basically a Has And
Belongs To Many relationship with itself so it should work well for
your purposes.
Once you get the relationship set up you can treat the friends as an
array on each user like:
#grab some users from the database
mike = User.find_by_name("mike")
rebecca = User.find_by_name("rebecca")
yngwie = User.find_by_name("yngwie")
derrida = User.find_by_name("derrida")
#add friends like this:
mike.friends << rebecca
mike.friends << yngwie
mike.friends << derrida
#notice everyone wants to be my friend?
-Mike
On 8/26/07, Yuval <uberllama-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
wrote:>
> Mike, give you give me a few more details? Cheers.
>
>
> >
>
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---
Yuval
2007-Aug-27 05:49 UTC
Re: Looking for advice on table/model relationships for "adding friends", user-to-user relationship
Hmm not sure if that''s going to work. acts_as_tree looks to be designed for classes that have only one parent (belongs_to rather than has_and_belongs_to_many). On Aug 26, 7:54 pm, "Michael Bannister" <mikebannis...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Check it out in your book in section 18.6. Acts As Tree is designed > for creating a hierarchy of objects but it''s basically a Has And > Belongs To Many relationship with itself so it should work well for > your purposes. > > Once you get the relationship set up you can treat the friends as an > array on each user like: > > #grab some users from the database > mike = User.find_by_name("mike") > rebecca = User.find_by_name("rebecca") > yngwie = User.find_by_name("yngwie") > derrida = User.find_by_name("derrida") > > #add friends like this: > mike.friends << rebecca > mike.friends << yngwie > mike.friends << derrida > #notice everyone wants to be my friend? > > -Mike > > On 8/26/07, Yuval <uberll...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > Mike, give you give me a few more details? Cheers.--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Thorsten
2007-Aug-27 12:31 UTC
Re: Looking for advice on table/model relationships for "adding friends", user-to-user relationship
acts_as_tree is in no way a HABTM, it''s a has_many / belongs to: parent has many children, children beloong to 1 parent. so not suited for this. there''s a plugin for this purpose however: http://blog.dnite.org/2007/6/8/howto-has_many_friends On 27 Aug., 07:49, Yuval <uberll...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Hmm not sure if that''s going to work. acts_as_tree looks to be > designed for classes that have only one parent (belongs_to rather than > has_and_belongs_to_many). > > On Aug 26, 7:54 pm, "Michael Bannister" <mikebannis...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> > wrote: > > > > > Check it out in your book in section 18.6. Acts As Tree is designed > > for creating a hierarchy of objects but it''s basically a Has And > > Belongs To Many relationship with itself so it should work well for > > your purposes. > > > Once you get the relationship set up you can treat the friends as an > > array on each user like: > > > #grab some users from the database > > mike = User.find_by_name("mike") > > rebecca = User.find_by_name("rebecca") > > yngwie = User.find_by_name("yngwie") > > derrida = User.find_by_name("derrida") > > > #add friends like this: > > mike.friends << rebecca > > mike.friends << yngwie > > mike.friends << derrida > > #notice everyone wants to be my friend? > > > -Mike > > > On 8/26/07, Yuval <uberll...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > Mike, give you give me a few more details? Cheers.- Zitierten Text ausblenden - > > - Zitierten Text anzeigen ---~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Yuval
2007-Sep-07 20:48 UTC
Re: Looking for advice on table/model relationships for "adding friends", user-to-user relationship
Hi folks. Got this solved today (huge massive glowing happiness) and
thought I''d post my solution. Note, this is more of a subscription
model than a friends model.
Class User
has_many :bookmarks
has_many :bookmarked_users, :through => :bookmarks, :source
=> :bookmarked_user
end
Class Bookmark
belongs_to :user
belongs_to :bookmarked_user, :class_name => "User", :foreign_key
=>
"bookmarked_user_id"
end
And the join table migration looks like this.
class CreateBookmarks < ActiveRecord::Migration
def self.up
create_table :bookmarks do |t|
t.column :user_id, :integer, :null => false
t.column :bookmarked_user_id, :integer, :null => false
end
end
def self.down
drop_table :bookmarks
end
end
Works perfectly. Enjoy!
On Aug 27, 6:31 am, Thorsten
<duple...-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
wrote:> acts_as_tree is in no way a HABTM, it''s a has_many / belongs to:
> parent has many children, children beloong to 1 parent. so not suited
> for this.
> there''s a plugin for this purpose
however:http://blog.dnite.org/2007/6/8/howto-has_many_friends
>
> On 27 Aug., 07:49, Yuval
<uberll...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>
> > Hmm not sure if that''s going to work. acts_as_tree looks to
be
> > designed for classes that have only one parent (belongs_to rather than
> > has_and_belongs_to_many).
>
> > On Aug 26, 7:54 pm, "Michael Bannister"
<mikebannis...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> > wrote:
>
> > > Check it out in your book in section 18.6. Acts As Tree is
designed
> > > for creating a hierarchy of objects but it''s basically a
Has And
> > > Belongs To Many relationship with itself so it should work well
for
> > > your purposes.
>
> > > Once you get the relationship set up you can treat the friends as
an
> > > array on each user like:
>
> > > #grab some users from the database
> > > mike = User.find_by_name("mike")
> > > rebecca = User.find_by_name("rebecca")
> > > yngwie = User.find_by_name("yngwie")
> > > derrida = User.find_by_name("derrida")
>
> > > #add friends like this:
> > > mike.friends << rebecca
> > > mike.friends << yngwie
> > > mike.friends << derrida
> > > #notice everyone wants to be my friend?
>
> > > -Mike
>
> > > On 8/26/07, Yuval
<uberll...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>
> > > > Mike, give you give me a few more details? Cheers.-
Zitierten Text ausblenden -
>
> > - Zitierten Text anzeigen -
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---