2

2 種類の管理者ユーザーがいます

  1. スーパー管理者
  2. 機関管理者

cancan を使用して次のことを行います。

スーパー管理者は、インスティテューション管理者/別のスーパー管理者、およびインスティテューションに関連する通常のユーザーを作成でき、関心の種類、目標などの他のすべてのものを管理できます。また、スーパー管理者は、システムで作成されたすべてのユーザーを見ることができます。

機関管理者は、機関に関連するユーザーのみを作成でき、その機関に関連するユーザーのみを表示できます。

したがって、1つのことがない限り、すべてが正常に機能します。機関管理者でログインし、ページに移動して新しいユーザーを作成すると、次のエラーが表示されます。

ActiveRecord::HasManyThroughNestedAssociationsAreReadonly in Admin::UsersController#new 
Cannot modify association 'AdminUser#users' because it goes through more than one other association.

モデル/admin_user.rb

class AdminUser < ActiveRecord::Base

  belongs_to :institution
  has_many :profiles, :through => :institution
  has_many :users, :through => :profiles

  devise :database_authenticatable, 
         :recoverable, :rememberable, :trackable, :validatable

  def password_required?
    new_record? ? false : super
  end

  def all_users
    if role == "super_admin"
     User.unscoped
    else
     #may be below line of code has issue.
     users       
    end
  end
 end

models/ability.rb

class Ability
  include CanCan::Ability

  def initialize(current_admin_user)
    # Define abilities for the passed in user here. For example:

    current_admin_user ||= AdminUser.new # guest user (not logged in)

    case current_admin_user.role
    when "super_admin"  
      can :manage, :all  
    when "institution_admin"
      can :manage, User, :profile => {:institution_id => current_admin_user.institution_id}
      can :manage, InterestType, :institution_id => current_admin_user.institution_id 
    end
    end
   end

コントローラー/users_controller.rb

 class UsersController < ApplicationController
      layout "home"
      skip_before_filter :require_login, :only => [:new, :create, :activate]

      def new
        @user = User.new
        @user.build_profile
      end

      def create
        @user = User.new(params[:user])
        if @user.save
           redirect_to home_path, :notice => "Please check email."
        else
           render :new, :alert => @user.errors
        end
      end
    end

admin/admin_users.rb

ActiveAdmin.register AdminUser do

  menu :if => proc{ can?(:manage, AdminUser) }        controller.authorize_resource 

  index do
    column :email
    column ("Role") {|admin_user| admin_user.role == "super_admin" ? "Administrator" : "Institution Administrator" }  
    column ("Instituion") { |admin_user| admin_user.institution.name unless admin_user.institution_id.nil? }
    column :current_sign_in_at
    column :last_sign_in_at
    column :sign_in_count
    default_actions   end

  #...   form do |f|
    f.inputs "Admin Details" do
      f.input :email
      f.input :role, :as => :select, :include_blank => false, :collection => Hash[ "Institution Administrator", "institution_admin", "Administrator", "super_admin"]
      f.input :institution_id, :as => :select, :include_blank => false, :collection => Institution.all.map{ |ins| [ins.name, ins.id] }
    end
      f.buttons   end

  after_create { |admin| admin.send_reset_password_instructions unless admin.email.blank? and admin.institution_id.blank? }
    def password_required?
    new_record? ? false : super   end

end

admin/users.rb

ActiveAdmin.register User do

  menu :if => proc{ can?(:manage, User) }     
  controller.authorize_resource 
  scope_to :current_admin_user, :association_method => :all_users

  index do

    column :username
    column :email
    column ("Instituion") { |user| user.profile.institution.name }
    column :activation_state
    column("Name" ) {|user| user.profile.users_firstname + " " + user.profile.users_lastname}
    column :created_at
  end

  form do |f|

    f.inputs "User Details" do
      f.input :username
      f.input :email
      if f.object.id.nil?
          f.input :password
          f.input :password_confirmation
      end
    end

    f.inputs "Profile Details", :for => [:profile, f.object.profile || Profile.new] do |profile_form|
      profile_form.input :users_firstname
      profile_form.input :users_lastname
      profile_form.input :users_telephone
      profile_form.input :class_year, :collection => 1995..2020,  :selected => Time.now.year
      if current_admin_user.role == "super_admin"
        profile_form.input :institution_id, :as => :select, :include_blank => false, :collection => Institution.all.map{ |ins| [ins.name, ins.id] }
      elsif current_admin_user.role == "institution_admin"
        profile_form.input :institution_id, :as => :hidden, :value => current_admin_user.institution_id
      end
    end

    f.buttons
  end


end

注: admin_users.rb の def all_users を users から User.scoped に編集すると、機関ユーザーから新しいユーザーを作成できますが、インデックス ページでは (機関のユーザーのみではなく) すべてのユーザーを表示できます。

4

1 に答える 1

1

users次のように行を変更することで、エラーを修正できますall_users

User.joins(:profile => :institution).where(["#{Institution.table_name}.id = ?", institution.id])

これは新しいユーザーにプロファイルを設定しないため、機関を割り当てるのと同じ方法でフォームにプロファイルを割り当てる必要があります。また、プロファイルと教育機関の間に双方向の関連付けが存在することを確認する必要があります。

エラーが発生した理由は、ActiveRecordでは、関連付けによってネストされたhas_manyから新しいレコードを作成できないためです。私たちは、has_manyを経由せずに、同じ関連付けの結果を取得することでこれを回避しています。クエリは、「プロファイルの一部であるすべてのユーザーを取得します。これは、機関のIDであり、機関のIDは現在のユーザーの機関のIDと同じです」と言うのと同じです。

于 2012-07-10T08:05:34.807 に答える