Question

I'm struggling on a design question for my Ruby on Rails website. I'm working on an estimation tool for construction companies for renovation projects.

It orders items this way by default:

  • Room (ex: Kitchen)
    • Section (ex: Painting)
      • Item (ex: Painting the ceiling)

But sometimes companies prefer to order items this way

  • Section
    • Room
      • Item

In our database, these items are in the same table with children containing their parent_id.

I give the option to quickly switch between 1st and 2nd display modes, but the way I do doesn't seem really clean to me. It is always stored like in the first example, and I have a bunch of "ifs" changing the way it's displayed.

I can't find a way to do this better, and didn't find any discussion on the subject (maybe I didn't know where to look)

Is there any best practices for this situation ?

Was it helpful?

Solution

Rather than the entities, let's look at the relationships here:

  • An Item is for exactly one Room; a Room has many Items
  • An Item is for exactly one Section; a Section has many Items
  • A Room has many Sections; a Section applies to many Rooms (even in the original hierarchy, your example Section was "Painting", not "Painting the Kitchen")

So we have two one-to-many relationships, and one many-to-many relationship. A hierarchy is a one-to-many structure, so can't correctly model the relationship between Rooms and Sections.

Instead, you can model the relationships explicitly:

  • Every Item has a Room ID and a Section ID
  • To list all Sections for a Room, look in Items for the distinct set of Section IDs with that Room ID
  • To list all Rooms for a Section, look in Items for the distinct set of Room IDs with that Section ID

If there is information that needs to be stored against the combination of Room and Section, you would need to create a new entity to represent that combination:

  • Every Item has a RoomSection ID
  • Every RoomSection has a unique combination of Room ID and a Section ID
  • To list all Sections for a Room, look in RoomSections for all the Section IDs with that Room ID
  • To list all Room for a Sections, look in RoomSections for all the Room IDs with that Section ID

Or, you might go the other way, and make this into a generic "facet" system, with "Room" and "Section" as run-time defined attributes which can be extended or replaced according to need. This flexibility brings a lot of complexity - you need to re-implement things like constraints, for instance - so don't take this option unless you're sure it will bring value.

Licensed under: CC-BY-SA with attribution
scroll top