0

In my app Users can follow each other. I have two tables: users and followers.

users

id
name

followers

id
user_id
follower_id

And two models:

class User < ActiveRecord::Base

  has_many :followers
  belongs_to :follower

end

class Follower < ActiveRecord::Base

  belongs_to :user

end

What I want to do is list the followers for a user. e.g.

<ul>
  <% @users.each do |user| %>
      <li><%= user.name %></li>
      <ul>
        <% user.followers.each do |follower| %>
            <li><%= follower.name %></li>
        <% end %>
      </ul>
  <% end %>
</ul>

However it doesn't look to be seeing the association...


After updating my model as per Deep's suggestions I got it working... however I'm unable to query followers and following users.

e.g.

I have two methods in my UsersController:

def user_followers
  @user = User.where(id: params[:id]).first
  @followers = @user.get_followers
end

def user_following
  @user = User.where(id: params[:id]).first
  @following = @user.get_following
end

and then in my User model I have:

def get_followers
  Follower.where(follower_id: self.id)
end

def get_following
  Follower.where(user_id: self.id)
end

Which should be returning the followers for the user or who the user is following. The views look like so:

<% @followers.each do |follower| %>
    <%= follower.user.name %>
<% end %>

<% @following.each do |following| %>
    <%= following.user.name %>
<% end %>

However it only returns the name of the user I'm supposed to be viewing.

The Follower model now looks like:

class Follower < ActiveRecord::Base

  belongs_to :user, foreign_key: 'follower_id', class_name: 'User'

end
Cameron
  • 27,963
  • 100
  • 281
  • 483

1 Answers1

1

The follower.name will not work because your follower model has no attribute named name. Also the association you have given is belongs_to :user which will fetch the user who has been followed. You need another association in the Follower model like:

belongs_to :following_user, foreign_key: 'follower_id', class_name: 'User'

And then in your view what you can do is:

<%= follower.following_user.name %>

This will fetch the user who has followed and from that object it will fetch the name attribute.

Update:

Don't remove the existing association you have. Means your model should look like:

belongs_to :user    
belongs_to :following_user, foreign_key: 'follower_id', class_name: 'User'

Now as discussed in comments user_id will consist of the user who is being followed and follower_id will consist of the user who is following.

To fetch the followers of a user you have the association which will find the followers. Just like user.followers. And to fetch the name:

<% user.followers.each do |follower| %>
   <li><%= follower.following_user.name %></li>
<% end %>

To find the followed users:

def followed_users
  Follower.where(follower_id: id)
end

And to fetch the name:

<% user.followed_users.each do |follower| %>
   <li><%= follower.user.name %></li>
<% end %>
Deepesh
  • 6,138
  • 1
  • 24
  • 41
  • Gives me the error: `SQLite3::SQLException: no such column: users.follower_id: SELECT "users".* FROM "users" WHERE "users"."follower_id" = ? LIMIT 1` – Cameron Dec 29 '16 at 12:08
  • Can you try including `primary_key: 'id'` in the association? – Deepesh Dec 29 '16 at 12:12
  • Aah.. just change the `has_one` to `belongs_to` and try please – Deepesh Dec 29 '16 at 12:19
  • That was a mistake of `foreign_key`. You can read more here: http://stackoverflow.com/questions/3808926/whats-the-difference-between-belongs-to-and-has-one – Deepesh Dec 29 '16 at 12:21
  • I've found another association issue, check my updated OP to see what I mean. – Cameron Dec 29 '16 at 14:23
  • I didn't understand your issue. What you need is the list of `followers` that is in `@followers` (it consist of the object of `Follower` model). Now you are looping it and fetching the `name` so it will get you the `name` only. What else do you want? – Deepesh Dec 29 '16 at 14:28
  • The `name` is of the user I'm viewing. So if user 1 is 'Cameron' and has 4 users following him, I will see the name 'Cameron' 4 times. Where as what I want to see is the 4 names of the users following. – Cameron Dec 29 '16 at 14:33
  • If I put it another way... `def get_followers Follower.where(follower_id: self.id) self.followers end` this works. But what is wrong with my query? – Cameron Dec 29 '16 at 14:40
  • It completely depends on how you have saved the `user_id` and `follower_id`. It seems that when saving the follower you have saved the user_id of user who is following in `user_id` and to whom he is following in `follower_id`. – Deepesh Dec 29 '16 at 14:53
  • That's correct. But I want to be able to query to see a list of users following a user and a list of users being followed by a user. – Cameron Dec 29 '16 at 15:17
  • That doesn't look to be working at the moment, as `.followers` looks to return all users from the db that match the `user_id` (regardless of follower or following) – Cameron Dec 29 '16 at 15:24
  • I think you need to save this in the opposite way and it will work fine. `user_id` will consist of the user who is being followed and `follower_id` will consist of the user who if following. – Deepesh Dec 29 '16 at 15:35
  • Okay doing that now. But how I get a list of followers (users following this user) for a particular user, and also a list of following (users that this user is following) for a user. Could you show an example of how to get these two lists? Thanks. – Cameron Dec 29 '16 at 15:39
  • Updated the answer. Check it. – Deepesh Dec 29 '16 at 16:11