Troubleshooting API through Binding.Pry
Tags: javascript, react, ruby, beginners
Published: 2022-06-28 02:24:29

This week, I completed another phase and project through Flatiron School’s Software Engineering program. In this phase, we’ve focused on building the backend of applications through Ruby, Active Record, and Sinatra. 

My project focussed on payment tracking to assist users with saving. To track and categorize payments, I had two, one-to-many model associations:

- Payments belong to Stores
  - Stores have many payments
- Payments belong to Categories
  - Categories have many payments

Setting up the migrations, models, and controllers came without issue. What did not make sense right away was how to build a Payment, with the above relationships, when a user submits payment information through a form. 

I struggled for a full 48 hours to understand how to format my Payment object through Javascript that correctly POSTs to the Sinatra built API and identify the two foreign keys I needed connected. 

This blog will cover how I accomplished this task and how `Binding.Pry` helped me find a solution when I was stuck.

To start, I will explain my API, Frontend Requests, and the Submission Form for Payments:

### The Set Up
As described, a `Payment` belongs to a `Store` and `Category`. Categories & Stores can have many payments. Categories and Stores do not currently tie together. 

Here is the Payment database model:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ye0zeme3hpxt8bi8prua.png)

A user can submit a payment through the following React form: 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9xz7vqc8rxcdljn287qn.png)

Form Submission to POST was something I had encountered before, but relating a value to a foreign key, when the user will have no concept of the foreign key's ID truly knocked me down. 

**Tip #1:** The JS object, or 'Form Data', as I've called it must include the required key, value pairs the server is expecting on the backend. 
 This may sound obvious, but as I was expecting a user to input a category or store name, I had assumed the client would send the category/store names and then `store_id` and `category_id` would be converted server side. This is not the case in my example! 

```
const [formData, setFormData] = useState({
      amount: "",
      date_paid: "",
      description: "",
      is_need: false,
      store_id: "",
      category_id: "",
  })
```

```
  const categoriesList = categories.map((category) => (
    <MenuItem key={category.id} value={category.id}>{category.category_type}</MenuItem>
  ))

 <Select
          displayEmpty
          id="standard-basic"
          className={classes.selectEmpty}
          name="category_id"
          value={formData.category_id}
          onChange={handleChange}
          inputProps={{ 'aria-label': 'Without label' }}
          > 
          <MenuItem value="" disabled>
                Category
          </MenuItem>
          {categoriesList}
        </Select> 
```

In my case, I chose to use a Select element for category and store submission to make it easier for the user and myself. The `Categories` display as `MenuItems` and that also gives me a chance to store that specific category's id under `name="category_id"`. 

When a store or category is selected, JS then does the work of inserting the corresponding ID to our `FormData`.

```
function handleChange(event) {
    if(event.target.name === "amount"){
      setFormData({
        ...formData,
          amount: parseFloat(event.target.value)
      }) 
    }
      else {
        setFormData({ 
          ...formData, 
          [event.target.name]: event.target.value 
        });
      }
  }
```
### The Server Side
Where I started to see smoke as a newbie engineer is that my JS object was showing up perfectly in the `console.log` output. But I was receiving specific API errors that Payment could not be submitting because the params were empty.

aka. My beautiful work was not coming across correctly in the server. 

**Tip #2**: Use Binding.Pry **AND** Play With It.

Here was my initial `payments_controller` for a POST:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/og5ly7wsn2pv5g1sl443.png)

and here is what `binding.pry` was providing me when I peeked into Payment:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ciwvfquy93agkyig3wa.png)


`Nil`!? How could that be when my object looked great before it was sent to server?



A tip from an instructor led me to try viewing the [params :payment] vs. just (params) within IRB. This led me to see that I was submitting data correctly, but I was asking my server to look for params called "payment", which did not exist as a key, value pair in my object. The solution:

```
post "/payments" do
    payment = Payment.new(params)
    if payment.save
      payment.to_json(include: [:store, :category])
    else
      {errors: payment.errors.full_messages}.to_json
    end
  end
```

Back tracking to just asking for "params" solved my issue (+/- some other tweaks to my code)! How could something so small trip me up for two days?

To put it simply, I was looking for the most complicated reason when `binding.pry` could have led me to a simple fix much quicker. 

### Conclusion:

I still struggled with the rest of my API calls because I was just getting used to Sinatra and Active Record set up. Leaning on `binding.pry` on the server side while also still utilizing `console.log` on the client end helped make sure the data was matching on both ends, taking less of my time!

Thanks for reading!