I just wrapped up development on a Scrum/Kanban-like application based on Ruby and React. In this post, I'll be discussing one of the roadblocks I was up against when creating the Ruby application controller.
A scrum/kanban (we'll call it scrumban from here on out) board is used by development teams to provide a way to break down a project into smaller chunks of work that are able to be implemented in 2-to-4-week sprints. The scrumban board typically contains columns for work that is in the backlog, in-progress, in-review and closed.
My scrumban application allows a team to add new tasks to a project, edit a tasks properties (e.g. description, due date, story points, etc.) and delete tasks. All of the data for this application including users, project names, and tasks reside in their own tables in an SQLite database.
The scrumban React front end makes HTTP requests to the server through Sinatras application controller. Upon initial page load, the front end makes a request to the server for JSON object containing all of the tasks and their associated project and assigned user. THIS is where I hit a wall during development.
How do I set up the application controller routing in a way that includes an entities associated data from multiple tables?
Problem
My Ruby models are set up as shown in the Entity-Relationship Diagram (ERD) shown below. We have a Projects table, a Users table and a Tasks table (our "Join" table). Each task has a single associated project and a single associated user assigned to the task. A project and user can have many tasks.
When it came time to configure my application controller (the "C" in MVC), I wanted to return a JSON object of all of the tasks in the database. I also wanted to include project and user information for each of these tasks. I knew how to access associated data from one table (shown below), but how do I include data from multiple tables?
1 get '/' do
2 task = Task.all
3 task.to_json(
4 include: :project
5 )
6 end
I searched forums and read the Sinatra documentation, but I just couldn't find the solution. I'm sure the answer is documented out there somewhere. But I was struggled to find it.
Solution
One day I decided I was going to solve the mystery once and for all. I refused to build work-arounds into the client-side React application (e.g. multiple fetch requests, filtering arrays to find matching foreign and local keys, etc).
I threw everything I had at the problem. I tried multiple include:
statements. I tried putting putting the associated tables into an object like this include: {:project, :user}
.
Finally, I tried an array. It worked! Putting [:project, :user]
after the include:
statement is we include associated data from multiple tables!
1 get '/' do
2 task = Task.all
3 task.to_json(
4 include: [:project, :user]
5 )
6 end
This will now give us the associated project and the assigned user for each task! It seems so simple now, but I was truly at a loss.
I hope this post helps someone else. If it does, let me know in the comments!
Photo by Joshua Fuller on Unsplash
Top comments (1)
Nic thank you so much! This was incredibly helpful -- had the same experience but you're right, the solution is seemingly nowhere to be found. Apart from this post now!