使用AJAX更新Rails中期望字符串数组类型的字段
这绝对是Rails强参数(Strong Parameters)在搞鬼!Rails为了防止批量赋值漏洞,会要求你在控制器里明确声明哪些参数是允许被修改的——如果没把sentences加进去,哪怕请求返回200状态码,Rails也会默默忽略这个参数,自然不会更新你的数据。
下面是一步步解决的方法:
1. 修复控制器的强参数配置
找到你的GamesController,定位里面的game_params私有方法,把sentences字段加进去。因为你的sentences是数组类型,所以要写成sentences: []来允许数组格式的参数:
class GamesController < ApplicationController def update @game = Game.find(params[:id]) if @game.update(game_params) render json: @game, status: :ok else render json: @game.errors, status: :unprocessable_entity end end private def game_params # 这里一定要把sentences: []加进去,允许数组类型的参数 params.require(:game).permit(:id, sentences: []) end end
如果只是测试单个字符串的情况,也可以写成permit(:id, :sentences),但既然你的需求是数组,用sentences: []更贴合场景。
2. 确保前端AJAX请求的参数格式正确
很多时候参数没生效,也和前端传参的格式有关。要确保你的AJAX请求用JSON格式发送,并且参数嵌套在game这个键下面:
举个jQuery的例子:
$.ajax({ url: '/games/16', method: 'PATCH', contentType: 'application/json', // 一定要设置这个,告诉Rails你发的是JSON data: JSON.stringify({ game: { sentences: ['hello', 'world'] // 嵌套在game下,和强参数的要求对应 } }), success: function(response) { console.log('游戏更新成功:', response); }, error: function(xhr) { console.log('更新失败:', xhr.responseText); } });
如果用原生fetch的话:
fetch('/games/16', { method: 'PATCH', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content // Rails需要CSRF令牌 }, body: JSON.stringify({ game: { sentences: ['hello', 'world'] } }) }) .then(response => response.json()) .then(data => console.log('更新成功:', data)) .catch(error => console.error('更新失败:', error));
3. 验证是否生效
修改完之后,打开Rails的服务器日志(log/development.log),发送请求后查看日志里的参数部分:
Parameters: {"game"=>{"sentences"=>["hello", "world"]}, "id"=>"16"}
如果看不到Unpermitted parameter: :sentences的提示,说明参数已经被允许了,再去数据库里查一下game记录,就能看到sentences字段已经更新成你传的数组了。
记住:Rails返回200状态码不代表数据真的被更新了——只要请求没有语法错误,哪怕参数被忽略,它也会返回200。所以一定要看日志和数据库状态来确认。
内容的提问来源于stack exchange,提问作者Sophia Deetee

