Ember Data: model.get('modelName') is undefined, but model._internalModel works - ember.js

I'm using Ember Data 2.2.0 and Ember 2.2.1. After retrieving a model from the data store, I'd like to get the model's type name as a string.
According to the API Docs, DS.Model defines a modelName property, which looks like what I want. However, I find that model.modelName, and model.get('modelName')are undefined, after retrieving model from the store with findRecord.
On the other hand, model._internalModel.modelName returns the lowercased, dasherized name of the model, as expected.
What's going on here?

It looks like a slight ambiguity in the documentation. It doesn't help that the modelName example uses DS.Store#modelFor which could be confused with Ember.Route#modelFor.
DS.Store#modelFor returns, according to the documentation, "a model class for a particular key. Used by methods that take a type key (like find, createRecord, etc.)". What I understand by this is that it returns the actual DS.Model class, and not the instance. _internalModel also returns the DS.Model class, hence the same behaviour.
I believe the safer alternative is doing model.constructor.modelName.

Related

Not possible to use shorthand route handlers if RestSerializer is used? (ember-cli-mirage)

I set up a simple Ember Twiddle to show you my error that is occurring when trying to update a model.
It's considerable that I'm using ember-cli-mirage for mocking the data.
According to the docs, I created a shorthand route that should handle the PUT request.
It does, but with the error: Your handler for the url /api/shops/1 threw an error: Cannot convert undefined or null to object
When using the JSONAPISerializer, everything is working with shorthands (mirage/config.js) and I'm able to update models, but in my case I have to use the RESTSerializer with serialized IDs in the responses.
The request payload when I'm sending the model's attrs are without Id at the end of the property name, f.e.:
// attrs object in PUT request
{
name: "Shop 1",
city: "1" // belongsTo relationship,
}
Now Mirage is trying to find those properties on the respective database model that has to be updated, but cannot find it, because in the database it's cityId and not just city...
I also found this issue report and it’s working, but I was hoping I could avoid something like this. As far as I can remember, in previous versions of ember-cli-mirage (v0.1.x) it was also not needed to override the normalize method in the serializer to be able to make use of the RestSerializer with serializedIds…
My question is:
Is there a way to stick to shorthand route handlers only, or do I really have to write a helper or other custom solution only because I have to use the RestSerializer?
That would be really sad, but at least I would know then.
Thanks for your support!
Short answer: it looks like you need the custom serializer for now until the bug fix for it is merged.
Long answer: that issue looks to be an issue that occurred in the 0.2 -> 0.3 upgrade for Mirage, likely because of underlying DB changes made in Mirage. It'll probably get fixed, but for now you'll need to work around it.

Prevent normalizing of the model name by overriding 'normalizeModelName' in Ember Data

I would like to prevent normalizing (dasherized by convention) of the model name and instead use the original name. I want to override the function 'normalizeModelName' as the page http://emberjs.com/api/data/#method_normalizeModelName suggests that this should be possible. But i'm not able to do so.
Simply assigning a new function to DS.normalizeModelName is returning an error: Cannot assign to read only property 'normalizeModelName' of object '[object Object]'.
How could I prevent normalizing of the (internal) model name?
small warning: this is related to 2.10.0
i will not guarantee compatibility beyond or below this version. you need to dig through the corresponding files yourself.
since i had a similar problem i dug through the sourcecode of some ember-data stuff and came to the following conclusion:
you need to extend DS.JSONAPIAdapter with pathForType(name) wich essentially takes the name and camelizes as well as pluralizes it before it's being returned as plain text string.
this usually converts model names from foo-bar to fooBars by doing this: https://github.com/emberjs/data/blob/v2.10.0/addon/adapters/json-api.js#L134-L137
now about the opposite:
you need to extend DS.JSONAPISerializer with keyForRelationship(key, typeClass, method)
where key is essentially the model name aquired from relationships in your models. like: fooBar
this usually translates to foo-bar by simply doing return dasherize(key); https://github.com/emberjs/data/blob/v2.10.0/addon/serializers/json-api.js#L453-L455
you might to also dig through some other methods inside the serializer: modelNameFromPayloadKey modelNameFromPayloadType payloadKeyFromModelName payloadTypeFromModelName
just throw in some debugger; lines to see whats going through.

Ember: use segments instead of query parameters for API?

Currently my Ember-cli application calls my API in this way:
apiurl:3000/ingredients?name=something
apiurl:3000/ingredients?filter=som?limit=10
I'd like to make Ember query for:
apiurl:3000/ingredient/something
apiurl:3000/ingredients/som?limit=10
But I've two problems:
WARNING: Encountered "ingredients" in payload, but no model was found for model name "ingredient" (resolved model name using myapp#serializer:application:.modelNameFromPayloadKey("ingredients"))
I can't find a way to make Ember use URL segments instead of query parameters.
I think I'm missing something?
Have you looked into overriding your RESTAdapter's buildURL method?
http://emberjs.com/api/data/classes/DS.RESTAdapter.html#method_buildURL
As what you're trying to do appears to be quite specific you could use this method to override the building of these requests, while at the same time keeping the default Ember model/params implementation the same.

what's the difference between deserialization and normalization?

Is to "deserialize" and "normalize" the same thing or are there differences? A straightforward question. I believe this is generic to front-end models communication to backend database sources/APIs. But if not, this is in the context of Ember Data.
There are differences. When you deseralize your intention is to change from one form say a javascript object and turning it into another form say a ember-data model. When you normalize your intention is to manipulate the data and/or structure of the current form.
So with ember-data you have RESTSerializer with:
serialize which takes a model and turns it into a plain javascript object.
normalize which takes a plain javascript object and returns a plain javascript object.
Compared to transforms/date.js:
deserialize Given a number or string returns a Date object.
serialize Returns a string representation of a Date object.
To put both of these things in context, from the docs on the applyTransforms method on JSONSerializer (this is where the transforms work on the plain javascript object):
Given a subclass of DS.Model and a JSON object this method will
iterate through each attribute of the DS.Model and invoke the
DS.Transform#deserialize method on the matching property of the
JSON object. This method is typically called after the
serializer's normalize method.

DS.RESTAdapter assuming polymorphism when there is none

I'm working with an API that I cannot alter. One of the resources it serves has a type property, which the RESTAdapter seems to assume is part of a polymorphic association. In this case, it isn't. So it throws errors like:
Error: No model was found for 'foobar'
Where 'foobar' is the value in the type column. Is there a way to tell Ember Data or its adapter that type is not part of a polymorphic association?
Use a custom serializer and remove the type.
http://emberjs.com/api/data/classes/DS.RESTSerializer.html