3

我试图弄清楚如何构建这个请帮助:我需要用户能够注册为雇主或雇员。雇主基本上是公司,雇员是从事该工作的人。我想知道如何记录员工何时/是否被雇用和终止工作。协会会has_many:through为此工作还是更好,但是否有一个我忽略的宝石可以帮助我解决这个问题?

4

4 回答 4

7

这是分层对象模型的经典案例,因此您必须根据所涉及的对象及其相互关系来考虑这个问题。想想企业在现实生活中的运作方式:

雇主 -> 雇员不是雇主 -> 经理等 -> 雇员

这种系统模型的一个很好的例子是 GitHub。在 GitHub 上,用户可以属于组织。他们还可以创建并管理它们,管理成员等(在您的情况下雇用和解雇)。因此,一个更好的建模这个系统的方法是让它以用户为中心,而不是分成两个不同的用户类别。

如前一个答案所述,不应将雇主(或这种意义上的企业)视为系统的用户,因为他们不会对程序的状态采取行动,用户会。因此,我个人认为 STI 对于这个系统模型来说有点矫枉过正。

所以...

企业中雇用的所有人员都是员工,但并非所有员工都具有相同级别的权限(例如,经理将比初级员工拥有更多权限)。因此,您应该建模 a Business,它有很多 Employees。这些Employees 将根据其职位具有不同级别的权限:

  • 可以雇用吗?
  • 可以开火吗?
  • 等等

您还可以创建一个方法来告诉您何时Employee雇用/解雇。如果他们被雇用/解雇或nil没有,这些可能会返回日期/时间。nil从这个意义上说,显然意味着他们还没有被雇用/解雇。

在管理不同用户的能力时,他们的权限级别由他们可以做什么和不能做什么来定义。您当然可以通过检查上述方法的简单方法将预设角色应用于这种情况。例如:

def manager?
  self.can_hire? and self.can_fire?
end

然后,您还可以定义允许创建业务的能力:

def can_create_business?
  self.manager?
end

注意:您可以使用范围来优雅地实现这一点。

您还可以为您的角色子类化一个基本用户模型,或者创建一个定义上述方法并作用于给定用户模型的角色类。然后,您可以创建单个角色和角色子集。

可以说,在某些情况下,允许将雇主/企业和雇员创建为可以对项目状态采取行动的独立实体是有用的。如果它Business可以执行的不仅仅是简单的管理功能,那么这可能是值得的。在这种情况下,我仍然不会将业务视为用户模型。我需要创建一个特殊的用户帐户以及具有Business角色Business Administrator或类似角色的用户帐户。

这个模型总体上遵循编程和计算机科学中的一些最基本的原则,所以我希望它能对你的问题有所帮助。当然,有许多可用的 gem 内置了这个功能,即DeviseCanCan/CanTango,尽管我会亲自构建这个系统。

于 2012-07-10T03:31:04.897 回答
2

我想我会将 STI 与有很多通过关系结合起来。

我将首先创建一个 Employers 和 Employees 的单表继承。

class User < ActiveRecord::Base
  ...
end

class Employer < User
end

class Employee < User
end

雇主雇用雇员。一个雇主可以拥有许多雇员,并且随着就业而来的是其他相关属性,例如date_of_hire, designation, status,manager_iddepartment。因此我会将其建模为一个单独的对象,因此将此信息存储在一个单独的表中。让我们这样称呼,Employment好吗?

rails g model employment employer_id:integer, employee_id:integer, date_of_hire:date, designation:string, status:string, manager_id:integer

现在让我们建立关系。

class Employment < ActiveRecord::Base
  belongs_to :employer # Foreign key options should not required because of User STI
  belongs_to :employee
  belongs_to :manager,  :foreign_key => :manager_id,  :class_name => "User"
end

class Employee < User
  has_many :employments
  has_many :employers
  has_one  :manager,      :through     => :employments, :foreign_key => :manager_id
end

class Employer < User
  has_many :employments, :foreign_key => :employer_id
  has_many :employees,   :through     => :employments
end

基于业务规则,我们可以实现优雅的范围。

class Employee < User
  ...
  scope :fired, :where => {:status => 'fired'}
  scope :recently_joined, :where => {:date_of_hire => 3.months.ago...Date.today}
  scope :developers, :where => {:designation => 'developer'}
  ... 
end

和...

Employee.recently_joined
Employee.recently_joined.developers
Employee.fired

请理解,这显然不是经过测试的代码,可能存在一些故障。

然而!

我强烈建议您重新考虑将雇主建模为用户的需求。从我个人的经验来看,结果证明是未来的灾难(可能是我当时没有经验,但我不会再走那条路了)。我真的会为 Employer 和 Employee 建立单独的模型,并建立如上所述的关系,但使用 foreign_key 和 class_name 属性。主要原因是 STI 要在您的域中工作,雇主和雇员应该与用户具有“IS A”关系。您可能会认为这是一个“IS A”关系,但也认为它是否与“IS A”关系的“TYPE”相同。在我处理的应用程序中,它没有任何意义,但我们还是选择了 STI。雇主有完全不同的特征,员工在申请中的身份和待遇。尽管两者都有一些相同的数据,但它们的存在目的不同,用途也不同。这足以(单一职责)对它们进行单独建模。STI 是一个可以解决问题的棘手工具。但是错误地使用它,它会产生比它所解决的问题更多的问题。

于 2012-07-09T12:45:56.147 回答
0

只需使用 has_many, :through。它会完成工作。假设您需要为一家您可以做的公司招募所有在职员工

class Employers   
  has_many  :hired_employees, :through => :employments, 
            :class_name => "Employees", 
            :source => :employee, 
            :conditions => ['employment.status= ?',"hired"] 
end

然后你可以做Employers.first.hired_employees。您可以添加更多并使用不同的条件,以便您可以“终止”、“解雇”等。

当然,这假设您有第三个模型,称为就业,它属于雇员和雇主。您的 Employee 和 Employment 类可能如下所示:

class Employee
  has_many :employments
end

class Employment
  belongs_to :employee
  belongs_to :employer
end
于 2012-07-09T07:40:56.783 回答
0

根据您所说,您可能需要以下模型:用户、工作、分配、角色

class User
    ... some devise declarations here ...
    ... some role here. rolify gem is my suggestion ...
    scope :employee, :where => {user.has_role? :employee}
    scope :employer, :where => {user.has_role? :employer}
    has_many :jobs, :through => :assignments 
    has_many :assignments 
end

class Job
    belongs_to :user # employer
    has_many :assignments
    has_many :users, :through => :assignments # employee
end

class Assignment
   belongs_to :job
   belongs_to :user # employee
   def fired?
       ... stuff to check if the employee is fired
   end
   def hired?
       ... stuff to check if the employee is hired
   end
end

优点:

  • 您可以轻松添加更多角色,例如经理、管理员……。使用 rolify gem 或者您可以为自己创建角色模型
  • 作业类将存储您需要存储的任何内容,例如解雇,雇用的员工
  • 由于角色是明确预定义的,因此可以使用 cancan 等授权 gem 轻松添加访问控制。

缺点:

  • 使用此模型,用户必须在执行任何其他操作之前检查您正在处理的当前用户是雇主还是雇员。但是,这可以使用角色轻松检查

为简单起见,您可以使用 rails_app_composer gem 生成安装了 devise、cancan 和 rolify 的初始应用程序。

注意:此答案基于许多类似的问题,例如: 多态性或 STI

于 2012-07-11T14:37:32.673 回答