我想知道我是否在正确的轨道上,并且轨道是否允许这类事情。
User
在Role
中有一个Network
。即“吉姆”是“学校”的“历史老师”。
Role
同时具有位置(权力)和名称(标签)。 “Jim”是“历史老师”(标签),但拥有会员或管理员,主管或其他任何人(权力)的权力。
根据Role
User
,Events
可以查看Network
中的所有User
,无论他/她是否创建了它们。即如果“吉姆”是“校长”(管理员),“吉姆”可以看到“南希”的“休息计划”,但如果“吉姆”是“历史老师”(会员)则不能看到。“
Event
在Role
内创建Network
作为Event
。即“吉姆”在“学校”创建“课程计划”作为“历史教师”。
Network
永远与特定Role
相关联,目前与Event
相关联。
如果User
替换User
中的其他Role
,新User
可以访问Event
,我希望Event
保持不变}。即“汤姆”将“吉姆”替换为“历史教师”,并且可以修改“课程计划”,因为他是“历史教师”。 “吉姆”无法再访问“课程计划”。
但如果User
没有附加Role
,我还希望Role
能够继续存在。即“汤姆”被解雇并且没有当前替换,管理员仍然可以看到“课程计划”。
最后,如果Event
被删除,Network
仍然存在,与Role
User
连接,而不是User
。
模型如下,我使用CanCan进行授权,这些是我的问题:
User
,还是需要创建一些通用的“无”Event
或“所有人”Role
? Event
可以Role
错过Network
吗? (可以belongs_to为null吗?)User
与Role
和Events
连接起来是好还是坏?有更好的方法吗?Network
根据他/她Role
可以看到更多活动,那么他们在Network
或class User < ActiveRecord::Base
has_many :roles
has_many :networks, :through => :roles
has_many :events, :through => :network
# I would use CanCan to determine the authorization of
# what network events they can see based on their role?
end
中有多少class Network < ActiveRecord::Base
has_many :roles
has_many :users, :through => :roles
has_many :events
# it shouldn't have this through roles right?
# because a role can be deleted
end
?我正在考虑class Role < ActiveRecord::Base
belongs_to :user #CAN THIS BE NULL?
belongs_to :network
end
,而Ability.rb会限制它。User.rb
class Event < ActiveRecord::Base
belongs_to :role #Can this be null?
belongs to :network
# Does it belong to the network through the role,
# or can it belong on its own, in case the role is deleted?
# belongs_to :user, :through => :roles
# Is this necessary if I am using CanCan
# to determine if a User can reach the event?
end
Network.rb
if user
user.roles.each do |role|
can :manage, Event, :role_id => role.id
if role.position == "admin" || role.position == "manager"
can :manage, Event, :network_id => role.network_id
elseif role.position == "supervisor"
can :read, Event, :network_id => role.network_id
end
end
end
Role.rb
{{1}}
Event.rb
{{1}}
Ability.rb
{{1}}
答案 0 :(得分:3)
您的关联很好,您可以拥有空belongs_to
个字段。默认情况下,Rails不会在数据库上创建外键约束。就CanCan设置而言,我会做类似的事情:
class Ability
include CanCan::Ability
def initialize(user)
#Adding can rules do not override prior rules, but instead are logically or'ed.
#See: https://github.com/ryanb/cancan/wiki/Ability-Precedence
#Anything that you can pass to a hash of conditions in Active Record will work here.
#The only exception is working with model ids.
#You can't pass in the model objects directly, you must pass in the ids.
#can :manage, Project, :group => { :id => user.group_ids }
#See https://github.com/ryanb/cancan/wiki/Defining-Abilities
can :read, Event, network: {id: user.supervises_network_ids}
can :manage, Event, role: {id: user.role_ids}
can :manage, Event, network: {id: user.manages_network_ids + user.admins_network_ids}
end
end
你在哪里:
class User < ActiveRecord::Base
#...
def manages_network_ids
@manages_network_ids ||= roles.manager.collect &:network_id
end
def admins_network_ids
@admins_network_ids ||= roles.admin.collect &:network_id
end
def supervises_network_ids
@supervises_network_ids ||= roles.supervisor.collect &:network_id
end
#...
end
关于角色你有:
class Role < ActiveRecord::Base
#...
scope :manager, where(position: "manager")
scope :admin, where(position: "admin")
scope :supervisor, where(position: "supervisor")
#...
end
这允许您的事件为空role_id
,因为您将允许网络上的任何管理员(或管理员)管理受network_id
约束的所有事件。此外,如果您将角色重新分配给新用户,则旧用户将无法再管理该事件,而新用户将无法管理该事件。
答案 1 :(得分:0)
要回答您的第一个问题,belongs_to
技术上可以nil
。您必须进行验证(validates_presence_of
)以避免这种情况。
我不知道CanCan 但是,从概念层面来说,我不会为了能够访问数据而写出这么多关联。 Rails协会不仅仅是一个数据阅读器,我不确定你是否在这里需要它。
例如,用户#事件可以替换为:
def events
roles.includes(:events).map(&:events).flatten
end
或者
def events
Event.where(:role_id => roles.map(&:id))
end
或者
def events
Event.joins(:role).where(:role => {:user_id => id})
end
如果多次调用此方法,可以添加一些memoization。 事实上,如果你只召唤一次,你几乎不需要一种方法。
关于将事件与角色和网络相关联,我会小心,因为您可能存在一致性问题(您必须确保event.role.network == event.network
)。另一种方法是为每个网络提供一个无法销毁的默认角色。但它可能并不简单。