DEV Community

august-jk
august-jk

Posted on

Showing Relational Tables in Your JSON Response

Consider this scenario:

You're a ruby developer and you've just set up a few models with a one-to-many relationship, for the purpose of this blog we'll say the models are Author and Book.

An Author has_many :books and a Book belongs_to :author

This is common, as in programming we tend to rely on real-world models for our code. A pet can belong to an owner and an owner can have many pets, and a game can have many reviews, but a review can only belong to that one game.

Let's also say, you've developed a React frontend where you need to show these relationships, and your backend is using Ruby, ActiveRecord, and Sinatra.

Well, it sounds like you need to use "include:" in your Sinatra ApplicationController!

Let's get started!

Locate your Application Controller; this is the part of our Ruby backend that will handle what endpoints we will fetch from inside our React frontend.

Using our Author and Book models, here is what this class might look like:

class ApplicationController < Sinatra::Base

  get '/authors' do
    Author.all.to_json
  end

end
Enter fullscreen mode Exit fullscreen mode

Making sure that we inherit methods from Sinatra::Base will allow us to use various options inside our Controller file.

Here's an example of what JSON data we might receive if we visit http://localhost:9292/authors (once we have started the server, that is):

[
  {
    "id": 1,
    "name": "J. R. R. Tolkien",
    "image_url": "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcQO-WAOvTtPuzb5mS0h2GIZvwSO-HLofOY7VZRZBfcVW8wEJQUa"
  }
]

Enter fullscreen mode Exit fullscreen mode

This is nice, but what if we want to see all of the books this author has written?
We would then need to create a new route inside our Application Controller, see a list of all the books in our database, then compare the author_id of each book to our desired author's id...
I don't know about you, but that sounds like a lot of extra and unnecessary work!

There's one little line of code we can add to our author's route that will make things a little easier, can you spot the difference?

class ApplicationController < Sinatra::Base

  get '/authors' do
    Author.all.to_json(include: :books)
  end

end
Enter fullscreen mode Exit fullscreen mode

Hey! This new route says (include: :books), what's that about?

Well, that little line of code allows the books associated with the authors to be included in the JSON data without a whole lot of extra work!

Here's what our JSON data will look like now:

[
  {
    "id": 1,
    "name": "J. R. R. Tolkien",
    "image_url": "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcQO-WAOvTtPuzb5mS0h2GIZvwSO-HLofOY7VZRZBfcVW8wEJQUa",
    "books": [...
    ]
  }
]

Enter fullscreen mode Exit fullscreen mode

You can further customize the data you receive by changing up the syntax a bit (depending on how you set up your classes and what you'd like to return), but there you have it!
A great way to receive all of the data you need for your frontend without having to rely on using a GET request to fetch data more than once.

Top comments (1)

Collapse
 
prsaya profile image
Prasad Saya

Thinking about the authors and books data model - you build models explaining the relationships (entities, attributes and relationships). Then, you build the data based upon the application requirements (how you use the data or the kind of queries you make). You can also consider storing data as Json or using a NoSQL data store for creating data like that. For example, authors data with books or books data with author or just plain authors and books.