Does store.find() method use different inflection rules from ember-inflector? - ember.js

I'm building a simple Ember application using Ember v1.0.0 and Ember-Data v1.0.0-beta.3. I have a model called 'Categoria'
categoria.coffee:
App.Categoria = DS.Model.extend
nombre: DS.attr 'string'
simplified: DS.attr 'boolean'
candidatos: DS.hasMany 'candidato'
When I try to find a 'Categoria' by it's id, I always get error message:
Assertion failed: No model was found for 'categorium'
categoria_route.coffee:
App.CategoriaRoute = Em.Route.extend(
model: (params)->
#store.find('categoria', params.categoria_id)
)
App.CategoriaIndexRoute = Em.Route.extend(
model: ->
categoria = #modelFor('categoria')
categoria.reload() if categoria.get('simplified')
categoria
)
I've specified the inflections rules, due the spanish-named model.
store.coffee:
Ember.Inflector.inflector.irregular('categoria', 'categorias')
Ember.Inflector.inflector.rules.irregularInverse['categorias'] = 'categoria'
App.ApplicationAdapter = DS.ActiveModelAdapter()
App.ApplicationSerializer = DS.ActiveModelSerializer.extend()
I'm wondering if the find method of the Store uses a different set of inflections rules? or is there any other place where I should declare the inflection rules for this model?
It worths to mention that requests to the server for this model are made correctly (to the right URL) and they're responded well formed.
I've tried to use different syntax for the store.find method as mentioned in the Ember Guides#Method Find (http://emberjs.com/api/data/classes/DS.Store.html#method_find) but the error is the same.

The problem is when it tries to singularize the json response, it attempts to singularize categoria and it returns categorium, your pluralization was working fine.
var iff = Ember.Inflector.inflector;
iff.irregular('categoria', 'categorias');
// this adds a test for when it finds categoria and you are trying to singularize, return categoria
iff.singular(/categoria/, 'categoria');
http://emberjs.jsbin.com/ICeGuzuX/3/edit

Related

Building Relations between ObjecTypes in Typgraphql and Prisma

I am trying to create a relation between 2 ObjecTypes in Typgraphql with Apollo. This is my error:
As you can see in my category section I get null. This should be an item, because I already see it in my prisma ORM
#FieldResolver(() => Category)
async categories(#Root() parent: Product, #Ctx() ctx:Context): Promise<Category[]> {
return await ctx.prisma.category.findUnique({
where: {id: parent.id}
}).categories()!
}
I created a FieldResolver that returns the category when running the product's id. However, when I run categories at the end I get the following error: Property 'categories' does not exist on type 'Prisma__CategoryClient<Category | null>'.
I don't why I am getting this issue. Any information would be greatly appreciated.

Ember data: interpolated pluralization of model name

Say I have a DS.Store model called "userPreferences". Say I have a backend API returning a SINGLE "userPreferences" record:
{"userPreferences":{"userID":"7","latitude":null,"longitude":null}}
Say I have a route that I want to use this model with:
App.SettingsRoute = Ember.Route.extend({
model: function() {
myModel = this.store.find('userPreferences', 7);
return myModel;
}
});
If I try to do this, I get the following error from ember:
Error: No model was found for 'userPreference'
How do I specify that I'm already returning the singular form?
If you don't ever plan to refer to a collection of userPreferences, as Steve H. suggested you might need to, you can define the phrase as uncountable:
Ember.Inflector.inflector.uncountable('userPreferences');
Just be careful, you might need to also define:
Ember.Inflector.inflector.uncountable('user_preferences');
Because at present the inflector doesn't assume that you want both defined. The underscore version is sometimes used by ember-data when referring to model properties during serialization. I always define both camelCase and underscore versions.
I've opened an issue about this on ember-inflector.
What do you plan to call a collection of userPreferences? Here, I'm calling them "manyUserPreferences", but I'd suggest something better :) You can customize the way Ember understands the model names using an Inflector:
Ember.Inflector.inflector.irregular('userPreferences', 'manyUserPreferences');

Change/Define the saving end of a many-to-many relationship

I've got a many-to-many relationship in my Application between Users and Conversations
App.User = DS.Model.extend,
conversations: DS.hasMany('App.Conversation')
App.Conversation = DS.Model.extend
participants: DS.hasMany('App.User')
But every time i create and save a conversation, ember tries to save each participant including the ids of their related conversations. But i want the exact opposite of that, i want it to update just that one conversation and send the related participant_ids with it.
Is there a way to make that work?
What i tried so far:
specifying the inverse key on the user model (conversations: DS.hasMany('App.Conversation', inverse: 'participants'))
the workaround below.
.
App.RESTAdapter = DS.RESTAdapter.extend
serializer: DS.RESTSerializer.extend
addHasMany: (hash, record, key, relationship) ->
type = record.constructor
name = relationship.key
serializedHasMany = []
embeddedType = this.embeddedType(type, name)
return unless embeddedType is 'always'
record.get(name).forEach (record) ->
serializedHasMany.push record.get('id')
, #
hash[#singularize(key) + '_ids'] = serializedHasMany
App.RESTAdapter.map 'D4S.Conversation',
participants:
embedded: 'always'
After that it will save the conversation including the foreign keys but still tries to update the users, so i tried to save it with a custom request and just reset participant sates :/
App.Conversation._createWith = (participants) ->
conversation = #createRecord()
participants.forEach (p) ->
conversation.get('participants').addObject(p)
# conversation.save()
adapter = conversation.get('store._adapter')
adapter.ajax(adapter.buildURL('conversation'), 'POST',
data: { conversation: conversation.serialize() }
).then ->
conversation.setProperties(arguments[0].conversation)
conversation.get('stateManager').transitionTo('saved')
conversation.get('participants').forEach (user) ->
user.get('stateManager').transitionTo('saved')
conversation.trigger('didCommit')
conversation
Which finally worked \o/ But throw up the next error :(
Upon loading ember doesn't load the relationship, conversations participants property is always an empty DS.ManyArray
So is there a way to make that work?
Solution: Implement your own mapping key, don't use one thats already used.
This implementation solved all my problems:
serializer: DS.RESTSerializer.extend
###
Custom implementation to realize manySaving mapping
###
addHasMany: (hash, record, key, relationship) ->
#_super(hash, record, key, relationship)
type = record.constructor
name = relationship.key
serializedHasMany = []
manySaving = this.manySaving(type, name)
return unless manySaving
record.get(name).forEach (record) ->
serializedHasMany.push record.get('id')
, #
hash[key] = serializedHasMany
###
Check if manySaving option for a specific relationship is enabeld
#param {String} type The record type (usally a model class)
#param {String} name The attribute name of the relationship
#return {Boolean}
###
manySaving: (type, name) ->
this.mappingOption(type, name, 'manySaving')
D4S.RESTAdapter.map 'D4S.User',
conversations:
manySaving: false
D4S.RESTAdapter.map 'D4S.Conversation',
participants:
manySaving: true
key: 'participant_ids'

Ember Data: how to set isDirty for a record?

I have a details: DS.attr('recursive_object') custom transformation (it's a recursive object).
The details attr can be edited in place, without the actual object reference changing (e.g., a sub-detail on the details attr is edited). This, however, doesn't trigger the parent record's isDirty flag.
How can I manually notify a DS.Model record that it's been updated?
Model definition:
App.MyRecord = DS.Model.extend
details: DS.attr "recursive object"
Editing details
# record is an instance of App.MyRecord
# makes a change to the record's details attr
record.makeChangeToDetails()
record.get('isDirty') # still false because Ember doesn't know that a sub-detail changed.
Things I've tried:
Wrapping record.makeChangeToDetails() with will/didSetProperty calls:
record.send 'willSetProperty', name: 'details'
record.makeChangeToDetails()
record.send 'didSetProperty', name: 'details'
Calling notifyPropertyChange
record.notifyPropertyChange 'details'
Calling set and passing it the same object
record.makeChangeToDetails()
record.set 'details', record.get('details')
I've also tried sending various other DS.model states events from here: https://github.com/emberjs/data/blob/master/packages/ember-data/lib/system/model/states.js
including didChangeData, becameDirty but none of these worked.
Any ideas?
I got some clues from this other question: How to manually set an object state to clean (saved) using ember-data
In particular, the bit about:
record.get('stateManager').transitionTo('loaded.saved')
Using 1.0.0-beta.7+canary.b45e23ba, this appears to do the job:
> record.isDirty()
< false
> record.send('becomeDirty')
< undefined
> record.isDirty()
< true

Creating vs Modifying in backbone.js

This is my first application using backbone and REST API, I'm a bit confused with some specific scenarios when it comes to creating-editing. So if the model exits on server, it will EDIT, if it doesn't it CREATES.
When I pass on a unique identifier in my model, it knows it exits, but if I pass a combination of existing data without a unique identifier it always assumes it should CREATE. I'm not sure if this should be solved on client side or server.
For instance:
var exportationMod = new Backbone.Model({ 'asset': '/api/v1/asset/'+this.assetID+'/', 'export_configuration': '/api/v1/exportconfiguration/'+this.model.get('id')+'/' });
exportationMod.url = '/api/v1/exportation/';
exportationMod.save();
OK so the server is running with django + tastypie. Should this be validated by the client by first making an extra query, on the server (maybe there is a way of setting a combination of unique keys like mysql), or is there another setting I can tweak so it edits instead of creating?
If you pass data to the server without some unique id, how would the server know what to update?
If it makes sense for your situation, you can override isNew() in your model.
var MyModel = Backbone.Model.extend({
idAttribute: 'somethingUnique',
url: '/api/v1/exportation/',
isNew: function(){
// return true if you want create (POST),
// return false if you want update (PUT)
}
});
By default it looks like this (with the above model, this.id would be the idAttribute value above):
// A model is new if it has never been saved to the server, and lacks an id.
isNew: function() {
return this.id == null;
},
If you want to edit something that already exists on the server, you should just fetch it first before editing/saving it. Also, if there is some unique id that is not called 'id' you can override that on the model as well (see above).