模型设计:用户有朋友是用户
Model design: Users have friends which are users
我想确保我的方法是正确的,然后再追求这个协会。实现听起来太复杂了,所以我认为我的计划一定有问题。我正在使用符合 rails 存储约定的结构化 (SQL) 数据存储。我有一个用户模型,它有一个电子邮件地址,password_digest
,和架构中的名称。
class User < ActiveRecord::Base
has_many :posts
end
我想实现与朋友集合的 has_many
关联,以便用户可以 belong_to
用户(作为朋友)。我希望在正确构建和填充后能够拥有 User.last.friends.last
return 用户对象。
我相信我可以为这个协会创建一个模型,例如:
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
我找到了 this:
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'
和this(自称'standard'):
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
方法看起来不错,但它需要一个额外的模型。现在进入问题:
我能否与 table 建立 has_and_belongs_to_many
关系,将用户与作为用户的朋友联系起来,而无需额外的模型?
以后再弹出一个额外的模型是否谨慎 'in case' 额外的要求?
您要找的是一个叫做 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
连接 table 才能获得参考:
$ 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: self join scheme with has_and_belongs_to_many?
Is it prudent to have an additional model 'in case' additional requirements pop up later?
只有当您知道时,您才会拥有额外的属性。如果没有,您可以随心所欲地使用 habtm
。
Rich 的回答是极好的资源。我按照这个约定成功地颠覆了几个步骤:
# app/model/user.rb
has_and_belongs_to_many :friends,
class_name: "User",
join_table: :friends_users,
foreign_key: :user_id,
association_foreign_key: :friend_id
此迁移已足够(无需修改生成的代码):
rails g migration CreateFriendlyJoinTable users friends
使用 rails generate migration -h
找到了 JoinTable 语法
你可以试试这个
--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 迁移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
我想确保我的方法是正确的,然后再追求这个协会。实现听起来太复杂了,所以我认为我的计划一定有问题。我正在使用符合 rails 存储约定的结构化 (SQL) 数据存储。我有一个用户模型,它有一个电子邮件地址,password_digest
,和架构中的名称。
class User < ActiveRecord::Base
has_many :posts
end
我想实现与朋友集合的 has_many
关联,以便用户可以 belong_to
用户(作为朋友)。我希望在正确构建和填充后能够拥有 User.last.friends.last
return 用户对象。
我相信我可以为这个协会创建一个模型,例如:
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
我找到了 this:
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'
和this(自称'standard'):
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
方法看起来不错,但它需要一个额外的模型。现在进入问题:
我能否与 table 建立
has_and_belongs_to_many
关系,将用户与作为用户的朋友联系起来,而无需额外的模型?以后再弹出一个额外的模型是否谨慎 'in case' 额外的要求?
您要找的是一个叫做 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
连接 table 才能获得参考:
$ 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: self join scheme with has_and_belongs_to_many?
Is it prudent to have an additional model 'in case' additional requirements pop up later?
只有当您知道时,您才会拥有额外的属性。如果没有,您可以随心所欲地使用 habtm
。
Rich 的回答是极好的资源。我按照这个约定成功地颠覆了几个步骤:
# app/model/user.rb
has_and_belongs_to_many :friends,
class_name: "User",
join_table: :friends_users,
foreign_key: :user_id,
association_foreign_key: :friend_id
此迁移已足够(无需修改生成的代码):
rails g migration CreateFriendlyJoinTable users friends
使用 rails generate migration -h
你可以试试这个
--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 迁移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