如何一次性初始化数据库并实现多视图数据一致性?
嘿,我完全懂你碰到的这个问题——你想让basic-author和detailed-author这两个API端点返回的核心数据(比如author_name)完全一致,但又要对应Ember里不同的模型类型,对吧?你的思路是复用工厂类来保证数据一致性,但Mirage的工作逻辑和你想的不太一样,所以才会出现schema.basicAuthors.all()返回空的情况。
问题出在哪?
Mirage的schema是基于你定义的Mirage模型来创建数据集合的。你只生成了author类型的数据(通过server.createList('author', 20)),所以schema里只有authors这个集合,basicAuthors和detailedAuthors根本不存在,自然查不到数据。而如果直接返回schema.authors.all(),默认序列化后的资源类型是author,Ember的basic-author/detailed-author模型会因为类型不匹配无法正确解析数据。
两种可行的解决方案
方案1:用序列化器修改资源类型(推荐)
不用创建多个工厂类,而是复用同一个author数据集合,通过序列化器把返回数据的type字段改成对应视图的类型,让Ember模型能正确识别。
首先在mirage/config.js里配置路由,指定对应的序列化器:
// mirage/config.js this.get('/basic-author', (schema) => { return schema.authors.all(); }, { serializer: 'basic-author' }); this.get('/detailed-author', (schema) => { return schema.authors.all(); }, { serializer: 'detailed-author' });
然后创建两个序列化器,继承自你的author序列化器,修改返回数据的type:
// mirage/serializers/basic-author.js import AuthorSerializer from './author'; export default AuthorSerializer.extend({ serialize() { let json = this._super(...arguments); // 把每个数据项的type改成basic-author json.data = json.data.map(item => ({ ...item, type: 'basic-author' })); return json; } });
// mirage/serializers/detailed-author.js import AuthorSerializer from './author'; export default AuthorSerializer.extend({ serialize() { let json = this._super(...arguments); json.data = json.data.map(item => ({ ...item, type: 'detailed-author' })); return json; } });
这样两个端点返回的核心数据完全一致(都来自同一个authors集合),但资源类型分别对应Ember的两个模型,完美解决类型不匹配的问题。
方案2:手动构造响应数据(更灵活)
如果需要对不同视图返回的属性做裁剪(比如basic-author只返回author_name,detailed-author返回更多信息),可以直接在路由处理函数里手动包装数据:
// mirage/config.js this.get('/basic-author', (schema) => { const authors = schema.authors.all().models; return { data: authors.map(author => ({ id: author.id, type: 'basic-author', attributes: { author_name: author.author_name // 这里只保留basic视图需要的属性 } })) }; }); this.get('/detailed-author', (schema) => { const authors = schema.authors.all().models; return { data: authors.map(author => ({ id: author.id, type: 'detailed-author', attributes: { author_name: author.author_name, bio: author.bio, birth_date: author.birth_date // 这里返回详细视图需要的所有属性 } })) }; });
这种方法不需要额外创建序列化器,而且能精准控制每个视图返回的属性,同时核心属性(比如author_name)的值完全一致,因为都是从同一个author实例中获取的。
为什么不推荐用多个工厂?
你之前尝试扩展工厂类的思路,本质上是想让basic-author和detailed-author复用author的属性,但Mirage的工厂是用来生成对应类型的数据的——如果要让schema.basicAuthors有数据,你得调用server.createList('basic-author', 20),但这样就会生成两套独立的数据,很难保证author_name完全一致(除非硬编码,但失去了faker的随机意义)。所以复用同一个数据集合+修改类型的思路才是更合理的。
内容的提问来源于stack exchange,提问作者Paul Sham

