1

我想知道我是否走在正确的轨道上,以及rails是否允许这种事情。

UserRole一个Network。即“吉姆”是“学校”的“历史老师”。

ARole既有位置(权力),也有名称(标签)。“Jim”是“历史老师”(标签),但具有成员或管理员、主管或其他任何(权力)的权限。

这取决于他/她是否创建了Role它们。即,如果“Jim”是“校长”(管理员),“Jim”可以看到“Nancy's”的“Recess Plan”,但如果“Jim”是“历史老师”(成员)则不能。UserEventsNetwork

A在 a 中User创建 aEvent作为Rolea Network。即“吉姆”在“学校”作为“历史老师”创建“课程计划”。

Event永远连接到那个特定的Network并且当前连接到那个Role

Event如果 aUser替换了另一个User,我希望它能够持续存在Role,并且 newUser可以访问它Event。即“汤姆”代替“吉姆”成为“历史老师”,并且可以修改“课程计划”,因为他是“历史老师”。“Jim”无法再访问“课程计划”。

Event但是如果没有User附加到 a ,我也希望 a坚持下去Role。即“汤姆”被解雇并且当前没有替换,管理员仍然可以看到“课程计划”。

最后,如果它Role被删除,它Event仍然存在,因为它与Network没有Role.

模型如下,我正在使用 CanCan 进行授权,这些是我的问题:

  1. 一个角色可以缺少一个User,还是我需要创建一些通用的“无”User或“每个人” User?并且可以Event缺少一个Role?(belongs_to 可以为空吗?)
  2. 将 a连接Event到 aRole和 a是好还是坏的设计Network?有一个更好的方法吗?
  3. 如果一个User可以根据他/她看到更多事件,Role他们是否有很多Events通过Network或他们的Role?我正在考虑Network,Ability.rb 会限制它。

用户.rb

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

网络.rb

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

角色.rb

class Role < ActiveRecord::Base
  belongs_to :user     #CAN THIS BE NULL?
  belongs_to :network
end

事件.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

能力.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
4

2 回答 2

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

这允许您的 Event 具有 null role_id,因为您将允许网络上的任何管理员(或经理)管理所有事件,受network_id. 此外,如果您将角色重新分配给新用户,旧用户将无法再管理活动,而新用户可以。

于 2012-12-06T16:05:54.143 回答
0

要回答你的第一个问题belongs_to,技术上可以nil。您必须使用验证 ( validates_presence_of) 来避免这种情况。

我不知道 CanCan,但在概念层面上,我不会写这么多关联只是为了能够访问数据。Rails 关联不仅仅是一个数据读取器,我不确定您是否需要它。

例如,User#events 可以替换为:

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

如果您多次调用此方法,您可以添加一些记忆。事实上,如果你只调用一次,你几乎不需要一个方法。

关于将事件与角色和网络相关联,我会小心,因为您可能有一致性问题(您必须确保event.role.network == event.network)。另一种方法是为每个网络设置一个不能被破坏的默认角色。但这可能并不简单。

于 2012-12-05T15:33:31.243 回答