1
votes

a rails newbie here, looking at doing some work with 4 tables and not totally sure how to structure the associations. Below topic involves real estate, probably helpful to keep that in mind.

I have four models:

  • Property - a physical house
  • Project - a large group of jobs happening at a house
  • Job - a specific job at a house
  • Worker - a person doing the work

The associations as I see them in my head are:

  • a Property can have many Projects, Jobs, and Workers
  • a single Project belongs to one Property, but can have many Jobs and (via Jobs) have many Workers
  • a single Job belongs to one Project and to one Property (via the Project), but can have many Workers
  • a single Worker can have one Job on one Projects on one Property

My two questions are:

  1. What is the best way to think about the above set of relationships?

  2. ** How do I build the associations between my models? Can't get my head wrapped around how to do that.

Really appreciate any thoughts!

***** UPDATED MODEL STRUCTURE - 9/30/2015 Thanks Jason - here is what I have now (below)

My key goal in working with the data will be the following: - list a property, it's projects, jobs and workers - list a set of projects and properties for a worker

Does the below model structure accomplish the above? It seems to from my view but can't totally be sure.

Model setup as 9/30

  • Property Model has_many :projects has_many :jobs, through: :projects has_many :workers, through: :jobs

  • Project Model belongs_to :property has_many :jobs has_many :workers, through: :jobs

  • Job Model belongs_to :project has_many :workers

  • Worker Model has_many :jobs

1
Check out guides.rubyonrails.org/association_basics.html. There you will learn about different types of associations, when to use which and how to set them up. - IngoAlbers
Thanks Egon, yeah I've seen that before. It all "makes sense" when I read it but then when I try to do it for some reason it all turns into a mess... - Anthony

1 Answers

1
votes

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.