0

I'm reading Service Oriented Design with Ruby on Rails, which includes the code you see in this image

enter image description here

My question is specifically about this line from the User model

has_many :followers, :through -> :followings, :source => :user

in which a User (as in an instance of the user model) has_many :followers, which are really just other users. So a user has_many users. This seems very weird to me that a User has_many :users, as if something should break when you write that, so I thought doign has_many :followers ...:source => :user might be meant to stop things from breaking.

According to one answer on this SO question Need help to understand :source option of has_one/has_many through of Rails, which was about the :source method for has_many associations, one rationale for using :source is to take code that looks this

class Newsletter
  has_many :subscriptions
  has_many :users, :through => :subscriptions
end

and change it into this

  class Newsletter
    has_many :subscriptions
    has_many :subscribers, :through => :subscriptions, :source => :user
   end

so that instead of doing this

  Newsletter.find(id).users

one would do the much more logical (because Newsletters have subscribers not users)

   Newsletter.find(id).subscribers

So, returning to the code from the book, my question is, is the only rationale for doing this in the User model

 has_many :followers, :through -> :followings, :source => :user

to make more readable code User.find(id).followers ? There would otherwise be no problem doing

User.rb 

has_many :users

Because if Rails let you do that (i.e. it doesn't break the application), then where would you put the belongs_to?

User.rb
has_many :users
belongs_to :user

This would seem very weird to me, but if :source is only there to let you write clearer queries, then this code should still work?

Update: the point of the question is, is there anything stopping anyone from doing this?

 User.rb
    has_many :users
    belongs_to :user
Community
  • 1
  • 1
BrainLikeADullPencil
  • 11,313
  • 24
  • 78
  • 134

1 Answers1

0

You are correct you don't need the source, its because you are removing the through parameter

User doesn't have may users

User has many following, each of which have a user so you need:

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

See more here:

http://guides.rubyonrails.org/association_basics.html#the-has_many-through-association

msaspence
  • 1,424
  • 2
  • 14
  • 25
  • I know Users doesn't have many :users, but the point of the post is, could it? It seems totally illogical to say User has_many :users, belongs_to :user. – BrainLikeADullPencil Mar 18 '13 at 14:44
  • This is a self referential association, and is perfectly acceptable, they are often renamed to make them more logical because as you say when does a users user really mean? For example rather than a `belongs_to :user`, and `has_many: :users` you'd do something like `belongs_to :father, class_name: 'User', foreign_key: 'father_id'`, and `has_many :children, class_name: 'User', foreign_key: 'father_id'` – msaspence Mar 18 '13 at 17:49