Reputation: 45
I'm stuck on this:
class Worker < ActiveRecord::Base
has_many :skills
has_many :jobs, through: :skills
..
end
class Skill < ActiveRecord::Base
belongs_to :worker
has_many :jobs
..
end
class Job < ActiveRecord::Base
has_many :skills
has_many :workers, through: :skills
..
end
What I'm trying to do is set up a many to many between Skill
and Job
inside of the `has_many' through relationship?
My question has three parts
This is a picture (of sorts) of what I'm trying to do, hope it helps... :(
Upvotes: 2
Views: 2689
Reputation: 77278
You're not giving active record enough information about your relationships. Every :has_many
should have a corresponding :belongs_to
so that active record knows which table holds the foreign key for each association. Notice that you only have one :belongs_to
for three relationships. That smells.
As for fixing the problem, you have at least 2 options:
:has_and_belongs_to_many
associationsMy preference is for the latter option. Being forced to name join tables often clarifies the nature of a relationship. On the flip side, I've found that :has_and_belongs_to_many
is often too implicit and ends up making my designs more obscure.
Explicit join tables
You might setup your relationships like this (untested):
class Assignment < ActiveRecord::Base
belongs_to :worker
belongs_to :job
end
class Qualification < ActiveRecord::Base
belongs_to :worker
belongs_to :skill
end
class Worker < ActiveRecord::Base
has_many :qualifications
has_many :skills, through: :qualifications
has_many :assignments
has_many :jobs, through: :assignments
..
end
class Skill < ActiveRecord::Base
has_many :qualifications
has_many :workers, through: :qualifications
has_many :jobs
..
end
class Job < ActiveRecord::Base
has_many :skills
has_many :workers, through: :assignments
..
end
By making the relationships more explicit I think the model is clearer. It should be easier to troubleshoot from here.
EDIT:
If you need to do a traversal like Job.find(1).qualified_workers
try making the following adjustment to the above model:
class Job
has_many :required_competencies
has_many :skills, through: :required_competencies
has_many :qualifications, through: :skills
has_many :qualified_workers, through: qualifications, class_name: :workers
end
class RequiredCompetency
belongs_to :job
belongs_to :skill
end
This is explicit about each traversal and names it. If you find these paths through your system are getting really long, I'd consider that a smell. There might be a more direct way to fetch your data or perhaps a better way to model it.
Upvotes: 2