Ember: working with http-mock and improper JSON - ember.js

Trying to work with http-mock feature of Ember-cli. My plan is not input some improper JSON(without root model, no Ids, embedded model instead of side loaded model etc etc) . Since i am new to this i first tried setting up a mock server with proper data and it was successful. Below is the relevant code.
adapters/post.js
import DS from "ember-data";
export default DS.RESTAdapter.extend({
namespace: 'api',
});
pods/post/route.js
import Ember from "ember";
export default Ember.Route.extend({
model: function(){
return this.store.find('post');
}
});
models/post.js
import DS from 'ember-data';
export default DS.Model.extend({
author: DS.attr('string'),
title: DS.attr('string'),
body: DS.attr('string'),
comments: DS.hasMany('comments')
});
server/mocks/posts.js
module.exports = function(app) {
var express = require('express');
var postsRouter = express.Router();
postsRouter.get('/', function(req, res) {
res.send({
"posts" : [{
'id': 1,
'author': 'Brian',
'title': 'Ember JS',
'body': 'JS framework for creating ambitious web applications',
'comments': [11,12]
}]
});
});
app.use('/api/posts', postsRouter);
};
This this point everything works fine. The above mock server data relates to the below JSON from an API call
{
"posts" : [{
'id': 1,
'author': 'Brian',
'title': 'Ember JS',
'body': 'JS framework for creating ambitious web applications',
'comments': [11,12]
}]
}
How would i write my mock-server code to produce a JSON which looks like this without root model?
{
'id': 1,
'author': 'Brian',
'title': 'Ember JS',
'body': 'JS framework for creating ambitious web applications',
'comments': [11,12]
}
Sorry for the long post and thanks in advance.
-Anees

Actually figured out a way myself and turned out to be quite easy.
server/mocks/posts.js
module.exports = function(app) {
var express = require('express');
var postsRouter = express.Router();
postsRouter.get('/', function(req, res) {
res.send(
{
'id': 1,
'author': 'Brian',
'title': 'Ember JS',
'body': 'JS framework for creating ambitious web applications',
'comments': [{
'author': 'Jimmy',
'body': 'Its cool',
},
{
'author': 'Jake',
'body': 'steep learning curve'
}]
}
);
});
app.use('/api/posts', postsRouter);
};
So basically its as simple as putting your desired JSON inside
res.send(
);
Thanks

Related

Ember.js : Modify request URL

I create an Ember app with a Symfony REST api. I also use the REST adapter for my requests.
I have 2 models in my app : users and their related comments.
I already created CRUD operations for my user properties and now I focus on the CRUD operations for comments.
Model user.js
export default DS.Model.extend({
firstName: DS.attr('string'),
lastName: DS.attr('string'),
comments: DS.hasMany('comment')
});
Model comment.js
export default DS.Model.extend({
title: DS.attr('string'),
message: DS.attr('string'),
user: DS.belongsTo('user')
});
I have a route which shows all comments (and other data) of a given user. The request loads the user object and his relations. On the view I also have a form and an action to create a new comment for this user.
Route users/get.js
import Ember from 'ember';
export default Ember.Route.extend({
id: null,
model(params) {
this.set('id', params.user_id);
return this.get('store').findRecord('user', params.user_id, {include: 'comments'});
},
});
Route users/get/comments.js
import Ember from 'ember';
export default Ember.Route.extend({
model(params) {
return this.modelFor('user.get', params.user_id);
},
});
Controller users/get/comments.js
import Ember from 'ember';
export default Ember.Controller.extend({
newComment: null,
user: null,
init: function() {
this._super(...arguments);
let comment = this.store.createRecord('comment');
this.set('newComment', comment);
},
actions: {
saveComment: function() {
let user = this.get('model');
let comment = this.get('newComment');
comment.set('user', user);
comment.save();
}
}
});
Everything works, except for the request sent to the backend. I loaded the comments from the user, so I expect a call to :
POST http://my-app.local/users/comments/
Instead the call is sent to :
POST http://my-app.local/comments/
Do you know why and how could I correct it ?
Second problem, the model is loaded from the 'user.get' route. This works because the user comes from this route to this page, but... It's doesn't work if the user enters directly the URL for comments. That sound logical, but I have no clue how to correct this problem... Can you help me ?
This can be done by rewrite the CommentAdapter.urlForCreateRecord method. Which affect new comment record requests.
adapters/comment.js
import DS from 'ember-data';
export default DS.RESTAdapter.extend({
urlForCreateRecord(modelName, snapshot) {
return '/users/comments'; // the url you want
}
});
There are several urlFor... method you might need to customise your url.
Just check out the document
http://devdocs.io/ember/classes/ds.buildurlmixin/methods#urlForCreateRecord

Ember store data to django backend

I'm new to Ember and I'm trying to communicate with a django server via RESTful API. So far I have managed to get the information from the server but if I try to send some information back I get a "CSRF Failed: CSRF token missing or incorrect." error.
In the resources of Chrome's developer tools I can see that I don't have any cookie. I've read that I should the "X-CSRFToken": "cookie" in my adapter but since I don't have a cookie I don't know what to do.
So I' m in dead end...
Here is my code:
Server Response:
[{"username":"user1","password":"123","email":"user1#example.com"},
{"username":"user2","password":"456","email":"user2#example.com"}]
Ember Model:
import DS from 'ember-data';
export default DS.Model.extend({
username: DS.attr(),
password: DS.attr(),
email: DS.attr()
});
Ember Adapter:
import DS from 'ember-data';
export default DS.RESTAdapter.extend({
host: '/api',
contentType: 'application/json',
dataType: 'json',
headers: {
username: 'XXXX',
password: 'XXXX'
},
buildURL: function(modelName, id, snapshot, requestType, query) {
var url = this._super(modelName, id, snapshot, requestType, query);
return url + "/";
}
});
Ember Serializer:
import DS from 'ember-data';
export default DS.JSONSerializer.extend({
primaryKey: 'username'
});
Ember Route: import Ember from 'ember';
export default Ember.Route.extend({
model() {
return this.store.findAll('account');
}
});
Ember Controller:
import Ember from 'ember';
export default Ember.Controller.extend({
actions: {
signup(){
console.log('My username is: ', this.get('username'));
console.log('My password is: ', this.get('password'));
console.log('My email is: ', this.get('email'));
var account = this.store.createRecord('account', {
username: this.get('username'),
password: this.get('password'),
email: this.get('email')
});
account.save();
}
}
});
Thank you in advance for your help.
I resolved my issue.
The problem was that I was using http://localhost:4200/ instead of http://127.0.0.1:4200/ and that's why I couldn't find django's cookie.
As soon as I found django's cookie, I just add an attribute to the header of the adapter.
My new adapter is shown below:
Ember Adapter:
import DS from 'ember-data';
export default DS.RESTAdapter.extend({
host: '/api',
contentType: 'application/json',
dataType: 'json',
headers: {
"X-CSRF-Token": 'django token',
username: 'XXXX',
password: 'XXXX'
},
buildURL: function(modelName, id, snapshot, requestType, query) {
var url = this._super(modelName, id, snapshot, requestType, query);
return url + "/";
}
});

Ember - Querying model by properties in a related model

I'm trying query my post model for published posts that have a specific tag. My models look like this:
var Post = DS.Model.extend({
tags: DS.hasMany('tag', { async: true }),
title: DS.attr('string'),
published: DS.attr('boolean'),
});
var Tag = DS.Model.extend({
posts: DS.hasMany('post', { async: true }),
name: DS.attr('string')
});
I've been able to get published posts in my query using the find() method:
this.get('store').find('post', {published: true});
But I don't understand how to query for properties that are part of a related model. I'd appreciate any guidance, thanks!
Edit
I came up with this solution using filter() which seems to work well.
var self = this;
var store = this.get('store');
store.find('post', {published: true}).then(function() {
self.set('content', store.filter('post', function(post) {
return post.get('tag.name') === 'Photography';
}));
});

ember how to display relationship property in template

I have a ember data model like this:
var attr = DS.attr,
hasMany = DS.hasMany,
belongsTo = DS.belongsTo;
App.Message = DS.Model.extend({
partner_pk: attr(),
message: attr(),
user: belongsTo('user', {async: true}),
inquiry: belongsTo('inquiry', {async: true}),
created_at: attr(),
updated_at: attr()
});
and route returning array of data like this:
App.TripMessagesRoute = Ember.Route.extend({
model: function(){
return this.store.find('message', {inquiry_id: 2});
}
})
My rest-api return data like this format:
{
"data": [
{
"id": 10,
"message": "this message is updated by ember.js",
"inquiry_id": 2,
"user_id": 1,
"created_at": "2014-08-05 14:20:46",
"updated_at": "2014-08-05 14:20:46"
},
{
"id": 17,
"message": "this is a test message by ember.js",
"inquiry_id": 2,
"user_id": 39,
"created_at": "2014-08-26 17:34:55",
}
]
}
in my template I am displaying the properties like this:
<script type="text/x-handlebars" data-template-name="trip/messages">
<h2>message is: {{message}}</h2> <!-- This works fine -->
<h2>User id: {{log user}}</h2> <!-- it gives null -->
<h2>User id: {{log user_id}}</h2> <!-- it gives undefined -->
</script>
My question is how do I display user_id in my template. Thanks in advance.
By default the property name in your Model definition should match the property being returned in your JSON.
Your choices are...
change your model to look like user_id: belongsTo('user', {async: true})
change your JSON to look like "user_id": 39
Add a MessageSerializer and change the object from user_id to user in the serializer.
You should then be able to put something like {{user.id}} in your template.

Model Not Found in Ember App Kit

I'm trying to use Ember App Kit with Ember Data (I'm using the latest of Both) using Fixtures - but for some reason I'm getting the following:
Assertion failed: No model was found for 'todo' [VM] ember.js (4005):415
Error while loading route: TypeError {} [VM] ember.js (4005):415
Uncaught TypeError: Cannot set property 'store' of undefined ember-data.js:2182
Application
import Resolver from 'resolver';
import registerComponents from 'appkit/utils/register_components';
var App = Ember.Application.extend({
LOG_ACTIVE_GENERATION: true,
LOG_MODULE_RESOLVER: true,
LOG_TRANSITIONS: true,
LOG_TRANSITIONS_INTERNAL: true,
LOG_VIEW_LOOKUPS: true,
modulePrefix: 'appkit', // TODO: loaded via config
Resolver: Resolver
});
App.initializer({
name: 'Register Components',
initialize: function(container, application) {
registerComponents(container);
}
});
App.ApplicationAdapter = DS.FixtureAdapter.extend();
export default App;
Index Route
import Todo from 'appkit/models/Todo';
var IndexRoute = Ember.Route.extend({
model: function() {
return this.store.findAll('todo');
}
});
export default IndexRoute;
Todo Model
var Todo = DS.Model.extend({
'title': DS.attr('string'),
'user': DS.attr('object'),
'comment': DS.attr('string'),
'mood': DS.attr('string')
});
Todo.FIXTURES = [{
'title': 'Received Hardware!',
'user': { 'username': 'alvincrespo' },
'comment': 'Finally received my hardware!',
'mood': 'happy'
}, {
'title': 'This is honorable.',
'user': { 'username': 'robwolf' },
'comment': 'I regret it already.',
'mood': 'happy'
}, {
'title': 'I can\'t seem to speak',
'user': { 'username': 'catstark' },
'comment': 'Wait a minute, why am I hear?',
'mood': 'sad'
}, {
'title': 'Attendance is poor.',
'user': { 'username': 'cerlan' },
'comment': 'Kings landing seems pretty empty after the war.',
'mood': 'neutral'
}];
export default Todo;
I've declared the DS.FixtureAdapter in app.js but for some reason its still not working? Any ideas?
Thanks!
I'm not positive about what the register components pieces does. But essentially it's saying it doesn't know about the Todo Model (generally it find it by looking for model's described in its namespace, aka App.Todo = DS.Model.extend....)
You might also need to still declare the store.
App.Store = DS.Store.extend();
And in Ember Data 1.0 beta 1 you do the adapter like so
App.ApplicationAdapter = DS.MyRESTAdapter; // note you don't extend/create it