Менеджер -> Объединение сотрудников одного уровня в рельсах - PullRequest
0 голосов
/ 15 октября 2019

Я хочу создать менеджер-> объединение сотрудников.

  • Менеджер имеет много сотрудников
  • Сотрудник принадлежит только одному менеджеру
  • Менеджер не имеет другого менеджера

Как реализовать этот дизайн? Я создал что-то более близкое (код ниже), но у моего менеджера по дизайну может быть другой менеджер.

class User < ApplicationRecord
  has_many :employee, class_name: "User", foreign_key: "manager_id"
  belongs_to :manager, class_name: "User", foreign_key: "manager_id"
end

Любая помощь высоко ценится!

Ответы [ 2 ]

1 голос
/ 16 октября 2019

То, что у вас есть, - это действительно стандартная самосоединяющаяся установка (с несколькими небольшими проблемами). Вы можете ограничить глубину дерева, просто добавив пользовательскую проверку:

class User < ApplicationRecord
  # optional: true is needed in Rails 5+ since belongs_to is no
  # longer optional by default
  belongs_to :manager, class_name: 'User',
                       optional: true
  # pay attention to pluralization
  has_many :employees, class_name: 'User',
                       foreign_key: 'manager_id'
  # calls the custom validation we will define later
  validate :manager_must_be_a_manager, unless: :manager?

  def manager?
    manager.nil?
  end

  private
    # our custom validation method
    def manager_must_be_a_manager
      errors.add(:manager, 'is not a manager') unless manager.manager?
    end
end

Так что теперь, если мы запустим:

user_1 = User.create!
user_2 = User.create!(manager: user_1)
User.create!(manager: user_2)

Третья строка повысит ActiveRecord::RecordInvalid: Validation failed: Manager is not a manager.

1 голос
/ 15 октября 2019

Я думаю, что лучше иметь еще одно поле manager: boolean в вашей таблице. На основе этого поля вы можете решить, является ли пользователь менеджером или нет. Также вы можете добавить проверки, что manager_id должен быть пустым, если поле менеджера имеет значение true.

validate :manager_id_blank_for_manager

has_many :employees, class_name: "User", foreign_key: "manager_id", dependent: :restrict_with_exception

scope :managers, ->{ where(manager: true) }

def manager?
  manager
end

private

def manager_id_blank_for_manager
  if manager_id.present? && manager?
    errors.add(:manager_id, :must_be_blank_for_manager) # Move this error to yml file
  end
end
...