Rails雇主和员工设计

时间:2012-06-25 20:42:32

标签: ruby-on-rails ruby ruby-on-rails-3.1 devise sti

我想弄清楚如何构建这个请帮助: 我需要用户能够注册为雇主或员工。雇主基本上是公司,雇员是雇用该雇员的人。我想知道如何记录员工何时/是否被雇用并终止工作。一个has_many:through分配对于这个或更好的工作是否有一个我忽略的宝石可以帮助我这个?

4 个答案:

答案 0 :(得分:7)

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

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

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

  

如前一个答案中所述,雇主(或此处的企业)   感觉)不应被视为系统的用户,因为他们不会   根据程序的状态,用户会。因此,我个人认为STI是一个   对这个系统模型来说有点过分。

因此...

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

  • can_hire?
  • can_fire?

您还可以创建一种方法,告诉您何时雇佣/解雇此Employee。如果他们被雇用/解雇,这些可以返回日期/时间,如果没有,则可以返回nilnil在这个意义上显然意味着他们还没有被雇佣/解雇。

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

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

然后,您还将定义一种允许创建业务的能力:

def can_create_business?
  self.manager?
end

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

您还可以为角色的基本用户模型进行子类化,或者创建一个Role类,该类定义上述方法并对给定的User模型执行操作。然后,您可以创建角色的各个角色和子集。

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

这个模型遵循编程和计算机科学的一些最基本的原则,所以我希望它能对你的问题有所了解。当然有很多可用的宝石都有内置的功能,即设计 CanCan / CanTango ,虽然我会亲自自己构建这个系统。

答案 1 :(得分:2)

我想我会把STI和很多人通过关系结合起来。

首先,我将开始使用Employers和Employees的单个表继承。

class User < ActiveRecord::Base
  ...
end

class Employer < User
end

class Employee < User
end

雇主雇用员工。一个雇主可以拥有许多员工,并有就业机会来到其他相关的财产,如date_of_hiredesignationstatusmanager_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来说,在您的领域中,雇主和员工应该拥有一个&#34; IS A&#34;与用户的关系。你可能会想到它是一个&#34; IS A&#34;关系,但也要考虑它是否相同&#34; TYPE&#34; &#34;是A&#34;关系。在我工作的应用程序中,它没有意义,但我们与STI达成和解。雇主在雇员的申请中具有完全不同的特征,身份和待遇。虽然有些数据对于两者都是相同的,但它存在用于不同目的并且使用不同。这是一个足够的理由(单一责任)来单独建模。 STI是一个可以解决问题的棘手工具。但是错误地使用它会产生比它解决的问题更多的问题。

答案 2 :(得分: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。您可以添加更多并使用不同的条件,以便您可以“终止”,“解雇”等。

当然,假设您有第三个名为Employment的模型,它属于Employee和Employer。您的员工和就业课程可能如下所示:

class Employee
  has_many :employments
end

class Employment
  belongs_to :employee
  belongs_to :employer
end

答案 3 :(得分: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或者您可以自己创建角色模型
  • 作业类将存储您需要存储的任何内容,例如解雇,雇用员工
  • 由于角色是明确预定义的,因此可以使用授权gem(例如cancan)轻松添加访问控制。

缺点:

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

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

注意:此答案基于许多类似的问题,例如: Polymorphism or STI