4

I'm trying to achieve the following in my ruby on rails application. This is also my database layout and the model names. Illustation

However, this isnt really working out for me.

User model:

class User < ActiveRecord::Base
    has_many :follows
    has_many :users, :through => :follows
end

Follow model:

class Follow < ActiveRecord::Base
    belongs_to :user, :foreign_key => :follow_user_id
end

I use this to debug:

<% current_user.follows.each do |x| %>
    <%= debug x.user %>
<% end %>

Debug

I have no idea how to do this the other way around and I'm not even sure if I'm doing this right. Any help appreciated.

Mike
  • 127
  • 12
  • 1
    Do you mean you want an "is_followed_by" relationship? – Shadow Radiance Sep 26 '14 at 18:04
  • 1
    Take a look at this: http://stackoverflow.com/questions/3397920/relationship-like-twitter-followers-followed-in-activerecord or this one http://stackoverflow.com/questions/6762919/ruby-on-rails-has-many-through-self-referential-following-follower-relationships – MrYoshiji Sep 26 '14 at 18:06
  • Just looked it up and yes, thats what I'm looking for. – Mike Sep 26 '14 at 18:07
  • 1
    The rails tutorial also has a nice explanation of how to do this. https://www.railstutorial.org/book/following_users#sec-the_relationship_model – nPn Sep 26 '14 at 18:18

2 Answers2

2

You have the right idea, you just haven't completed the associations. First, note that User is connected twice to Follow - once in each direction.

rails g model User email:string name:string
rails g model Follow user:references follow_user:references

Then:

class User < ActiveRecord::Base
  has_many :follows, inverse_of: :user
  has_many :followers, through: :follows

  has_many :followings, class_name: 'Follow', foreign_key: :follow_user_id, inverse_of: :follower
  has_many :users_i_follow, through: :followings, source: :user
end

class Follow < ActiveRecord::Base
  belongs_to :user, inverse_of: :follows
  belongs_to :follower, inverse_of: :followers, class_name: 'User', foreign_key: :follow_user_id
end

Now, for a user you have two associations that you'll probably mostly use: "followers" and "users_i_follow".

mdchaney$ bundle exec rails c
Loading development environment (Rails 4.1.5)
2.1.1 :001 > u = User.create(:email => 'test@comor.net', :name => 'Leader Guy')
 => #<User id: 1, email: "test@comor.net", name: "Leader Guy", created_at: "2014-09-26 18:48:52", updated_at: "2014-09-26 18:48:52"> 

2.1.1 :002 > u2 = User.create(:email => 'follower@comor.net', :name => 'Follower Guy')
 => #<User id: 2, email: "follower@comor.net", name: "Follower Guy", created_at: "2014-09-26 18:49:13", updated_at: "2014-09-26 18:49:13"> 

2.1.1 :003 > u3 = User.create(:email => 'follower3@comor.net', :name => 'Follower Guy, III')
 => #<User id: 3, email: "follower3@comor.net", name: "Follower Guy, III", created_at: "2014-09-26 18:49:25", updated_at: "2014-09-26 18:49:25"> 

2.1.1 :004 > u.followers
 => #<ActiveRecord::Associations::CollectionProxy []> 

2.1.1 :005 > Follow.create(:user => u, :follower => u2)
 => #<Follow id: 1, user_id: 1, follow_user_id: 2, created_at: "2014-09-26 18:50:12", updated_at: "2014-09-26 18:50:12"> 

2.1.1 :006 > Follow.create(:user => u, :follower => u3)
 => #<Follow id: 2, user_id: 1, follow_user_id: 3, created_at: "2014-09-26 18:50:14", updated_at: "2014-09-26 18:50:14"> 

2.1.1 :007 > u = User.find(1)
 => #<User id: 1, email: "test@comor.net", name: "Leader Guy", created_at: "2014-09-26 18:48:52", updated_at: "2014-09-26 18:48:52"> 

2.1.1 :008 > u.followers
 => #<ActiveRecord::Associations::CollectionProxy [#<User id: 2, email: "follower@comor.net", name: "Follower Guy", created_at: "2014-09-26 18:49:13", updated_at: "2014-09-26 18:49:13">, #<User id: 3, email: "follower3@comor.net", name: "Follower Guy, III", created_at: "2014-09-26 18:49:25", updated_at: "2014-09-26 18:49:25">]> 

2.1.1 :009 > u.follows
 => #<ActiveRecord::Associations::CollectionProxy [#<Follow id: 1, user_id: 1, follow_user_id: 2, created_at: "2014-09-26 18:50:12", updated_at: "2014-09-26 18:50:12">, #<Follow id: 2, user_id: 1, follow_user_id: 3, created_at: "2014-09-26 18:50:14", updated_at: "2014-09-26 18:50:14">]> 

2.1.1 :010 > u2 = User.find(2)
 => #<User id: 2, email: "follower@comor.net", name: "Follower Guy", created_at: "2014-09-26 18:49:13", updated_at: "2014-09-26 18:49:13"> 

2.1.1 :011 > u2.followers
 => #<ActiveRecord::Associations::CollectionProxy []> 

2.1.1 :012 > u2.follows
 => #<ActiveRecord::Associations::CollectionProxy []> 

2.1.1 :013 > u2.followings
 => #<ActiveRecord::Associations::CollectionProxy [#<Follow id: 1, user_id: 1, follow_user_id: 2, created_at: "2014-09-26 18:50:12", updated_at: "2014-09-26 18:50:12">]>

2.1.1 :014 > u2.users_i_follow
 => #<ActiveRecord::Associations::CollectionProxy [#<User id: 1, email: "test@comor.net", name: "Leader Guy", created_at: "2014-09-26 18:48:52", updated_at: "2014-09-26 18:48:52">]> 
Michael Chaney
  • 2,911
  • 19
  • 26
0

This also can be done with a single has_many :through association. See the related answer.

It's for the friends / friendships problem but it's basically identical to the followers / follows problem.

jibiel
  • 8,175
  • 7
  • 51
  • 74