您尝试在model:example(1)中包含'dasherized-attribute-name',但模型上未定义名为'dasherizedAttributeName'的相关

wkyowqbh  于 2022-11-05  发布在  其他
关注(0)|答案(1)|浏览(110)

我们的应用在创建时主要使用下划线作为模型属性,因此我们很难完全实现mirage。当我们尝试在模型中包含作为下划线属性引用的相关模型时,我们收到以下错误:
Mirage: You tried to include 'dasherized-attribute-name' with model:example(1) but no association named 'dasherizedAttributeName' is defined on the model
模型/工厂设置如下:
应用程序/模型/示例.js:

import { belongsTo } from 'ember-data/relationships';
import Model from 'ember-data/model';

export default Model.extend({
    dasherized_attribute_name: belongsTo('attribute', { inverse: 'examples' }),
});

应用程序/模型/属性.js:

import { hasMany } from 'ember-data/relationships';
import Model from 'ember-data/model';

export default Model.extend({
    examples: hasMany('example', {
        inverse: 'dasherized_attribute_name',
    }),
});

应用程序/幻影/工厂/示例.js:

import { Factory, association } from 'ember-cli-mirage';

export default Factory.extend({
    dasherized_attribute_name: association(),
});

应用程序/幻影/序列化程序/应用程序.js:

import { JSONAPISerializer } from 'ember-cli-mirage';
import { pluralize } from 'ember-inflector';
import { underscore } from '@ember/string';

export default JSONAPISerializer.extend({
    alwaysIncludeLinkageData: true,

    keyForAttribute(key) {
        return underscore(key);
    },

    keyForRelationship(key) {
        // underscoring this value does nothing
        return key;
    },

    payloadKeyFromModelName(modelName) {
        return underscore(pluralize(modelName));
    },
});

实施例测试:

import { module, test } from 'qunit';
import hbs from 'htmlbars-inline-precompile';
import { render } from '@ember/test-helpers';
import { setupRenderingTest } from 'ember-qunit';
import { setupMirage } from 'ember-cli-mirage/test-support';

module('Integration | Component | example', (hooks) => {
    setupRenderingTest(hooks);
    setupMirage(hooks);

    hooks.beforeEach(async function () {
        this.store = this.owner.lookup('service:store');
        const serverExample = this.server.create('example');
        const example = await this.store.findRecord(
            'example',
            serverExample.id,
            { include: 'dasherized_attribute_name' }
        );

        this.set('example', example);
    });

    test('it renders', async (assert) => {
        await render(hbs`
            {{component
                example=example
            }}
        `);

        assert.dom('[data-test-example]').exists();
    });
});

我发现这是非常混乱和不直观的。我们的属性是snake case,该错误显示我们正在尝试包含属性dasherized,但它最终在模型上查找的是camel cased属性。当然,将模型/工厂属性更改为camel cased可以解决此问题,但鉴于属性的绝对数量,这对于我们的应用程序目前并不一定可行。我已经尝试了序列化器文档中引用的每一个钩子来尝试处理这种情况,但是根本无法找到这些转换实际发生的地方。

fiei3ece

fiei3ece1#

很抱歉您遇到了困难,我们真的应该在网站的某个地方添加一个指南来解释这一点!
我可以帮助澄清。当我第一次写Mirage时,我们确实做了你的直觉所暗示的事情:将Mirage的模型和关系与您的API惯例相匹配。
事实证明,这是一种限制和混乱。Mirage真正需要的是一个序列化器层,它将负责独立于数据层的数据形状。这样,数据层就可以对主机应用的数据+关系(例如外键的存储位置)做出更多假设。
这就是我们为Mirage引入序列化程序的原因。序列化程序将传入负载转换为Mirage能够理解的“标准”格式,并将传出负载转换为API发送的格式(这也是Ember应用所期望的格式)。因此,为了回答您的问题,序列化程序是您希望解决此问题的层。
这里有一个ActiveModelSerializer,它可能是一个很好的起点,因为它已经为属性加了下划线。根据你的后端,它可能会起作用,或者你可以自己实现一个序列化器。配置序列化器应该是一次性的,应用程序范围内的事情,假设您的生产API在某种程度上是一致的。各种keyFor*方法是您用来将Mirage模型+如果你想看一个例子的话,你可以看看the source for ActiveModelSerializer
最后一部分是normalize()方法,该方法接收传入的请求并将其转换为JSON:API格式,因此Mirage知道在哪里查找属性和关系。同样,大多数应用都应该能够扩展现有的序列化程序之一,因此您不必自己编写序列化程序。但这取决于您的后端API格式。normalize()方法使Mirage的速记和助手(如normalizedRequestAttrs)能够处理您的Ember应用的请求数据。
希望这能对这个主题有所帮助,您可以看到2015年的一篇旧博客文章here,我在那里第一次思考这个问题。如果您在配置串行化程序时仍有问题,请打开有关Mirage回购协议的新问题或新的堆栈溢出问题,我会尽我所能回答它!

相关问题