I am building an emberjs app and I want to call my REST API for results. I have this code:
App.Post = DS.Model.extend();
App.PostAdapter = DS.RESTAdapter.extend({
namespace: 'api/v1',
host: 'http://myapp.com'
});
And in the controller I have this
post: this.store.find('post')
The problem is that it always calls with "s" added in the end, for example - http://myapp.com/api/v1/posts
How do I remove the plural form from these calls?
You need to override the pathForType method in your adapter.
App.PostAdapter = DS.RESTAdapter.extend({
pathForType: function(type) {
var camelized = Ember.String.camelize(type);
return Ember.String.singularize(camelized);
}
});
var inflector = new Ember.Inflector();
inflector.singularize('posts');
Ember put 's' automatically. You need to force it to use singular. Above code tells Ember to request to myapp.com/post when you call this.store.find('post'); otherwise default behaviour will try to send request to myapp.com/posts
I had same issue once upon a time. I could not even found a way to set this behaviour globally. I have repeated this code ( inflector.singularize('posts'); ) for every store.
Related
I am using ember 2.0 and ember-data 2.0, and I have been struggling to find a way to pass custom URL to model.
For example, if my model is named Person and stored in model/person.js file, I would like rest web service url for finding record to be xxx/user/1, or in other words to avoid convention, and pass my URL to rest service - is is possible at all?
You can use Adapter.
If your backend conventions differ from Ember Data convention, it easy to change its functionality by swapping out or extending the default Adapter.
App.ApplicationAdapter = DS.RESTAdapter.extend({
namespace: 'api/v1',
pathForType: function(type) {
return Ember.Inflector.inflector.singularize(type);
}
});
If you want just override a specific model just write new adapter with modelName + Adapter.
When I want to use a custom adapter for a 'note' model I can do something like:
App.Note = DS.Model.extend({
title: DS.attr('string'),
/* others attrs */
});
App.NoteAdapter = DS.RESTAdapter.extend({
namespace: 'other/endpoint',
pathForType: function(type) {
return Ember.Inflector.inflector.pluralize(type);
}
});
Take a look at ember adapter guide, if you use ember-cli use blueprint generator like:
ember generate adapter user
Hi according to the ember ds 1.13 release docs:
If your app is using the vanilla JSONSerializer or RESTSerializer,
you will not have to make any changes, and your app will continue to
work. The existing serializers have been updated in a backwards
compatible way to return JSON API data to the store.
Currently I am the default RESTAdapter:
export default DS.RESTAdapter.extend({
host: 'http://localhost:9990',
namespace: 'api/v1'
});
Which has a custom serailzer for the model:
export default DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
comments: { embedded: 'always' }
}
});
When I attempt to use the new queryRecord method:
this.store.queryRecord('discussion',{ titleid: self.get('title_id')});
I get the following exception in the logs:
Error while processing route: title.index Assertion Failed: You tried to make a query but your adapter does not implement `queryRecord` Error: Assertion Failed: You tried to make a query but your adapter does not implement `queryRecord`
at new Error (native)
at Error.EmberError (http://localhost:4200/assets/vendor.js:25705:21)
at Object._emberMetalCore.default.assert (http://localhost:4200/assets/vendor.js:15895:13)
at ember$data$lib$system$store$$Service.extend.queryRecord (http://localhost:4200/assets/vendor.js:80502:15)
at loadDiscussionModel (http://localhost:4200/assets/ui.js:2728:32)
at renderTemplate (http://localhost:4200/assets/ui.js:2715:12)
at _emberRuntimeSystemObject.default.extend.setup (http://localhost:4200/assets/vendor.js:37282:14)
at Object.callHook (http://localhost:4200/assets/vendor.js:65078:38)
at handlerEnteredOrUpdated (http://localhost:4200/assets/vendor.js:63868:12)
at setupContexts (http://localhost:4200/assets/vendor.js:63836:9)
serializer/application.js
import DS from 'ember-data';
export default DS.RESTSerializer.extend({
serialize: function(record) {
return this._super(record, {includeId: true});
},
isNewSerializerAPI: true
});
According to source code default adapter does not have an implementation for queryRecord method: https://github.com/emberjs/data/blob/e89732a5aefb6a81b46927da1c6f048f4aede85e/packages/ember-data/lib/system/adapter.js#L226
Nor it's defined in RESTAdapter, neither in new JSONAPIAdapter. To my mind, this is due to query requests are too specific for every project thus are hard to generalize.
Nevertheless documentation contains explanation and example of implementation: http://emberjs.com/api/data/classes/DS.Adapter.html#method_queryRecord
By the way, there are two errors:
id shold be passed as 4th argument;
type.typeKey should be replaced with typeClass.modelName.
We prefer using simpler implementation in our own project:
export default DS.RESTAdapter.extend({
...
queryRecord: function(store, type, query, id) {
return this.ajax(this.buildURL(type.modelName, id, null, 'query', query), 'GET');
}
});
You can replace id argument with null in buildUrl method if needed.
Update
I forgot to mention, that in ember-data 1.13.5 RESTAdapter's default urlForQuery implementation returns url without actual query parameters passed.
So here's out implementation based on default _buildUrl method, with id replaced by query:
urlForQuery: function(query, modelName) {
var url = [];
var host = this.get('host');
var prefix = this.urlPrefix();
var path;
if (modelName) {
path = this.pathForType(modelName);
if (path) {
url.push(path);
}
}
if (prefix) {
url.unshift(prefix);
}
url = url.join('/');
if (!host && url && url.charAt(0) !== '/') {
url = '/' + url;
}
if (query) {
var queryParams = [];
for(var paramName in query) {
if(query.hasOwnProperty(paramName)) {
queryParams.push(paramName + '=' + encodeURIComponent(query[paramName]))
}
}
if(queryParams.length > 0) {
url = url + '?' + queryParams.join('&');
}
}
return url;
}
This method is in the same adapter as queryRecord from the original answer.
Adding isNewSerializerAPI: true to the all the relevant model Serializers worked to a certain degree (it removed the Error stated below). However the original error still occurrs.
Before due to an incorrect import the following Error in the console logs was not being displayed.
Error: Assertion Failed: is using the
old serializer API and expects
it collaborates with to do the same. Make sure to set
isNewSerializerAPI: true in your custom serializers if you want to
use the new Serializer API.
Also FYI according to the documentation this flag will not be required in Ember Data 2.0:
http://emberjs.com/blog/2015/06/18/ember-data-1-13-released.html
If you have customized your serializer, you should upgrade to Ember
Data 1.13, check the upgrade guide to see if you need to make any
changes, and then set a temporary flag on your Serializer:
isNewSerializerAPI. This will opt you into the new serializer API.
Once you are on the Ember Data 2.0 train, new Serializer API is the
default one, and there is no need for a flag.
I want to retrieve information through a REST request and set up a RESTAdapter like this:
App.ApplicationAdapter = DS.RESTAdapter.extend({
url: 'http://whatever.local'
});
Ember is doing a GET request but is not appending a parameter if I try do to a this.store.find('entry', 11) or this.store.findQuery('entry', {foo:'bar'})
Additionally it does not send the request to the url I defined. It just sends it to the host the app is running on.
Therefore I'm guessing I initialize the Adapter not properly, but cant seem to find the answer what I am doing wrong.
App.OverviewRoute = Ember.Route.extend({
model: function (params) {
console.log(params);
var entries = this.store.findQuery('entry', {periodDate: params.period_id});
return entries;
}
});
Help is appreciated.
Starting in EmberData 1.0.beta.1, the adapter option is host, not url (see here in the transition guide):
App.ApplicationAdapter = DS.RESTAdapter.extend({
host: 'http://whatever.local'
});
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.
I am new(to ember) and trying to build a search centric Ember App w/ Ember-data also. I wanted to change the url on the fly(based on search string) and the data should change automatically(on the fly). How to do it?
This is my not working code:
Emapp.Data = DS.Model.extend({
first_name: DS.attr('string')
}).reopenClass({
url: Emapp.MyURL.get('url')
});
Emapp.MyURL = Em.Object.create({
urlParam: 'John',
url: function()
{
return 'emb/data.php?id=%#'.fmt(this.get('urlParam'));
}.property('urlParam')
});
When I execute. emapp.MyURL.set('urlParam', 'Adams'). I can inspect and see the url changed to 'Adams'. But data is not fetched again.
Edit: emapp -> Emapp (pointed out by rudi-angela)
As you have made the 'url' property a computed property, Ember takes care of updating this value when the urlParam changes. That is all you have instructed Ember to do here (and apparently it is doing it properly).
But I reckon what you want here is any change in the 'urlParam' property to trigger a fetch action. In that case a solution would be to create a separate object that observes the urlParam and will take action when the 'urlParam' value changes. Something along these lines:
emapp.watcher = Ember.Object.create({
valueBinding: "emapp.MyURL.urlParam",
observer: function() {
console.log("urlParam has changed:");
// perform your fetch here
}.observes("value"),
});
Note: I thought there was a requirement for the namespace to be capitalised (rather Emapp instead of emapp).