Currently delving into the world of Rails and Vue, I decided to take on a small project involving a basic Rails API and Vue app to practice making GET and POST requests from my Vue app to the Rails API. While GET requests are working smoothly, I'm encountering a 400 Bad Request error due to incorrect syntax when attempting to send POST requests. Interestingly, when testing with Insomnia (similar to Postman), the POST requests are successful. However, utilizing my Vue app for POST requests leads to a 400
error.
This is how my Rails controller is set up:
def create
@todo = Todo.new(todo_params)
if @todo.save
render :show, status: :created, location: @todo
else
render json: @todo.errors, status: :unprocessable_entity
end
end
...
private
def set_todo
@todo = Todo.find(params[:id])
end
def todo_params
params.require(:todo).permit(:title, :description, :finished)
end
In my Vue app, I have a simple text input field intended for submitting data to my Rails backend:
<template>
<input type="text" v-model="postBody"/>
<button v-on:click="submit()">Submit</button>
</template>
<script>
import axios from 'axios';
export default {
name: 'HelloWorld',
props: {
msg: String
},
data() {
return {
todos: [],
errors: [],
postBody: ''
}
},
methods: {
submit() {axios.post(`http://localhost:3000/todos/`, {
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: JSON.stringify(this.postBody)
})
.then(response => response.data)
.catch(e => {
this.errors.push(e)
})
}
}
}
</script>
I attempt to make a POST request in JSON format through the text input to the endpoint http://localhost:3000/todos/
:
{
"title": "Sweets",
"description": "Buy cookies",
"finished": false
}
Upon submission, the browser displays the following error message:
{status: 400, error: "Bad Request",…}
error: "Bad Request"
exception: "#<ActionController::ParameterMissing: param is missing or the value is empty: todo>"
status: 400
traces: {Application Trace: [{id: 1, trace: "app/controllers/todos_controller.rb:51:in `todo_params'"},…],…}
Application Trace: [{id: 1, trace: "app/controllers/todos_controller.rb:51:in `todo_params'"},…]
0: {id: 1, trace: "app/controllers/todos_controller.rb:51:in `todo_params'"}
1: {id: 2, trace: "app/controllers/todos_controller.rb:24:in `create'"}
The terminal output from my local Rails server while testing this locally in both Vue and Rails reads:
Started POST "/todos/" for ::1 at 2020-09-21 12:09:16 +0800
Processing by TodosController#create as JSON
Parameters: {"headers"=>{"Content-Type"=>"application/json; charset=UTF-8"}, "body"=>"\"{ \\\"title\\\": \\\"Sweets\\\", \\t\\\"description\\\": \\\"Buy cookies\\\", \\\"finished\\\": false }\"", "todo"=>{}}
Completed 400 Bad Request in 0ms (ActiveRecord: 0.0ms)
ActionController::ParameterMissing (param is missing or the value is empty: todo):
app/controllers/todos_controller.rb:51:in `todo_params'
app/controllers/todos_controller.rb:24:in `create'
It seems that the issue lies within strong parameters in my Rails controller. Removing the required params with .require(:todo)
allows the POST to go through, but all JSON fields end up null:
{
"id": 6,
"title": null,
"description": null,
"finished": null
}
Further attempts to investigate whether the problem stemmed from how form data was sent from my Vue app to the Rails endpoint, including using JSON.stringify
on the body
, did not yield any positive results.
After three days of trying to tackle this issue without success, I am reaching out for assistance. Any guidance would be greatly appreciated! :)