最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

How to post to Rails app with JavaScript Fetch - Stack Overflow

programmeradmin2浏览0评论

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 of x-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 as application/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
Add a ment  | 

3 Answers 3

Reset to default 5

Rails .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!

发布评论

评论列表(0)

  1. 暂无评论