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. 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). All three have their company_id set to the company id which we can assume is 1
when I ask for company.owner, I get the right user and when I do company.employee, I get all three.
If I change the owner to user 2, it removes user 1 from the employees automatically by setting it's company_id to nil. 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.
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. 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.
I'm not quite sure how well accepts_nested_attributes_for will play with a belongs_to relationship.
has_one is syntactic sugar for:
has_many :whatevers, :limit => 1
has one adds the :limit => 1
bit, thereby ensuring only 1 record is ever returned. In your has one declaration, make sure you have an :order
clause, to return the right record in all circumstances. 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.
Your question about how come Rails knows this is because most databases will return records in their primary key order. So, the 1st added employee has ID 1, thereby will be returned 1st.
You could have a model called ownership -
ownership belongs_to company
ownership belongs_to user
user has_many ownerships
company has_one ownership
来源:https://stackoverflow.com/questions/1480631/has-one-and-has-many-in-same-model-how-does-rails-track-them