您试图在模型:example(1)中包含“ dasherized-attribute-name”,但在模型上未定义名为“ dasherizedAttributeName”的关联

问题描述 投票:1回答:1

我们的应用程序主要使用下划线表示模型属性,因此我们很难完全实现海市rage楼。当我们尝试在模型中包括一个作为下划线属性引用的相关模型时,会收到以下错误:

Mirage: You tried to include 'dasherized-attribute-name' with model:example(1) but no association named 'dasherizedAttributeName' is defined on the model

具有这样的模型/工厂设置:

app / models / example.js:

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

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

app / models / attribute.js:

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

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

app / mirage / factories / example.js:

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

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

app / mirage / serializers / application.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();
    });
});

我发现这非常令人困惑和不直观。我们的属性是蛇形,错误表明我们试图包括经过反斜线化的属性,但最终在模型上寻找了驼峰式的属性。当然,将模型/工厂属性更改为驼峰式可以解决此问题,但是鉴于大量属性,现在对于我们的应用程序来说不一定可行。我已经尝试了序列化程序文档中引用的每个钩子来尝试处理这种情况,但根本找不到这些转换实际上发生在哪里。任何帮助将不胜感激。

ember.js ember-cli-mirage
1个回答
0
投票

对不起,您正在苦苦挣扎,我们应该在网站的某个位置添加一个指南来解释这一点!

我可以帮助澄清。当我第一次编写Mirage时,我们实际上是按照您的直觉建议进行操作:将Mirage的模型和关系与您的API约定匹配。

事实证明这是限制和混乱。 Mirage真正需要的是一个Serializer层,它将负责独立于数据层的数据形状。这样,数据层可以对主机应用程序的数据+关系进行更多假设,例如外键的存储位置。

这就是为什么我们将序列化器引入Mirage的原因。序列化程序将传入的有效负载转换为Mirage可以理解的“标准”格式,并将传出的有效负载转换为您的API发送的格式(这也是您的Ember应用程序期望的格式)。因此,为回答您的问题,序列化器是您要解决此问题的层。

有一个ActiveModelSerializer可能对您来说是一个很好的起点,因为它已经强调了属性。根据您的后端,这可能会起作用,或者您可以自己实现一个序列化器。假设您的生产API在某种程度上是一致的,那么配置序列化程序应该是一次性的,在整个应用程序范围内的事情。例如,可以使用各种keyFor*方法将Mirage模型+关系camelCase约定转换为下划线。如果您想查看示例,可以查看the source for ActiveModelSerializer

最后一部分是normalize()方法,该方法接收传入的请求并将其转换为JSON:API格式,因此Mirage知道在哪里可以找到属性和关系。同样,大多数应用程序应该能够扩展现有的序列化器之一,因此您不必自己编写。但这取决于您的后端API格式。 normalize()方法使Mirage的速记和助手(如normalizedRequestAttrs)可以与您的Ember应用程序的请求数据一起使用。

[希望这能使您对此有所了解,您实际上可以看到一个较早的博客帖子here,该帖子可以追溯到2015年,当时我第一次想到这个问题。如果您在配置序列化器时仍然遇到问题,请在Mirage repo上打开一个新问题或一个新的Stack Overflow问题,我将尽力回答!

© www.soinside.com 2019 - 2024. All rights reserved.