BigRetroMike BigRetroMike - 26 days ago 7
Javascript Question

Application in Ember don't recognize model so it end up with index data is null

I'm started adventure with Ember few weeks ago.
I have solid progress thanks to docs and example around the internet.

Sadly I hit solid wall with this one as have almost copy-pase models which few works and one and only one don't want to work.

The error that I see in Inspector is:

Encountered a resource object with type "series", but no model was found for model name "series" (resolved model name using 'my-app@serializer:-json-api:.modelNameFromPayloadKey("series"))
Error while processing route: serie.index data is null...


I'm using mirage fixtures with success

// mirage/fixtures/files.js
export default [
{duration:'1',filename:'1.mkv',size:'1',id:'1',url:'dl/1.mkv'},
{duration:'2',filename:'2.mkv',size:'2',id:'2',url:'dl/2.mkv'}
];

// mirage/fixtures/series.js
export default [
{type:'show',title:'ser1',summary:'123',id:'11'},
{type:'show',title:'ser2',summary:'234',id:'12'}
];


Both use same model for mirage

// mirage/model/file.js
// mirage/model/serie.js
import { Model } from 'ember-cli-mirage';
export default Model.extend({
});


I load fixtures this way:

// mirage/scenarios/default.js
export default function(server) {
server.loadFixtures();
}


And serializer is set on mirage this way:

// mirage/serializers/application.js
import { JSONAPISerializer } from 'ember-cli-mirage';
export default JSONAPISerializer.extend({
});


only thing that I added to config is

// added to mirage/config.js
this.namespace = 'api';
this.get('/series');
this.get('/series/:id');
this.get('/files');
this.get('/files/:id');


There is nothing more to do with mirage so let's move onto ember.

// app/adapters/application.js
application.js
import DS from 'ember-data';
export default DS.JSONAPIAdapter.extend({
namespace: 'api'
});


Both user same component

// app/components/file-view.js
// app/components/serie-view.js
import Ember from 'ember';
export default Ember.Component.extend({
});


Models are define this way:

// app/models/file.js
import DS from 'ember-data';

export default DS.Model.extend({
filename: DS.attr(),
url: DS.attr(),
art: DS.attr()
});

// app/models/serie.js
import DS from 'ember-data';

export default DS.Model.extend({
title: DS.attr(),
type: DS.attr(),
summary: DS.attr()
});

// app/router.js
import Ember from 'ember';
import config from './config/environment';

const Router = Ember.Router.extend({
location: config.locationType,
rootURL: config.rootURL
});

Router.map(function() {
this.route('serie', function() {
this.route('show');
});
this.route('file', function() {
this.route('show');
});
});

export default Router;


Routes are almost identical

// app/routes/file.js
import Ember from 'ember';

export default Ember.Route.extend({
model() {
return this.get('store').findAll('file');
}
});

// app/routes/serie.js
import Ember from 'ember';

export default Ember.Route.extend({
model() {
return this.get('store').findAll('serie');
}
});


Same goes to templates

// app/templates/file.hbs
<h2>Files</h2>

{{#each model as |fileUnit|}}
{{file-view file=fileUnit}}
{{/each}}
{{outlet}}

// app/templates/serie.hbs
<h2>Series</h2>

{{#each model as |serieUnit|}}
{{serie-view serie=serieUnit}}
{{/each}}
{{outlet}}


And last are component templates:

// app/templates/components/file-view.js
<div>
<img src="cover.jpg" width=200 hight=200 alt="">
<h3>{{file.filename}} id: {{file.id}}</h3>
</div>

// app/templates/components/serie-view.js
<div>
<h3> {{serie.title}} id: {{serie.id}}</h3>
Summary: {{serie.summary}}
</div>


And as
http://localhost:4200/file
work excellent the
http://localhost:4200/serie
throw error on me

I try to struggle with this by removing unnecessary code and models so I could narrow the problem but end up with having two models that are very similar with almost copy-paste function and having one work other don't.

I really have no idea what is this about anymore.

Answer

Your error gives you a hint

Encountered a resource object with type "series", but no model was found for model name "series" (resolved model name using 'my-app@serializer:-json-api:.modelNameFromPayloadKey("series"))

The problem is that ember knows how to switch between files and file but not between series and serie because the word series is irregular (both singular and plural) so serie is not its proper singular form.

Override modelNameFromPayloadKey method in your serializer to return the proper model name for the key 'series':

export default DS.JSONAPISerializer.extend({
  modelNameFromPayloadKey(key) {
    // if payload model name is 'series', use 'serie'
    if (key === 'series') { 
      return 'serie';
    }
    // otherwise do the default thing
    return this._super(...arguments);
  }
});
Comments