views:

29

answers:

3

I'm working on Ruby on rails 2.3.8, and I'd like to build a functionality to follow users.

For this purpose, I've created 2 tables: users and followings, with their respective models:

class User < ActiveRecord::Base
  has_and_belongs_to_many :followings, :foreign_key => "follower_id"
end

class Following < ActiveRecord::Base
  has_and_belongs_to_many :users, :foreign_key => "follower_id", :class_name => "User"
end

Now, when I try to execute current_user.followings.all (with a valid current_user, of course), it throws me the following exception:

'followings_users' doesn't exist: SELECT 'followings'.* FROM `followings`  INNER JOIN 'followings_users' ON 'followings'.id = 'followings_users'.following_id WHERE ('followings_users'.follower_id = 1 )

I can't make this work. I don't know why it asks me for a "followings_users" table. What if I want to call it just "followings"?

What am I doing wrong here?

+1  A: 

When using habtm, Rails will try to get the associations from a join table. It tries to guess the name of the table by joining the two names (followings_users), or you can specify the name of the table as an option. But you have to explicitely create this table in your migrations.

See documentation here

Chubas
So, the best option for me is to change the model and table names for following_user and following_users respectively?
Brian Roisentul
All you have to do is add the `:join_table` option. When we don't use the conventional naming, we can specify the join table name using this option.
j.
In which model should I put that option? Should it be :join_table => 'followings'? Because I've tried that on both User and Following models and it threw me the following, because it's trying to 'join itself': Not unique table/alias: 'followings': SELECT `followings`.* FROM `followings` INNER JOIN `followings` ON `followings`.id = `followings`.following_id WHERE (`followings`.follower_id = 1 )
Brian Roisentul
No, you don't have to rename the models. You have to add a table in the migration named followings_users. See the documentation, in the example they create a table `developers_projects`
Chubas
+1  A: 

You can also do this using the newer syntax has_many :through:

class User < ActiveRecord::Base
  has_many :user_followings
  has_many :followings, :through => :user_followings
end

class UserFollowing < ActiveRecord::Base
  belongs_to :users
  belongs_to :followings
end

class Following < ActiveRecord::Base
end

This requires a join table called :user_followings with columns user_id and following_id.

The new syntax is generally preferred over HABTM because it allows you to define methods on the join model, which can be useful, although HABTM still works fine as well.

zetetic
Which info will Following model have?
Brian Roisentul
You don't need to define associations on the Following model unless you needed to use them, i.e. if you wanted to know the Users for a Following you could define a `has_many :user_followings` and `has_many :users, :through => :user_followings`. I think the solution you posted does something similar.
zetetic
A: 

Well, I've found a great solution here: http://railstutorial.org/chapters/following-users?version=2.3#top

Thanks for your answers though.

Brian Roisentul