I have created 3 models for a small system. The intent here is to handle users, companies and their relationships. I anticipate to do a lot of lookups over the intersections and also want to have strict controls over the joins available, in that a user can only belong to one company, but company can have many users. I feel the best way to represent this is with the below. I would like some feedback on this preposition. So far my tests have worked fine validating my thesis and some small implementation efforts have gone fine, but when I look through a list of users to find their company I somehow run into issues and I have a feeling it is related to the has_one relationship, but not sure. Again thanks for constructive feedback.
class User < ActiveRecord::Base
has_one :companyrelationship, foreign_key: "user_id"
has_one :company, :through => :companyrelationship, dependent: :destroy
class Company < ActiveRecord::Base
has_many :companyrelationships
has_many :users, :through => :companyrelationships
class CompanyRelationship < ActiveRecord::Base
belongs_to :company
belongs_to :user
validates :user_id, presence: true, uniqueness: true
validates :company_id, presence: true
I do see one thing that I’m pretty sure is an error and won’t work. I can also try to add a couple points of constructive criticism.
The error is that the CamelCase model name is converted to underscorey (sorry, I can’t remember the term for that right now) case. All your references to companyrelationship should add an underscore. You can override the convention by setting the :class_name attribute, but I don’t think that’s what you wanted.
Another issue I see which isn’t technically wrong, but is almost certainly not what you want is that the
dependent: :destroywould delete theCompanywhen you deleted aUser. (Actually, I’m not suredependent: :destroyworks in athrough:relationship.) I assume what you wanted was just to delete theCompanyRelationship. You can read the section on Dependent associations at this link:http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
Next point is that the default
foreign_keyis the model +_idso you don’t need to specify it in this case.My last point is purely a style preference. I like doing my validations by validation type. You’re doing them by variable. They are functionally equivalent, so feel to take it with a grain of salt. (I’m pretty sure
useranduser_idare equivalent, but feel free to stick touser_idif you’re more comfortable with it.)If it were completely up to me, I would code it this way:
I hope that helps you get further.