使用Ember CLI Mirage时Patch请求报错:无法读取null的update属性
问题原因分析
你遇到的两个现象(patch时的null错误、自动生成字符串id)其实是同一个问题导致的:Mirage默认使用id作为数据库集合的内部主键,而你自定义了keyId作为主键,但没有同步配置Mirage的数据库查找逻辑。
具体来说:
- 当你在Mirage的
RestSerializer里设置primaryKey: 'keyId',这只影响Mirage返回给前端的数据格式(把keyId作为主键字段序列化),但Mirage的数据库集合(比如surveyGroups)依然默认用自动生成的字符串id作为内部存储的主键。这就是你看到每条记录被添加字符串id的原因——这是Mirage自动给记录分配的内部主键。 - 你的前端Ember Data Serializer也设置了
primaryKey: 'keyId',所以前端发送patch请求时,URL里的:id是keyId的值(比如29116)。但你在Mirage的patch处理器里用surveyGroups.find(id)查找时,这个find方法是根据Mirage内部的id主键来查找的,而不是你定义的keyId,所以自然找不到对应记录,返回null,调用update时就会抛出“无法读取null的update属性”的错误。而你用那个自动生成的字符串id能找到记录,是因为那才是Mirage数据库当前认可的主键值。
解决方案
下面提供两种可行的解决方式,你可以根据项目需求选择:
方案一:调整查找逻辑(快速修复)
直接在patch处理器里,改用keyId来查找记录,同时注意把URL参数的字符串转成数字(因为你的Fixture里keyId是数字类型):
// mirage/config.js this.patch('/survey-groups/:id', function({ surveyGroups }, request) { let id = parseInt(request.params.id, 10); // 转成数字类型匹配Fixture的keyId let attrs = this.normalizedRequestAttrs(); let surveyGroup = surveyGroups.findBy({ keyId: id }); if (surveyGroup) { return surveyGroup.update(attrs); } // 处理找不到记录的情况,返回404 return this.notFound(); });
方案二:配置Mirage Model使用keyId作为主键(长期规范方案)
如果你的项目需要长期维护,建议配置Mirage的Model,让数据库集合直接使用keyId作为主键,从根源上解决主键不匹配的问题:
- 创建Mirage Model文件
mirage/models/survey-group.js:
import { Model } from 'ember-cli-mirage'; export default Model.extend({ primaryKey: 'keyId' // 指定该Model的主键为keyId });
- 确保你的Mirage Serializer配置正确(你当前的配置已经满足,这里再确认下):
// mirage/serializers/application.js import { RestSerializer } from 'ember-cli-mirage'; export default RestSerializer.extend({ primaryKey: 'keyId' });
这样配置后,Mirage加载Fixture时会用keyId作为数据库的内部主键,不会再自动生成字符串id,你原来的patch处理器代码就可以正常工作了:
this.patch('/survey-groups/:id', function({ surveyGroups }, request) { let id = parseInt(request.params.id, 10); let attrs = this.normalizedRequestAttrs(); return surveyGroups.find(id).update(attrs); });
内容的提问来源于stack exchange,提问作者Musimire
相关产品推荐
相关产品推荐

