I'm making an app that retrieves data of an API which is not in my control. I have the following scenario:
The path for retrieving the posts is /api/posts. So I configured my ApplicationAdapter as follows:
App.ApplicationAdapter = DS.RESTAdapter.extend({
namespace: 'api'
});
The url for retrieving comments is '/api/posts/1/comments'. You can see that the url is prefixed by the path for retrieving a single post followed by the default path /comments.
Ember data defaults to /api/comments. But I want to configure an adapter for my Comment-model so it makes the correct url: /api/posts/:post_id/comments with :post_id replaced with the id of the current post. How do I do that?
Modify your post json to include the hasMany as links (this could be done clientside), when it builds up the url it will prepend the url of the post, giving you post/1/comments
App.Post = DS.Model.extend({
comments: DS.hasMany('comment', {async:true})
});
{
post:{
id: 1,
links: {
comments: 'comments'
}
}
}
Here's a dinky example with colors and items
http://emberjs.jsbin.com/OxIDiVU/68/edit
Related
I have this model:
App.Game = DS.Model.extend({
name: attr(),
uri: attr()
});
and this route:
App.GamesRoute = Ember.Route.extend({
model: function() {
return this.store.find('game');
}
});
This works fine, calls the backend server, and stores elements in the store (I've checked with Ember inspector). This is the json I return:
{"games":[{"id":"TicTacToe","name":"TicTacToe","uri":"http://localhost:10000/games/TicTacToe"}]}
Now I have this template for 'games' (snipped):
{{#each game in model}}
{{#link-to 'games.matchlist' game.id}}{{game.uri}}{{/link-to}}
This shows the URI for each game. Now in the games.matchlist route what I would like to do is to search in the store by the game_id received param and get the game URI. The reason is that the server doesn't follow RESTAdapter conventions, and I would like to make a custom AJAX query to that URI myself.
This doesn't work:
App.GamesMatchlistRoute = Ember.Route.extend({model: function(params) {
var store = this.store;
var game = store.find('game', params.game_id)
console.log(game);
console.log("URI: " + game.uri);
at this point, game is an object but it's not an instance of my model. It doesn't have a uri attribute. What am I doing wrong? I'm feeling that I'm missing something obvious.
If you want to get records without hitting the server and you know you already have it in the store, use this.store.getById('game', ID).
I'm on my mobile, but you need to create a GameAdapter and customize I believe the fetch function. Checkout the docs for adapters on the ember site and you should have your answer.
Your other option is to fetch the data from your server and use this.store.pushPayload(data).
Docs here: http://emberjs.com/api/data/classes/DS.Store.html#method_pushPayload
And the adapter docs here: http://emberjs.com/guides/models/customizing-adapters/
I have a initial page where shows all posts.
Post as many comments, but in this initial page I don't wanna show comments. When User click in a post, the application goes to url posts/post/1 in this page I wanna show the comments of post.
My server has this endpoint
My server should provide separates endpoints for /posts and /comments or posts/:id/comments/ ?
what/how is the right way to fetch(fetch or find)?
Model
// Post
export default DS.Model.extend({
message: DS.attr('string'),
comments: DS.hasMany('comment'),
});
// Comment
export default DS.Model.extend({
message: DS.attr('string'),
post: DS.belongsTo('post'),
});
The best solution would be for your server to return the comments along with the post - called "sideloading".
So, if you called a GET on /post/1 and that post had comments 1,2, and 3, the JSON returned would include the "post" as well as those three comments
When you navigate to that URL "posts/post/1" you can get the dynamic segment value i.e 1 in your case.
In your model hook (in post route) find comment with that dynamic segment value
Eg:
model: function() {
return this.store.find("comments", post_id);
}
In your controller you can access this model by
var temp = this.get('model');
According to the URL conventions, the REST adapter performs a Find All (GET) at the plural URL, and a Find (GET) to the singular/id URL. Now, one of my URLs does not follow this scheme, because the URL itself refers to a single object, without id.
The URL is: api/me. This will return data about the current logged-in user, but I am not able to map a route to it. This is my code:
App.Me = DS.Model.extend({
full_name : DS.attr('string'),
email : DS.attr('string'),
});
App.ProfileUserRoute = Ember.Route.extend({
model: function () {
return App.Me.find();
}
});
The RESTAdpater is generating this URL: http://localhost:8000/api/mes, which is not found on my server. How can I finetune the URL which is used for a given route?
What might help is to define plurals on your adapter. This could look like this:
App.Adapter.configure('plurals', { "me": "me" });
Hope it helps.
Two of the models in my application are projects and users. Projects can have many users assigned to them and vice versa. I'm using Ember Data, so my model looks like this:
App.Project = DS.Model.extend({
name: DS.attr('string'),
created: DS.attr('date'),
users: DS.hasMany('App.User')
});
When creating a project on the server, the API expects to receive the project's name AND an array of IDs corresponding to the project's users. So, basically, something like this:
POST /projects
{
project: {
name: 'My Project',
users: [1, 10, 14]
}
}
However, Ember Data isn't including the array of user IDs when sending a POST or PUT request. By default, it only includes the name attribute. How can I modify Ember Data to include what I need? Is it even worth doing, or should I go the Discourse route and abandon Ember Data for now?
Assuming you are using the latest version and the RESTAdapter/RESTSerializer, you can override the addHasMany method of the serializer.
So, here is an example of how to do this:
App.CustomSerializer = DS.RESTSerializer.extend({
addHasMany: function(hash, record, key, relationship) {
var ids = record.get(relationship.key).map(function(item) {
return item.get('id');
});
hash[relationship.key] = ids;
},
});
App.Store = DS.Store.extend({
adapter: DS.RESTAdapter.extend({
serializer: App.CustomSerializer.create()
})
});
Note that the addHasMany implementation is taken from https://github.com/emberjs/data/blob/master/packages/ember-data/lib/serializers/fixture_serializer.js#L41
I'm very, very, very new to Ember :-)
I have a DS.Model where I want to force the extension with .json, for retrieving the data from a Rails Server.
The url from the Server is working, and for I can see in the browser's debugger, the url is not what it's specified in the DS.model url
var App = Ember.Application.create();
App.store = DS.Store.create({
adapter: DS.RESTAdapter.create({url: 'http://127.0.0.1:3000'}),
revision: 8
});
App.Expedient = DS.Model.extend({
url: 'expedients/%#.json',
procedencia: DS.attr('string'),
interessat_nom: DS.attr('string'),
data_signatura_provisional: DS.attr('date')
});
Fetch the expedient manually:
var model2 = App.store.find(App.Expedient, 125000);
Output console:
OPTIONS http://127.0.0.1:3000/expedients/125000 404 (Not Found)
I would like to be this url like this:
http://127.0.0.1:3000/expedients/125000.json
Also I've tried to really change the DS.Model url with another different name like this:
App.Expedient.reopenClass({
url: 'mockurl/%#.json'
});
But the browser's console has the same 'url' as before, I don't know why Ember-Data is not getting the model's url.
thanks!
regards,
ps. I'm aware of the Access-Control-Allow-Origin CORS problem when testing Ajax from two origins
github isn't working right now, for some reason, so I can't look at the source for ember, but I think you can do something like this:
var adapter = DS.RestAdapter.extend({
buildURL: function(record, suffix) {
var s = this._super(record, suffix);
return s + ".json";
})
});
You'll need to plug this your store instead of the default rest adapter.
I just tried this with my RESTAdapter subclass and it's working:
App.WORESTAdapter = DS.RESTAdapter.extend({
...
buildURL: function(record, suffix){
return this._super(record, suffix) + ".json";
}
})
Since you are working with a rails back end would it be easier to adapt your API to the same conventions Ember.data expects? so in your expedientsController#show action:
def show
#expedient = Expedient.find(params[:id])
render json: #expedient
end
As long as your controller is returning the JSON structure Ember expects it should map to your DS.Model see: this ember guide.