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 -~----------~----~----~----~------~----~------~--~---