1

私が正しい方向に進んでいるかどうか、そしてrailsがこの種のことを可能にするかどうかを知りたいです。

Userに1つRoleありNetworkます。つまり、「ジム」は「学校」の「歴史教師」です。

ARoleには、位置(パワー)と名前(ラベル)の両方があります。「ジム」は「歴史教師」(ラベル)ですが、メンバー、管理者、スーパーバイザー、またはその他(権限)の権限を持っています。

それに応じて、Role彼/彼女がそれらを作成したかどうかでUserすべてを見ることができます。つまり、「ジム」は「校長」(管理者)の場合は「ナンシー」の「休憩プラン」を見ることができますが、「ジム」が「歴史教師」(メンバー)の場合は見ることができません。EventsNetwork

Aは、内にとしてUserを作成します。つまり、「ジム」は「学校」で「歴史教師」として「教案」を作成します。EventRoleNetwork

EventNetworkその特定の、そして現在そのに永遠に接続されていRoleます。

その中の別のものを置き換えEventても、それを持続させたいのですが、新しいものはそれにアクセスできます。つまり、「トム」は「歴史の先生」として「ジム」を置き換え、「歴史の先生」であるため「教案」を変更することができます。「ジム」は「レッスンプラン」にアクセスできなくなりました。UserUserRoleUserEvent

ただし、にアタッチされていEventない場合は、を保持する必要もあります。つまり、「トム」が解雇され、現在の代替はありません。管理者は引き続き「レッスンプラン」を見ることができます。UserRole

最後に、それRoleが削除された場合でも、。なしでEvent接続されたまま存在します。NetworkRole

モデルは以下のとおりです。承認にCanCanを使用しています。これらは、私の質問です。

  1. 役割にが欠けている可能User性がありますか、それとも一般的な「なし」Userまたは「全員」を作成する必要がありますかUser?そしてEvent、欠落している可能性がありRoleますか?(belongs_toをnullにすることはできますか?)
  2. をaとaのEvent両方に接続するのは良い/悪い設計ですか?これを行うためのより良い方法はありますか?RoleNetwork
  3. User彼/彼女に応じてより多くのイベントを見ることができる場合、彼らはまたは彼らを通してRole多くを持っていますか?私は熟考していて、Ability.rbがそれを制限するでしょう。EventsNetworkRoleNetwork

User.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

Network.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

Role.rb

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

Event.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

Ability.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関連付けは問題なく、nullフィールドを使用できます。デフォルトでは、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これにより、ネットワーク上のすべての管理者 (またはマネージャー) がすべてのイベントを管理できるようになるため、Event に null を設定できますnetwork_id。また、ロールを新しいユーザーに再割り当てすると、古いユーザーはイベントを管理できなくなり、新しいユーザーが管理できます。

于 2012-12-06T16:05:54.143 に答える
0

あなたの最初の質問に答えるbelongs_toことは技術的にすることができますnilvalidates_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)。もう1つの方法は、ネットワークごとに、破棄できないデフォルトの役割を設定することです。しかし、それはそれほど単純ではないかもしれません。

于 2012-12-05T15:33:31.243 に答える