To clarify, I think you have this: A property can have many projects. Each project belongs to one property and can have many jobs. Each job belongs to one project and can have many workers. Each worker belongs to one job.
Property
model:
has_many :projects
Project
model:
belongs_to :property
has_many :jobs
Job
model:
belongs_to :project
has_many :workers
Worker
model:
belongs_to :job
Each project
should have a property_id
, each job
should have a project_id
and each worker should have a job_id
. These can be established in your migration (with the belongs_to
function) where you create the tables for these models. They'll look like this:
create_table :projects do |t|
t.belongs_to :property, index: true
.
. # your other attribute(s) here
.
end
That will give the Project
model a property_id
attribute, allowing you to access a Project
's Property
.
Edit:
If you want to easily access all of a property's workers and all of a project's workers, you can add a has_many
through
association to each of the Property
and Project
models. Also, you can add another association to the Property
model that will allow you to access all of a property's jobs. They will look like this:
Property
model additions:
has_many :jobs, through: :projects
has_many :workers, through: :projects
Project
model additions:
has_many :workers, through: :jobs
Edit: (OP clarified desired model scheme)
Now if we want to have it so a worker can be assigned to more than one property, a different type of association will be needed. First of all, this association will only need to handle the relationship between jobs and workers. Since every job has only one parent project, and every project has only one parent property, the project and property associated with any job that a worker has will be accessible through that job.
There are two options for this job to worker relationship: has_and_belongs_to_many
and has_many
through
. The key difference between these options is that each record in the has_and_belongs_to_many
join table will only establish the association between a job and a worker and would not require a model, but the has_many
through
join table can contain additional information about that association. That additional information would be accessed through a separate model. This second option could, for example, be useful for keeping track of the number of hours that a worker logged on each job. Here is a more thorough description of the difference between these options.
If you have already created the Worker
and Job
models, you should generate a new migration to create this join table. Otherwise, you can include the following create_table
in the migration file for the Worker
or Job
models.
Here is the migration code for a has_and_belongs_to_many
association:
def change
create_table :jobs_workers do |t|
t.belongs_to :job, index: true
t.belongs_to :worker, index: true
end
end
In the Job
model, get rid of this:
has_many :workers
and replace it with this:
has_and_belongs_to_many :workers
In the Worker
model, get rid of this:
belongs_to :job
and replace it with this:
has_and_belongs_to_many :jobs
An explanation of the has_many
through
association would be more lengthy, so I'll defer to this page.