Following this post, the scenario is the same outlined here, i.e. a list of posts, each having zero or more comments.
Suppose one has the following router.
App.Router.map(function() {
this.resource('posts', function() {
this.resource('post', { path: '/:post_id' }, function() {
this.resource('comments', function() {
this.route('create');
});
});
});
});
The model for a post is the following one.
App.Post = DS.Model.extend({
title: DS.attr('string'),
comments: DS.hasMany('comment', { async: true })
});
A post, for example, is the following one.
{
"post": {
"id": 1,
"title": "Rails is omakase",
"links": { "comments": "/posts/1/comments" }
}
}
This way, I am able to load the comments of this post using the following route.
App.CommentsRoute = Ember.Route.extend({
model: function() {
return this.modelFor('post').get('comments');
}
});
The question now is: how can I create the CommentsCreateRoute, so that the new comment is actually posted to /posts/1/comments and not to /comments?
So far I have the following.
App.CommentsCreateRoute = Ember.Route.extend({
model: function() {
var newComment = this.store.createRecord('comment');
newComment.set('title', 'test comment');
return newComment;
}
});
App.CommentsCreateController = Ember.ObjectController.extend({
actions: {
saveEditing: function(){
var newComment = this.get('model');
newComment.save().then(function(comment) {
/* OK saved */
}, function(response) {
/* show errors */
});
}
}
});
Does this REST scheme make sense?
GET /posts/{post_id}/comments
PUT /posts/{post_id}/comments/{comment_id}
POST /posts/{post_id}/comments
or should I use the following?
GET /posts/{post_id}/comments
PUT /comments/{comment_id}
POST /comments
or any other? Which would be the most "standard"?
Related
So, I'm trying to use the Twitter-style URL syntax, allowing a user to go to example.com/quaunaut to visit the user page of the user with the username 'quaunaut'. I was able to accomplish this via:
app/router.js
export default Router.map(function() {
this.route('users.show', { path: '/:user_username' });
});
app/routes/users/show.js
export default Ember.Route.extend({
model: function(params) {
return this.store.find('user', { username: params.user_username }).then(function(result) {
return result.get('firstObject');
});
},
serialize: function(model) {
return { user_username: model.get('username') };
}
});
Now, when live or run via ember s, this works fantastically. However, in tests, it seems for some reason to not resolve.
var application, server, USERS;
USERS = {
'example1': [{
id: 1,
username: 'example1'
}],
'example2': [{
id: 2,
username: 'example2'
}]
};
module('Acceptance: UsersShow', {
beforeEach: function() {
application = startApp();
server = new Pretender(function() {
this.get('/api/users', function(request) {
return [
201,
{ 'content-type': 'application/javascript' },
JSON.stringify(USERS[request.queryParams.username])
];
});
});
},
afterEach: function() {
Ember.run(application, 'destroy');
server.shutdown();
}
});
test('visiting users.show route', function(assert) {
visit('/example1');
andThen(function() {
assert.equal(currentPath(), 'users.show');
assert.equal(find('#username').text(), 'example1');
});
});
Which results in the following test results:
Acceptance: UsersShow: visiting users.show route
✘ failed
expected users.show
✘ failed
expected example1
So, any ideas why currentPath() isn't resolving? If you also have any recommendations for better means to implement what I'm looking to do here, I'm certainly open to it.
Your visit syntax isn't quite right, should be:
test('visiting users.show route', function(assert) {
visit('/example1').then(function() {
assert.equal(currentPath(), 'users.show');
assert.equal(find('#username').text(), 'example1');
});
});
I'm new to Ember.js and Firebase and I've managed to add a post and display it onto the screen but I'm stuck on being able to delete it, will anyone be able to help me?
////////////////////////////////////////////////////////////
// CONTROLLER
////////////////////////////////////////////////////////////
App.PostsController = Ember.ArrayController.extend({
init: function() {
this.set('post', Ember.Object.create());
},
sortProperties: ['timestamp'],
sortAscending: false, // sorts post by timestamp
actions: {
publishPost: function() {
var newPost = this.store.createRecord('post', {
title: this.get('post.title'),
body: this.get('post.body'),
timestamp: new Date()
});
newPost.save();
},
removePost: function(post) {
var post = this.get('post');
Promise.cast(post.get('post.title')).then(function(posts) {
posts.removeObject(post);
post.destroyRecord();
post.save();
});
}
}
});
////////////////////////////////////////////////////////////
// POSTS
////////////////////////////////////////////////////////////
App.PostsRoute = Ember.Route.extend({
model: function() {
return this.store.findAll('post');
}
});
I've managed to fix it the updated code it below:
removePost: function(the_id)
{
console.log("Look, the record class is actually a promise! :D");
console.log(this.get('store').find('post', the_id));
console.log(this.get('store').find('post', the_id).toString());
this.get('store').find('post', the_id).then(function(rec) {
rec.destroyRecord();
});
}
I wasn't passing the id through in the index file, which weren't allowing me to delete the post. A rewrite of the removePost function also helped.
What I have done -
Model -
App.Book = DS.Model.extend({
book_name: DS.attr('string'),
edition: DS.attr('string')
});
Router -
App.Router.map(function() {
this.resource('books', function() {
this.route('new');
});
});
App.BooksNewRoute = Ember.Route.extend({
model: function() {
return this.store.createRecord('book');
},
actions: {
save: function() {
this.modelFor('newBook').save();
}
}
});
Now Can anybody help me.. How to save data ?
I am getting error like
TypeError: this.modelFor(...) is undefined
this.modelFor('newBook').save();
It is hard to tell how the context of your action looks like.
But one option is to pass the object you want to save as a parameter like this {{action save myBook}}.
Then you action could look like this:
App.BooksNewRoute = Ember.Route.extend({
model: function() {
return this.store.createRecord('book');
},
actions: {
save: function(book) {
book.save();
}
}
});
I think this should work.
App.BooksNewRoute = Ember.Route.extend({
model: function() {
return this.store.createRecord('book');
},
actions: {
save: function() {
this.get('model').save();
}
}
});
Given the following Ember.js application (using Ember 1.0.0.rc.6.1 and Ember Data 0.13):
App = Ember.Application.create({ LOG_TRANSITIONS: true });
App.Store = DS.Store.extend();
App.Router.map(function() {
this.resource('promotions', function() {
this.resource('promotion', { path: '/:promotion_id' }, function() {
this.resource('entrants', function() {
this.resource('entrant', { path: '/:entrant_id' });
});
});
});
});
App.PromotionRoute = Ember.Route.extend({
model: function() {
return { id: 1, name: 'My Promotion' };
}
});
App.EntrantsIndexRoute = Ember.Route.extend({
model: function(params) {
console.warn('EntrantsIndexRoute', '\nparams:', params, '\nparams.promotion_id:', params.promotion_id, '\narguments:', arguments);
console.log('params should be:', { promotion_id: 1 });
console.log('The queried URL should be:', '/entrants?promotion_id=1');
return App.Entrant.find({promotion_id: params.promotion_id});
}
});
App.Entrant = DS.Model.extend({
name: DS.attr('string')
});
If you enter the url #/promotions/1/entrants, which should be a nested resource, the params is an empty object. How can I access promotion_id there? JSFiddle here, take a look at the console after clicking on "Click me": http://jsfiddle.net/Kerrick/4GufZ/
While you can't access the dynamic segments of the parent route, you still can retrieve the model for the parent route and get its ID, like this:
App.EntrantsIndexRoute = Ember.Route.extend({
model: function() {
var promotion_id = this.modelFor('promotion').id;
return App.Entrant.find({ promotion_id: promotion_id });
}
});
Or, if there is a has-many relation between promotion and entrants, you even might do:
App.EntrantsIndexRoute = Ember.Route.extend({
model: function() {
return this.modelFor('promotion').get('entrants');
}
});
Try this code:
App.EntrantsIndexRoute = Ember.Route.extend({
model: function() {
var promotion_id = this.modelFor('promotion').query.promotion_id;
return App.Entrant.find({ promotion_id: promotion_id });
}
});
I'm using EmberData and wonder how I can I fetch a model from path like this:
products/:id/comments
Considering that you are using the default RESTAdapter, this is one possible way — although I'm not sure if it's the best one:
App = Ember.Application.create();
App.ProductCommentsRoute = Ember.Route.extend({
model: function() {
var productId = this.controllerFor('product').get('model').get('id');
return App.Comment.find({ product_id: productId });
}
});
App.Router.map(function() {
this.resource('products', function() {
this.resource('product', { path: ':product_id' }, function() {
this.route('comments');
})
});
});