【问题标题】:has_one and has_many in same model. How does rails track them?has_one 和 has_many 在同一模型中。轨道如何跟踪它们?
【发布时间】:2009-09-26 07:02:35
【问题描述】:

即使它正常工作,我也对它如何工作感到有些困惑。我有一个模型与同一个模型有两个关联。

公司有一个所有者,公司有很多员工的类用户。

这是我的公司模型:

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

这是我的用户模型:

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

现在假设我有这家公司的 3 名员工,包括所有者。当我第一次创建公司时,我将所有者设置为 ID 为 1 的员工,另外两个 (2,3) 通过设置其 company_id (user.company=company) 添加到员工列表中。这三个都将其 company_id 设置为公司 ID,我们可以假设为 1

当我查询 company.owner 时,我得到了正确的用户,当我查询 company.employee 时,我得到了这三个。

如果我将所有者更改为用户 2,它会通过将用户 1 的 company_id 设置为 nil 来自动从员工中删除用户 1。这很好,如果我将他添加为简单的员工,一切仍然很好。

rails 怎么知道哪个是哪个?我的意思是它如何知道员工是所有者而不仅仅是员工?架构中的任何内容都没有定义这一点。

我有一种感觉,我应该反转所有者关联,让公司属于用户。

【问题讨论】:

    标签: ruby-on-rails activerecord rails-models


    【解决方案1】:

    正如您现在所拥有的,没有什么可以区分所有者和员工。这意味着一旦您开始移除人员或尝试更改所有权,您就会遇到问题。

    正如 François 指出的那样,您很幸运,因为所有者是属于 ID 最低的公司的用户。

    为了解决这个问题,我会让我的模型按以下方式关联。

    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
    

    您必须在 Companies 表中添加另一个名为 owner_id 的列,但这更清楚地定义了您的关系。并且将避免与更改所有者相关的任何麻烦。请注意,如果您走这条路并设置数据库以使 users.company_id 和 Companies.owner_id 都不能为空,则可能存在周期性依赖关系。

    我不太确定accepted_nested_attributes_for 在belongs_to 关系中的表现如何。

    【讨论】:

    • 结束了这件事,在用户方面,我做了 belongs_to :employer, :class_name => "Company" 我需要这样做以防止与 user.company 发生冲突,现在 user.company 是拥有的公司和 company.employer 是......你明白了:P
    【解决方案2】:

    has_one 是语法糖:

    has_many :whatevers, :limit => 1
    

    有一个添加:limit =&gt; 1 位,从而确保只返回 1 条记录。在您的 has one 声明中,确保您有一个 :order 子句,以便在所有情况下都返回正确的记录。在这种情况下,我会在 Employee 上放置一个标志来表示谁是所有者,并按此列排序以获得正确的记录 1st。

    关于 Rails 是如何知道这一点的问题是因为大多数数据库将按主键顺序返回记录。因此,第一个添加的员工的 ID 为 1,因此将返回第一个。

    【讨论】:

      【解决方案3】:

      你可以有一个称为所有权的模型 -

      ownership belongs_to company   
      ownership belongs_to user
      
      user has_many ownerships
      company has_one ownership
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-12-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-11
        相关资源
        最近更新 更多