CRUD in nested(related) models
Closed this issue · 4 comments
Hi, say I have:
var Post = Backbone.AssociatedModel.extend({
urlRoot: '/posts',
defaults: {
content: 'Post by user'
}
});
var Posts = Backbone.Collection.extend({model: Post});
and a User model:
var User = Backbone.AssociatedModel.extend({
urlRoot: '/users',
relations: [
{
type: Backbone.Many,
key: 'posts',
collectionType: Posts.extend({
url: function () {
return '/users/' + user.id + '/posts';
}
})
}
]
});
I am trying to basically create an extra /posts CRUD route, after /users/{id}, but just overriding the url doesn't seem to work.
So basically, I want to be able to do:
var post = new Post({content: 'Blog post'});
user.get('posts').create(post); // => POST at /user/id/posts
Right now it just does a POST at /posts, which is not what I want to do.
Is this possible at all?
The reason for this is that in the backend route for /users/id/posts , I want to see the user ID so that I can associate it with this new Post instance. (just for the record, I am using a graph database(Neo4j) on the backend, so in terms of a graph database, I want to add a relationship between my User node and the to be created Post node).
Any help or suggestion would be appreciated!
Try using this one:
var User = Backbone.AssociatedModel.extend({
urlRoot: '/users',
initialize: function() {
var user = this;
this.get('posts').url = function(){
return '/users/' + user.id + '/posts';
}
},
relations: [
{
type: Backbone.Many,
key: 'posts',
collectionType: Posts
}
],
defaults: {
posts: []
}
});
For more details, you can take a look at this recipe.
Let me know if you need any help on this issue.
Thanks for responding. I did try that initially before I switched to the version of the User model in my initial post (ie extending the Posts collection to override the url), and it still does the same.
It works when I try to fetch the collection, ie if I do:
user.get('posts').fetch(); // => GET /user/10/posts
But if I try any of the other Backbone collection methods it fails. Ex:
user.get('posts').create({content: 'test'});
// => it does a POST at /posts instead of /user/10/posts
user.get('posts').sync(); // => Error message saying 'url' has not been specified, when it clearly has been.
users.get('posts').url(); // => users/10/posts
So I am not sure if this is because how Backbone works, or because of backbone-associations overriding sync and create maybe?
Here is a jsfiddle where you can try the exact code I'm running: http://jsfiddle.net/gonigkum/2TsMQ/1/
Thanks!
user.get('posts').sync()
needs method
and model
. Backbone obtains url
from model
object. So I think sync
will definitely fail without arguments.
In your case, Backbone uses urlRoot
to save newly created Post
model.
var Post = Backbone.AssociatedModel.extend({
// urlRoot: '/posts', // Try without urlRoot
defaults: {
content: 'Post by user'
}
});
After that change, user.get('posts').create({id: 45, content:"Hello"})
will make PUT request.
Let me know if it works for you.
Did this work for you?