我想弄清楚如何构建这个请帮助:
我需要用户能够注册为雇主或员工。雇主基本上是公司,雇员是雇用该雇员的人。我想知道如何记录员工何时/是否被雇用并终止工作。一个has_many:through
分配对于这个或更好的工作是否有一个我忽略的宝石可以帮助我这个?
答案 0 :(得分:7)
这是分层对象模型的经典案例,因此您必须根据所涉及的对象及其关系来考虑此问题。想想企业在现实生活中的运作方式:
雇主 - >员工不是雇主 - >经理等 - >员工
这个系统模型的一个很好的例子是GitHub。在GitHub上,用户可以属于到组织。他们还可以创建它们并管理它们,管理成员等(在您的情况下雇用和解雇)。因此,对这个系统进行建模的一种更好的方法是让它以用户为中心而不是两个不同类别的用户分开。
如前一个答案中所述,雇主(或此处的企业) 感觉)不应被视为系统的用户,因为他们不会 根据程序的状态,用户会。因此,我个人认为STI是一个 对这个系统模型来说有点过分。
因此...
企业中雇用的所有人员都是员工,但并非所有员工都具有相同级别的权限(例如,经理将拥有比初级员工更多的权限)。因此,您应该为Business
建模,其中有很多 Employee
。那些Employee
将根据其位置具有不同级别的权限:
您还可以创建一种方法,告诉您何时雇佣/解雇此Employee
。如果他们被雇用/解雇,这些可以返回日期/时间,如果没有,则可以返回nil
。 nil
在这个意义上显然意味着他们还没有被雇佣/解雇。
在管理不同用户的能力时,他们的权限级别由他们能做什么和不能做什么来定义。您当然可以使用检查上述方法的简单方法将预设角色应用于此情况。例如:
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_hire
,designation
,status
,manager_id
,department
等。因此,我会模拟这个作为单独的对象,因此将此信息存储在单独的表中。我们称之为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
优点:
缺点:
为简单起见,您可以使用rails_app_composer gem生成安装了devise,cancan和rolify的初始应用程序。
注意:此答案基于许多类似的问题,例如: Polymorphism or STI