DS.RESTAdapter assuming polymorphism when there is none - ember.js

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

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 Data: model.get('modelName') is undefined, but model._internalModel works

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.

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.

Ember-Data relationship for objects that have relationships to other instances of the same object

I am converting a project from Backbone (w/ Backbone Relational for ORM) to Ember and I cannot find in the documentation an example of how to use DS.belongsTo to reference an object of the same type.
In otherwords, I have the following model definition (generic pseudo-code for clarity).
BoxModel
Text = String
BoxParent = BoxModel (referenced by id)
I want to re-create this structure in Ember for client-side manipulation etc.
I am also using requirejs so all my object targets for DS.belongsTo have to be included in the define statement and made available as parameters to the anonymous function.
As such, I doubt I can use something like this:
define ([ 'textbox' ]), function(TextBox) {
return DS.Model.extend({
BoxParent: DS.belongsTo(TextBox)
});
});
The reference to the current class definition is not likely to work. In Django, this type of relationship is handled with the special target of "self" but I cannot find any equivalent solution in Ember. Any help would be very much appreciated.
As a final note, this relationship can also be null because not all TextBoxes must have a parent (this is inevitable with this type of relationship unless you have infinite circular references.
Thanks!
Steve
You need to wrap your model name around quotes to use a non initialized model name.
App.Box = DS.Model.extend([
parent: DS.belongsTo('App.Box')
});