Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 :compus 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?

like image 367
kalbasit Avatar asked Feb 24 '23 18:02

kalbasit


1 Answers

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.

like image 82
mike Avatar answered Feb 26 '23 22:02

mike