如何将POST请求的FormData传递至Rails控制器并存储JSON数据
没问题,我来帮你搞定这个FormData传递到Rails控制器的问题,分两种常见场景给你讲解,你可以按需选择:
方式一:使用FormData传递(适合需同时上传文件的场景)
前端代码完善
你之前的FormData构造没写完,按照Rails的参数命名规范,得用模型名[字段名]的格式来append参数,这样控制器才能自动识别。完整的JS代码如下:
function save() { var tojs = myDiagram.model.toJSON(); var jsonStr = JSON.stringify(tojs); var formData = new FormData(); // 关键:遵循Rails参数命名规则 formData.append('tournoi[payload]', jsonStr); var xhr = new XMLHttpRequest(); xhr.open('POST', '/tournois', true); // 重要提示:不要手动设置Content-Type,FormData会自动生成正确的multipart/form-data请求头 xhr.onload = function() { if (xhr.status >= 200 && xhr.status < 400) { console.log('数据保存成功!'); } else { console.error('保存失败,状态码:', xhr.status); } }; xhr.send(formData); }
Rails控制器处理
因为前端传的是JSON字符串,我们需要把它解析成Ruby Hash再存入数据库(这样后续操作payload里的字段会更方便)。在你的TournoisController里这样写:
class TournoisController < ApplicationController def create @tournoi = Tournoi.new(tournoi_params) if @tournoi.save render json: @tournoi, status: :created else render json: @tournoi.errors, status: :unprocessable_entity end end private def tournoi_params // 先白名单参数,再把JSON字符串转成Hash params.require(:tournoi).permit(:payload).tap do |whitelisted| if params[:tournoi][:payload].present? whitelisted[:payload] = JSON.parse(params[:tournoi][:payload]) end end end end
方式二:直接发送JSON请求(纯数据场景推荐)
如果不需要上传文件,直接发JSON格式的请求会更简洁,Rails也能自动解析请求体:
前端代码
function save() { var tojs = myDiagram.model.toJSON(); var xhr = new XMLHttpRequest(); xhr.open('POST', '/tournois', true); // 设置请求头为JSON格式 xhr.setRequestHeader('Content-Type', 'application/json'); xhr.onload = function() { if (xhr.status >= 200 && xhr.status < 400) { console.log('数据保存成功!'); } else { console.error('保存失败,状态码:', xhr.status); } }; // 直接发送嵌套模型参数的JSON字符串 xhr.send(JSON.stringify({ tournoi: { payload: tojs } })); }
Rails控制器处理
这种情况下,Rails会自动把JSON请求体解析成参数Hash,控制器的参数处理会更简单:
class TournoisController < ApplicationController def create @tournoi = Tournoi.new(tournoi_params) if @tournoi.save render json: @tournoi, status: :created else render json: @tournoi.errors, status: :unprocessable_entity end end private def tournoi_params params.require(:tournoi).permit(:payload) end end
额外注意点
- 你的迁移文件是正确的,
t.json 'payload'会在PostgreSQL中创建json类型字段,Rails会自动处理Hash和JSON字符串的存储。 - 如果你需要对payload内的字段做查询(比如
Tournoi.where("payload->>'key' = ?", 'value')),只要确保存入的是合法JSON格式即可。
内容的提问来源于stack exchange,提问作者Dezz H
相关产品推荐
相关产品推荐

