In my app, User objects can follow each other, and be followed. The two relationships are distinct.
I'm seeing that when I set user_a.follows << user_b
that user_b.followed_by.count
still == 0. Why?
When I play in the console, I see:
$ jordan = User.new(:name=>"Jordan")
=> #<User id: nil, name: "Jordan">
$ matt = User.new(:name=>"Matt")
=> #<User id: nil, name: "Matt">
$ matt.followers << jordan
=> [#<User id: nil, name: "Jordan">]
$ matt.followers.first
=> #<User id: nil, name: "Jordan">
$ jordan.friends.first
=> nil
$ matt.save
SQL (14.1ms) INSERT INTO "users" ("name") VALUES (?) [["name", "Matt"]]
SQL (0.3ms) INSERT INTO "users" ("name") VALUES (?) [["name", "Jordan"]]
SQL (0.4ms) INSERT INTO "followings" ("f开发者_开发知识库ollowee_id", "follower_id") VALUES (?, ?) [["followee_id", nil], ["follower_id", 2]]
=> true
My objects are defined as:
class User < ActiveRecord::Base
has_many :follower_followee_rel,
:class_name => "Following",
:foreign_key => 'followee_id',
:dependent => :destroy
has_many :friends,
:through => :follower_followee_rel,
:source => :followee
has_many :followee_follower_rel,
:class_name => 'Following',
:foreign_key => 'follower_id',
:dependent => :destroy
has_many :followers,
:through => :followee_follower_rel,
:source => :follower
end
class Following < ActiveRecord::Base
belongs_to :followee,
:class_name => 'User'
belongs_to :follower,
:class_name => 'User'
end
Totally ignoring the second half of the relationship.
No errors are raised. What's going on?
Join relationships don't work unless the two models that are being joined have both already been saved. You can see on the 3rd line of the SQL that nil is being inserted for followee_id, as jordan doesn't yet have an id.
You would also need to save matt before you check jordan's friends, because doing matt.followers << jordan
is treated as a modification of matt that doesn't effect anything else until matt is saved.
Implementing Michael Fairley's suggestion got ActiveRecord to build the relationship, but the relationship was still being defined wrong.
Final solution was to save the records in advance of joining them, and to fix the foreign keys, which were backwards.
Was:
has_many :follower_followee_rel,
:class_name => 'Following',
:foreign_key => 'followee_id',
:dependent => :destroy
has_many :friends,
:through => :follower_followee_rel,
:source => :followee
has_many :followee_follower_rel,
:class_name => 'Following',
:foreign_key => 'follower_id',
:dependent => :destroy
has_many :followers,
:through => :followee_follower_rel,
:source => :follower
Is now:
has_many :follower_followee_rel,
:class_name => 'Following',
:foreign_key => 'follower_id',
:dependent => :destroy
has_many :friends,
:through => :follower_followee_rel,
:source => :followee
has_many :followee_follower_rel,
:class_name => 'Following',
:foreign_key => 'followee_id',
:dependent => :destroy
has_many :followers,
:through => :followee_follower_rel,
:source => :follower
Change is found @
:follower_followee_rel, :foreign_key=>'followee_id'
and
:followee_follower_rel, :foreign_key=>'followee_id'
精彩评论