开发者

Only one side of join table being saved?

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'

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜