rails has_one通过集合

时间:2011-06-25 17:16:09

标签: ruby-on-rails associations has-one

我首先粘贴相关代码,然后我会解释我想要做什么

class User < ActiveRecord::Base
  has_many :compus, :dependent => :destroy
  has_many :companies, :through => :compus
end

class Company < ActiveRecord::Base
  has_many :compus, :dependent => :destroy
  has_many :employees, :through => :compus, :source => :user
  has_one  :owner, :through => :compus, :source => :user, :conditions => { :owner => true }
end

class Compu < ActiveRecord::Base
  belongs_to :company
  belongs_to :user
end

compus表包含以下列(从迁移中复制)

create_table :compus do |t|
  t.references :company
  t.references :user
  t.string     :job_title
  t.boolean    :owner, null: false, default: false

  t.timestamps
end

正如你所看到的,我有一个用户可以创建n家公司并在n家公司找到工作,在公司找工作并不意味着他是所有者..

我想得到的是:

user.companies#=&gt;用户创建的公司,或者有工作(我担心以后过滤结果)

company.employees#=&gt;所有在该公司工作的用户(通过compus)

company.owner#=&gt;最初创建公司的一个用户(或稍后转移的另一个用户)

所以我在编写上面的代码之前添加了以下规范。

it "has one owner" do
  company = Factory(:company)
  user    = Factory(:user)

  company.should respond_to(:owner)

  user.companies << company

  company.owner.should === user
end

但我收到以下错误:

ActiveRecord::HasOneThroughCantAssociateThroughCollection:
       Cannot have a has_one :through association 'Company#owner' where the :through association 'Company#compus' is a collection. Specify a has_one or belongs_to association in the :through option instead.

那么如何在不向公司表添加更多列的情况下解决此问题,如果我在公司表上添加 owner_id 会更容易,但这会导致数据库中的重复,通常是用户创建了一家公司,这意味着他在这里工作

我遇到的另一个问题是,如何通过关联轻松访问compus表上的:job_title?

1 个答案:

答案 0 :(得分:7)

您可以创建一个函数来返回所有者

def owner
    compus.where(:owner => true).first
end

在数据库设计方面,如果要将公司限制为一个所有者,最好将owner_id列放在公司表中。否则你必须始终强制他们只是一个所有者,而且会更复杂。