![](/img/trans.png)
[英]Rails ActiveRecord relationships for has_and_belongs_to_many
[英]Activerecord has_and_belongs_to_many with nested groups
我需要將用戶組存儲在其他組中,例如Windows Active Directory。
我有以下工作原理
ActiveRecord::Schema.define do
create_table :users do |table|
table.column :name, :string
end
create_table :groups do |table|
table.column :name, :string
end
create_join_table :users, :groups do |t|
end
end
class User < ActiveRecord::Base
has_and_belongs_to_many :groups
end
class Group < ActiveRecord::Base
has_and_belongs_to_many :users
# has_and_belongs_to_many :groups
end
peter = User.create(id: 1, Name: 'Peter')
thomas = User.create(id: 2, Name: 'Thomas')
inf = Group.create(id: 1, Name: 'Informatics')
peter.groups << inf
inf.users << thomas
p User.find_by(Name: 'Peter').groups
p Group.find_by(Name: 'Informatics').users
但我也想做以下事情
sm = Group.create(id: 2, Name: 'System')
inf.groups << sm
這樣做的最簡單方法是什么?
您可以通過在Group
模型中使用自引用關系來完成此操作。 這是表中的記錄可能指向同一表中其他記錄的地方。
基本上,主要組的parent_id
將為NULL
,子組的parent_id
設置為其父組的列ID。
組型號:
has_many :users
has_many :sub_groups, class_name: "Group", foreign_key: :parent_id
has_many :sub_group_users, through: :sub_groups, source: :users
belongs_to :parent, class_name: 'Group', foreign_key: :parent_id, optional: true
# This is a scope to load the top level groups and eager-load their users, sub-groups, and the sub-groups' users too.
scope :top_level, -> { where(parent_id: nil).includes :users, sub_groups: :users}
組控制器:
def show
@group = Group.find(params[:id])
@category = @group.parent
@users = @group.users
@sub_group = @group.sub_groups.first
unless @sub_group.nil?
@relatives = @group.sub_group_users
end
end
private
def cat_params
params.require(:group).permit(:name, :parent_id, :sub_group)
end
def main_group
@group = Group.parent_id.nil?
end
在您的groups
表中,添加以下列: t.integer "parent_id"
在users
表中,添加以下列: t.integer "group_id"
您還需要將:group_id
添加到user_params
中(在用戶控制器中)。
用戶模型: belongs_to :group
在您的組顯示視圖中:
<% if @category %>
<% @users.each do |user| %>
<% end %>
<% else %>
<% @relatives&.each do |user| %>
<% end %>
<% end %>
我將帶有Jake解決方案的attemtp放在一個單獨的答案中,以使其與原始版本區分開來,並使僅對該解決方案進行評論和編輯成為可能。 我無意接受此作為答案! 另外,我將整個腳本放在這里,以便人們可以立即進行測試。 該解決方案僅使用2個表,而不是原來的3個表,這很好,但是還不完整,請參閱代碼末尾的說明。
require 'active_record'
require 'logger'
ActiveRecord::Base.establish_connection(
:adapter => "sqlite3",
:database => ":memory:"
)
ActiveRecord::Schema.define do
create_table :users do |table|
table.column :name, :string
table.column :group_id, :integer
end
create_table :groups do |table|
table.column :name, :string
table.column :user_id, :integer
table.column :parent_id, :integer
end
end
class User < ActiveRecord::Base
belongs_to :group
has_many :groups
end
class Group < ActiveRecord::Base
has_many :users
has_many :sub_groups, class_name: "Group", foreign_key: :parent_id
has_many :sub_group_users, through: :sub_groups, source: :users
belongs_to :parent, class_name: 'Group', foreign_key: :parent_id, optional: true
# This is a scope to load the top level groups and eager-load their users, sub-groups, and the sub-groups' users too.
scope :top_level, -> { where(parent_id: nil).includes :users, sub_groups: :users}
end
peter = User.create(id: 1, name: 'Peter')
thomas = User.create(id: 2, name: 'Thomas')
erika = User.create(id: 3, name: 'Erika')
inf = Group.create(id: 1, name: 'Informatics')
devs = Group.create(id: 2, name: 'Devs')
log = Group.create(id: 3, name: 'Logistics')
# peter.groups << inf # doesn't work
devs.users << thomas
devs.users << peter
inf.users << erika
# expect inf.groups << devs to work
inf.sub_groups << devs
# doesn't work
p peter.groups #<ActiveRecord::Associations::CollectionProxy []>
# only gives users added straight to the group
p inf.users #<ActiveRecord::Associations::CollectionProxy [#<User id: 3, name: "Erika", group_id: 1>]>
# this should be added to inf.users
p inf.sub_group_users
#<ActiveRecord::Associations::CollectionProxy [#<User id: 1, name: "Peter", group_id: 2>, #<User id: 2, name: "Thomas", group_id: 2>]>
# works
p Group.top_level
#<ActiveRecord::Relation [#<Group id: 1, name: "Informatics", user_id: nil, parent_id: nil>]>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.