简体   繁体   English

has_one和has_many在同一个模型中。 rails如何跟踪它们?

[英]has_one and has_many in same model. How does rails track them?

I a little confused about how this work even if it works properly. 我有点困惑,即使它正常工作如何工作。 I have a model that has two association to the same other model. 我有一个与同一个其他模型有两个关联的模型。

Company has an owner and company has many employees of the class users. 公司拥有一个所有者和公司拥有众多员工的类用户。

here is my company model: 这是我的公司型号:

class Company < ActiveRecord::Base
  validates_presence_of :name

  has_many :employee, :class_name => 'User'
  has_one :owner, :class_name => 'User'
  accepts_nested_attributes_for :owner, :allow_destroy => true
end

here is my user model: 这是我的用户模型:

class User < ActiveRecord::Base
  include Clearance::User
  attr_accessible :lastname, :firstname #other attr are whitelisted in clearance gem
  validates_presence_of :lastname, :firstname
  belongs_to :company
end

Now assuming I have 3 employee of this company including the owner. 现在假设我有这家公司的3名员工,包括业主。 When I first create the company I set the owner to the employee with id 1 and the two others (2,3) are added to the employee list by setting their company_id (user.company=company). 当我第一次创建公司时,我将所有者设置为id为1的员工,另外两个(2,3)通过设置他们的company_id(user.company = company)添加到员工列表中。 All three have their company_id set to the company id which we can assume is 1 所有这三个都将他们的company_id设置为公司ID,我们可以假设为1

when I ask for company.owner, I get the right user and when I do company.employee, I get all three. 当我要求company.owner时,我得到了正确的用户,当我做公司工作时,我得到了所有三个。

If I change the owner to user 2, it removes user 1 from the employees automatically by setting it's company_id to nil. 如果我将所有者更改为用户2,则会通过将用户1的company_id设置为nil来自动从员工中删除用户1。 This is fine and if I add him back as a simple employee all is still good. 这很好,如果我把他作为一个简单的员工加回来,一切都还是不错的。

How the heck does rails know which is which? 铁路怎么知道哪个是哪个? What I mean is how does it know that an employee is owner and not just an employee? 我的意思是,它是如何知道员工是所有者而不仅仅是员工? Nothing in the schema defines this. 架构中没有任何内容定义此内容。

I have a feeling I should reverse the owner association and make company belong_to a user. 我有一种感觉,我应该扭转所有者协会,让公司属于一个用户。

As you have it now, there's nothing to distinguish owners from employees. 正如您现在所拥有的,没有什么可以区分所有者和员工。 Which means you're going to run into problems once you start removing people or try to change ownership. 这意味着一旦您开始删除人员或尝试更改所有权,您将遇到问题。

As François points out, you're just lucking out in that the owner is the user that belongs to company with the lowest ID. 正如弗朗索瓦指出的那样,你只是幸运,因为所有者是属于ID最低的公司的用户。

To fix the problem I would have my models relate in the following maner. 为了解决这个问题,我会让我的模型在以下方面有所涉及。

class Company < ActiveRecord::Base
  belongs_to :owner, :class_name => "user"
  has_many :employees, :class_name => "user"
  validates_presence_of :name
  accepts_nested_attributes_for :owner, :allow_destroy => true
end

class User < ActiveRecord::Base
  include Clearance::User
  attr_accessible :lastname, :firstname #other attr are whitelisted in clearance gem
  validates_presence_of :lastname, :firstname
  belongs_to :company
  has_one :company, :foreign_key => :owner_id
end

You'll have to add another column called owner_id to the Companies table, but this more clearly defines your relationships. 您必须在Companies表中添加另一个名为owner_id的列,但这更清楚地定义了您的关系。 And will avoid any troubles associated with changing the owner. 并且将避免与更换所有者相关的任何麻烦。 Take note that there might be a cyclical dependency if you go this route and have your database set so that both users.company_id and companies.owner_id cannot be null. 请注意,如果您使用此路由并且设置了数据库,那么可能存在周期性依赖关系,以便users.company_id和companies.owner_id都不能为空。

I'm not quite sure how well accepts_nested_attributes_for will play with a belongs_to relationship. 我不太确定accepts_nested_attributes_for与belongs_to关系有多好。

has_one is syntactic sugar for: has_one是语法糖:

has_many :whatevers, :limit => 1

has one adds the :limit => 1 bit, thereby ensuring only 1 record is ever returned. 有一个添加:limit => 1位,从而确保只返回1条记录。 In your has one declaration, make sure you have an :order clause, to return the right record in all circumstances. 在您有一个声明中,请确保您有一个:order子句,以便在所有情况下返回正确的记录。 In this instance, I'd put a flag on the Employee to signify who is the owner, and sort by this column to get the right record 1st. 在这种情况下,我在Employee上放置一个标志来表示谁是所有者,并按此列排序以获得正确的记录第1。

Your question about how come Rails knows this is because most databases will return records in their primary key order. 关于Rails如何知道这一点的问题是因为大多数数据库都会以主键顺序返回记录。 So, the 1st added employee has ID 1, thereby will be returned 1st. 因此,第一个添加的员工有ID 1,因此将返回第1。

You could have a model called ownership - 你可以拥有一个名为所有权的模型 -

ownership belongs_to company   
ownership belongs_to user

user has_many ownerships
company has_one ownership

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM