DEV Community

Laura Berge
Laura Berge

Posted on

Posting Nested Resources to Your Rails API

For the fourth project of the Flatiron School curriculum, I had to build an app that used a Ruby on Rails API backend and a vanilla Javascript frontend. The API needed to have at least one has-many relationship. The frontend also needed to make at least one other type of request than a 'GET.' I chose to use a POST request, so I found myself needing to figure out how to make a POST request to my API along with rails' 'accepts_nested attributes.' We hadn't learned the standard way to combine these two in the curriculum, so I read through a few blogs to see what others had done.

A little disclaimer: I am not sure if this is considered the best practice of putting a fetch request together with rails 'nested_attributes.' This is just the way I coded my app to make the request successful.

The Backend

I started with the API since I have more experience in ruby at this point. I start by coding 'accepts_nested_attributes_for' in my primary model like so...

# models/vacation.rb
class Vacation
  has_many :stays
  accepts_nested_attributes_for :stays
end

Then all that's left is to include those attributes in the controller white-listed params. The secondary model in a normal rails app from form_with sends through the 'fields_for' parts of the form with the key 'modelname_attributes.'

# controllers/vacations_controller.rb
class VacationsController < ApplicationController
  def vacation_params
      # in the array value, declare all the attributes of the secondary model you need
      params.fetch(:vacation, {}).permit(:city, :state, :country, :etc, stays_attributes: [:name, :address, :etc])
    end
end

The Frontend

While constructing the data being sent in the fetch request, I knew the API was expecting to receive data about a new vacation in the format of:

const data = {
  city: 'NYC',
  state: 'NY',
  country: 'USA',
  etc: 'more info',
  stays_attributes: [{
      name: 'The Hilton',
      address: '21367 Some St',
      etc: 'more data'
    }, {
      name: 'Holiday Inn',
      address: '35261 Some St',
      etc: 'more data'
    }
  ]
}

So, that is how I formatted my data from the HTML form. Once I had grabbed all the values from the HTML and formatted in the object as such, I passed that object into the body of the fetch request.

const configObject = {
        method: "POST",
        headers: {
            "Content-Type": "application/json",
            "Accept": "application/json"
        },
        body: JSON.stringify(data)
    };
fetch(url, configObject)
  .then(resp => resp.json())
  .then(json => console.log(json))
  .catch(error => alert(error.message));

Aside to Myself

Looking at how little code this all requires, it seems very simple to me since creating this app, but it definitely took me a bit of time and blog reading to figure out. One of the most powerful things I've learned from my journey thus far is how simple something that at first seemed impossible to comprehend can seem. That realization has made me a lot kinder to myself as a beginner and learner, as well as more understanding of others who don't yet understand something I might find self-explanatory. I'm now only four months into learning to code and at the beginning writing a simple line of HTML seemed so complex. Now basic HTML seems almost like second nature. Hopefully, soon Javascript will begin to feel simple--or at least more readable--as well.

Top comments (0)