I'm building a Chrome extension that needs to post to a Rails app.
I can send the request with Fetch but the JSON object isn't right when Rails processes the request. My controller returns an error:
NoMethodError (undefined method permit' for #<String:0x00007ff83b5a36e8>)
The logs say the data object looks like this:
{"highlight"=>"{\"text\":\"hello world!\",\"url\":\"helloworld\"}"}
The data object should look something like this:
{"highlight"=>{"text"=>"hello world!", "url"=>"helloworld"}}
For some reason, Rails processes the request as a string with the quotes escaped, and not a hash. I don't know how to pass it from Fetch so that it doesn't do that.
Here is the JavaScript code:
function captureHighlight(selection, tab) {
const highlight = {
text: selection.selectionText,
url: selection.pageUrl
}
return highlight;
}
async function postHighlight(highlight) {
let formData = new FormData();
formData.append('highlight', JSON.stringify(highlight));
const response = await fetch('http://localhost:3000/highlights', {
method: 'POST',
body: formData,
});
console.log(response);
}
I'm building a Chrome extension that needs to post to a Rails app.
I can send the request with Fetch but the JSON object isn't right when Rails processes the request. My controller returns an error:
NoMethodError (undefined method permit' for #<String:0x00007ff83b5a36e8>)
The logs say the data object looks like this:
{"highlight"=>"{\"text\":\"hello world!\",\"url\":\"helloworld.\"}"}
The data object should look something like this:
{"highlight"=>{"text"=>"hello world!", "url"=>"helloworld."}}
For some reason, Rails processes the request as a string with the quotes escaped, and not a hash. I don't know how to pass it from Fetch so that it doesn't do that.
Here is the JavaScript code:
function captureHighlight(selection, tab) {
const highlight = {
text: selection.selectionText,
url: selection.pageUrl
}
return highlight;
}
async function postHighlight(highlight) {
let formData = new FormData();
formData.append('highlight', JSON.stringify(highlight));
const response = await fetch('http://localhost:3000/highlights', {
method: 'POST',
body: formData,
});
console.log(response);
}
Share
Improve this question
edited Nov 16, 2019 at 20:23
the Tin Man
161k44 gold badges221 silver badges306 bronze badges
asked Nov 16, 2019 at 18:14
greenie-beansgreenie-beans
5201 gold badge5 silver badges16 bronze badges
4
-
2
Your fetch is sending your data as
x-www-form-urlencoded
so Rails would process the posted fields as strings. I don't know Rails much but I don't think it knows how to automatically determine if request parameters are json and should be parsed. I think you are possibly confusing what you did with sending your request as JSON instead ofx-www-form-urlencoded
, if that is the case see: stackoverflow./questions/29775797/fetch-post-json-data – Patrick Evans Commented Nov 16, 2019 at 18:22 - 3 Rails definitely does not automatically detect and parse "JSON" fields in form data. I don't think any sensible framework does. How should they know that you even intended to parse the field as JSON and its not something like a code snippet? – max Commented Nov 16, 2019 at 18:37
-
I'm able to send the request in Postman as
x-www-form-urlencoded
and the Rails app successfully processes the request. I tried to match that Postman request with Fetch but having that string issue in Rails. Should I try sending it asapplication/json
instead? – greenie-beans Commented Nov 17, 2019 at 1:57 - i can't get it to work with application/json either. it leaves my browser in the proper form but then rails processes and malforms it into what i mentioned in my question – greenie-beans Commented Nov 17, 2019 at 3:53
3 Answers
Reset to default 5Rails .xhr? method checks if the X-Requested-With
header contains the XMLHttpRequest
value. Simply set it in headers, like so:
const response = await fetch('http://localhost:3000/highlights', {
method: 'POST',
body: formData,
headers: {
'X-Requested-With': 'XMLHttpRequest'
},
});
and Rails will detect the request as xhr
and return the response in the appropriate format.
You should include into headers 'Content-Type': 'application/json' and all will be ok. The problem jumps into existance because rails doesn't know what type your content have.
There are two things I did wrong. I abandoned fetch and found it easier to use XMLHttpRequest()
. I don't have an JSON string problems with that, for whatever reason... FYI, my browser tool showed that my json was formatted correctly when the request left the client, whether using fetch or xml.
But, more importantly. I had CORS issues too. I should've gone back to the Chrome Extension documentation. All I had to do was grant permissions to whatever cross origin resource I want. https://developer.chrome./extensions/xhr
Thank y'all for reading/taking the time!