当前位置:  开发笔记 > 数据库 > 正文

模型设计:用户有朋友是用户

如何解决《模型设计:用户有朋友是用户》经验,为你挑选了2个好方法。

我想在追求这种关联之前确保我的方法是正确的.实施听起来太复杂了,所以我认为我的计划肯定有问题.我正在使用结构化(SQL)数据存储,符合rails存储约定.我所拥有的是用户模型,它在模式中有一个电子邮件地址password_digest和名称.

class User < ActiveRecord::Base
  has_many :posts
end

我想实现has_many与朋友集合的关联,以便用户可以belong_to用户(作为朋友).我希望能够User.last.friends.last在正确构建和填充后返回User对象.

我相信我可以为这个协会创建一个模型,如:

Class Friend < ActiveRecord::Base
  belongs_to :user
  belongs_to :friendlies, class: 'User'
end
Class User < ActiveRecord::Base
  has_many :posts
  has_many :friends
  has_many :friendly, class: 'Friend'
end

但我认为这需要我添加一个关于模型和查询使用User.last.friends.last.user 所以我在想的是这是一种has_and_belongs_to_many关系.我可以逃脱以下(或类似的东西):

class User < ActiveRecord::Base
  has_and_belongs_to_many :friends, class: 'User'
end

我发现了这个:

class User < ActiveRecord::Base
  has_many :user_friendships
  has_many :friends, through: :user_friendships


class UserFriendship < ActiveRecord::Base
  belongs_to :user
  belongs_to :friend, class_name: 'User', foreign_key: 'friend_id'

而这(自称"标准"):

has_many :friendships, :dependent => :destroy
has_many :friends, :through => :friendships, :dependent => :destroy
has_many :inverse_friendships, :class_name => "Friendship", :foreign_key => "friend_id", :dependent => :destroy
has_many :inverse_friends, :through => :inverse_friendships, :source => :user, :dependent => :destroy

我假设需要一个Friendship模型.我觉得我不需要友谊模特.我认为该class UserFriendship方法看起来正确,但它需要一个额外的模型.现在进入问题:

    我可以has_and_belongs_to_many与将用户与用户的朋友关联的表格建立关系,而不会产生额外的模型吗?

    是否有额外的模型"以防万一"以后出现额外的要求?

Richard Peck.. 7

你正在寻找的东西叫做a self referential join,这意味着你可以model用不同的关联来引用它:

#app/models/user.rb
class User < ActiveRecord::Base
   has_and_belongs_to_many :friendships,
      class_name: "User", 
      join_table:  :friendships, 
      foreign_key: :user_id, 
      association_foreign_key: :friend_user_id
end

您必须创建一个habtm连接表以获得引用:

$ rails g migration CreateFriendshipsTable

#db/migrate/create_friendships_table____.rb
class CreateFriendShipsTable < ActiveRecord::Migration
   def change
      create_table :friendships, id: false do |t|
        t.integer :user_id
        t.integer :friend_user_id
      end

      add_index(:friendships, [:user_id, :friend_user_id], :unique => true)
      add_index(:friendships, [:friend_user_id, :user_id], :unique => true)
   end
end

$ rake db:migrate

这里有一个很好的参考:Rails:has_and_belongs_to_many的自加入方案?


是否有额外的模型"以防万一"以后出现额外的要求?

只有当你知道你将拥有额外的属性时.如果没有,你可以habtm随心所欲地逃脱.



1> Richard Peck..:

你正在寻找的东西叫做a self referential join,这意味着你可以model用不同的关联来引用它:

#app/models/user.rb
class User < ActiveRecord::Base
   has_and_belongs_to_many :friendships,
      class_name: "User", 
      join_table:  :friendships, 
      foreign_key: :user_id, 
      association_foreign_key: :friend_user_id
end

您必须创建一个habtm连接表以获得引用:

$ rails g migration CreateFriendshipsTable

#db/migrate/create_friendships_table____.rb
class CreateFriendShipsTable < ActiveRecord::Migration
   def change
      create_table :friendships, id: false do |t|
        t.integer :user_id
        t.integer :friend_user_id
      end

      add_index(:friendships, [:user_id, :friend_user_id], :unique => true)
      add_index(:friendships, [:friend_user_id, :user_id], :unique => true)
   end
end

$ rake db:migrate

这里有一个很好的参考:Rails:has_and_belongs_to_many的自加入方案?


是否有额外的模型"以防万一"以后出现额外的要求?

只有当你知道你将拥有额外的属性时.如果没有,你可以habtm随心所欲地逃脱.



2> 小智..:

你可以试试这个

--friendship.rb

class Friendship < ApplicationRecord
  belongs_to :user
  belongs_to :friend, :class_name => 'User'
end

--user.rb

class User < ApplicationRecord
  has_many :friendships
  has_many :friends, through: :friendships
end

--db migrate xxxx_create_friendship.rb

class CreateFriendships < ActiveRecord::Migration[5.0]
  def change
    create_table :friendships do |t|
      t.belongs_to :user
      t.belongs_to :friend, class: 'User'
      t.timestamps
    end
  end
end

推荐阅读
喜生-Da
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有