almost 5 years ago

系统中有一个 User 模型,要求用户之间需要存在一个朋友关系,即:每个人有可以拥有多个朋友:

current_user.friends.push << user1 << user2

步骤:

  1. 首先创建一个用于存储朋友关系的表:

    class CreateFriendships < ActiveRecord::Migration
    def change
    create_table :friendships do |t|
      t.references :friend, index: true
      t.references :person, index: true
    
      t.timestamps
    end
    end
    end
    
  2. 修改 User 模型:

    class User < ActiveRecord::Base
    has_many :friendships
    has_many :friends, :through => :friendships
    end
    
  3. 添加 Friendship 模型:

    class Friendship < ActiveRecord::Base
    belongs_to :user
    belongs_to :friend, :foreign_key => :friend_id, :class_name => :User
    end
    

    实际上,步骤 23 还可以简化为:

    class User < ActiveRecord::Base
    has_and_belongs_to_many :friends, :class_name => :User, :join_table => "friendships",
                                :association_foreign_key => :friend_id
    end
    

到目前为止已经可以实现了在用户之间建立朋友关系,但是上面实现的这个关联是单方向的:当把张三设置为李四的朋友(lisi.friends << zhangsan)之后,李四并不会出现在张三的朋友集合(zhangsan.friends)中,我没有找到能很好地实现此种需求的关联设置方案,但是从 RailsCasts(见下面参考部分的链接)里找到一个替代方案。实施方法如下:

修改 User 模型如下即可:

class User < ActiveRecord::Base
    has_many :friendships
  has_many :friends, :through => :firendships
  has_many :inverse_friendships, :class_name => :Friendships, :foreign_key => :friend_id
  has_many :inverse_friends, :through => :inverse_friendships, :source => :user
end

此时,当将张三添加到李四的朋友集合中(lisi.friends << zhangsan)后,那么李四就会出现 zhangsan.inverse_friends 集合中

参考:

← 从一个几十GB上百GB的日志文件中过滤所关心的错误信息 has_many 的 :dependent 选项和 delete/destroy/clear 方法 →
 
comments powered by Disqus