rails has_one through a collection
I'll start by pasting the relevant code and then I'll explain later what I am trying to do
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
The compus table has the following columns (copied from the migration)
create_table :com开发者_开发技巧pus do |t|
t.references :company
t.references :user
t.string :job_title
t.boolean :owner, null: false, default: false
t.timestamps
end
So as you can see, I have a user who can create n companies and have jobs at n companies, having a job at a company does not mean he's the owner..
What I would like to get is:
user.companies #=> The companies the user has created, or have jobs at (I worry about filtering results later)
company.employees #=> All the users that have jobs at this company (through compus)
company.owner #=> The one user that has originally created the company (or another one if transferred later)
So I added the following spec before I wrote the code above.
it "has one owner" do
company = Factory(:company)
user = Factory(:user)
company.should respond_to(:owner)
user.companies << company
company.owner.should === user
end
but I'm getting the following error:
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.
So how can resolve this problem without adding more columns to the companies table, it would be easier if I added owner_id on the companies table but that would lead to duplications in the database, usually if a user created a company it means that he works at it
Another question while I'm at it, How can I easily access the :job_title that is on the compus table through the association?
You can just make a function to return the owner
def owner
compus.where(:owner => true).first
end
In terms of database design, if you want to limit a company to one owner it would be a good idea to put an owner_id column in the company table. Otherwise you have to enforce that their is exactly one owner at all times, and it will be more complicated.
精彩评论