Ember + Ember Data Route error handling issue - ember.js

In soume routes in my app error action is never triggered and I can't figure out why. On some Routes error action works fine.
This is application route:
Simitu.ApplicationRoute = Ember.Route.extend({
init: function() {
this._super();
Simitu.AuthManager = Simitu.AuthManager.create();
},
model: function() {
if (Simitu.AuthManager.get('session.user'))
return this.store.find('admin', Simitu.AuthManager.get('session.user'));
},
actions: {
error: function(reason, transition) {
if (reason.status === 401) {
Simitu.AuthManager.reset();
this.transitionTo('login');
}
}
}
});
On this route Error is never triggered:
Simitu.PlacesIndexRoute = Ember.Route.extend({
model: function() {
var self = this;
// force adapter request
this.store.find('place');
return this.store.filter('place', function(record) {
// return just places that belongs to this client / application
return record.get('client_id') === self.modelFor('client');
});
},
actions: {
createNew: function() {
var place = this.store.createRecord('place');
// tree structure in places is not implemented yet
//parent = this.store.find('place', params.place_id);
place.set('client_id', this.modelFor('client'));
// open place
this.transitionTo('place', place);
},
error: function(error, transition) {
return true;
}
}
});
And on this Route everything works just fine:
Simitu.ClientsRoute = Ember.Route.extend({
model: function() {
return this.store.find('client');
},
actions: {
error: function() {
return true;
}
}
});
Have anybody some ide why?

The error action is fired on the resource, not an individual route.
http://emberjs.jsbin.com/cayidiwa/1/edit

This is how my router looks like. Maybe it breaks because of the nesting or filter logic in models. I fixed it in beforeModel hook in routes but still have not clue what is wrong with my first solution.
Simitu.Router.map(function () {
this.resource('login');
this.resource('clients');
this.resource('client', { path: 'clients/:client_id'}, function() {
this.resource('places', function() {
this.resource('place', { path: ':place_id' });
});
this.resource('placecategories',{ path: 'places-categories' }, function() {
this.route('new');
});
});
});

I move some of auth handling logic to beforeModel hook.
Simitu.AuthRoute = Ember.Route.extend({
beforeModel: function(transition) {
if (!Simitu.AuthManager.isAutenticated()) {
this.redirectToLogin(transition);
}
},
redirectToLogin: function(transition) {
this.transitionTo('login');
},
actions: {
error: function(reason, transition) {
if (reason.status === 401) {
Simitu.AuthManager.reset();
this.redirectToLogin(transoition);
}
}
}
});

Related

Ember.js dynamic routes not resolving in test, but work in production

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');
});
});

Uncaught TypeError: Cannot read property 'login' of undefined

I'm trying to set up OAuth with Firebase and Ember. For some reason it's returning the error
Uncaught TypeError: Cannot read property 'login' of undefined
App.LoginController = Ember.ObjectController.extend({
actions: {
login: function() {
var controller = this;
debugger;
controller.get("session").login().then(function(user) {
// Persist your users details.
}, function() {
// User rejected authentication request
});
}
},
});
I was thinking maybe the user is undefined, but I've defined it in a model:
App.User = DS.Model.extend({
username: DS.attr('string'),
});
Then I thought maybe it's the "session" that's undefined--I used the debugger to look up & it says it's an unknown mixin.
var session = Ember.Object.extend({
ref: new Firebase("https://glowing-fire.firebaseio.com/"),
addFirebaseCallback: function() {
var session = this;
this.get("ref").onAuth(function(authData) {
if (authData) {
session.set("isAuthenticated", true);
} else {
session.set("isAuthenticated", false);
}
});
}.on("init"),
login: function() {
return new Promise(function(resolve, reject) {
this.get("ref").authWithOAuthPopup("facebook", function(error, user) {
if (user) {
resolve(user);
} else {
reject(error);
}
});
});
},
currentUser: function() {
return this.get("ref").getAuth();
}.property("isAuthenticated")
});
App.Session = Ember.Object.extend({
initialize: function(container, app) {
app.register("session:main", session);
app.inject("controller", "session", "session:main");
app.inject("route", "session", "session:main");
}
});
I'd really appreciate your help!
The issue might be that you are trying to access an injected property, but the code that does the injection is never called. The recommended way to inject properties is described on this page.
More specifically the samples below (from the Ember.js website) should help
Using an application initializer:
App = Ember.Application.extend();
App.Logger = Ember.Object.extend({
log: function(m) {
console.log(m);
}
});
App.IndexRoute = Ember.Route.extend({
activate: function(){
// The logger property is injected into all routes
this.logger.log('Entered the index route!');
}
});
Ember.Application.initializer({
name: 'logger',
initialize: function(container, application) {
application.register('logger:main', App.Logger);
application.inject('route', 'logger', 'logger:main');
}
});
App.create();
or directly on the application:
App = Ember.Application.create();
App.register('logger:main', {
log: function(m) {
console.log(m);
}
}, { instantiate: false });
App.inject('route', 'logger', 'logger:main');

How can a controller or route send an action to itself

Given the following code, how can the route call it's doSomething action?
export default Ember.Route.extend({
setupController: function(controller, model) {
// call the doSomething action
},
actions: {
doSomething: function() { ... }
}
}
You can use Transition object which is passed do beforeModel/model/afterModel hook.
App.IndexRoute = Ember.Route.extend({
actions: {
doSomething() {
console.log('doSomethingInvoked');
}
},
beforeModel(transition) {
transition.send('doSomething');
},
model(params, transition) {
transition.send('doSomething');
},
afterModel(model, transition) {
transition.send('doSomething');
}
});
Working demo.

Ember.js Fixture findQuery

I'm trying to change my URLs in Ember to use a property on a model (title), instead of the ID. I can get everything to work if I click on a link-to, but when I do a fresh reload of the models route, everything seems to fall apart. Within queryFixtures I can get return the desired item, and logs to the console by logging 'experiment' to the console in the model hook.
App.ExperimentRoute = Ember.Route.extend({
serialize: function(experiment, params) {
return {
experiment_title: experiment.get('urlFriendlyName')
}
},
model : function(params) {
experiment = this.get('store').find('experiment', { title: params.experiment_title });
return experiment;
}
});
My store:
App.Store = DS.Store.extend({
adapter: DS.FixtureAdapter.extend({
queryFixtures: function(fixtures, query, type) {
function urlFriendlyTitle(title) {
var ret = title.replace(/ /g,"-"); // replace spaces
// do other replacements that make sense in your case, e.g.:
ret = ret.replace(/&/g,"and");
//... and so on and so forth
// encode the remaining characters
ret = ret.toLowerCase();
ret = encodeURIComponent(ret);
return ret;
}
return fixtures.filter(function(item) {
if(urlFriendlyTitle(item.title) == query.title) {
// console.log(item);
return item;
}
});
}
})
});
UPDATE:
App.ExperimentRoute = Ember.Route.extend({
model : function(params) {
experiment = this.get('store').find('experiment', { });
console.log(Ember.inspect(experiment))
return experiment;
}
});
Running the above outputs '<DS.PromiseArray:ember325>' in the console
App.Router.map(function () {
// Add your routes here
this.resource('category', { path: '/:category_id'}, function() {
this.resource('experiment', { path: '/:experiment_title' }, function() {
this.resource('device', { path: '/:device' });
});
});
});
App.ExperimentRoute = Ember.Route.extend({
setupController: function(controller, model) {
console.log(Ember.inspect(model))
console.log(Ember.inspect(controller))
}
})
This route outputs <App.ExperimentController:ember388> <DS.AdapterPopulatedRecordArray:ember326>

Trigger a model.get('transaction').rollback() from the deactivate hook in a route

How can I do a get('transaction').rollback() or deleteRecord() of the model in the deactivate route hook when the model is isNew? I can't figure out how to access the model from within the hook.
app.js
App.Router.map(function() {
this.resource('users', function() {
this.route('new');
})
});
App.UsersNewRoute = Ember.Route.extend({
model: function() {
return App.User.createRecord();
},
activate: function() {
this.controllerFor('users').set('newUserCreate', true);
},
deactivate: function() {
this.controllerFor('users').set('newUserCreate', false);
}
});
This is the code that does a rollback() on the model:
deactivate: function() {
this.controllerFor('users').set('newUserCreate', false);
if (this.currentModel.get('isNew')) {
this.currentModel.get('transaction').rollback();
}
Special thanks to #sly7_7 for solving this.
Route objects know about their controllers. You should also be able to do this:
deactivate: function() {
var model = this.get('controller.content');
if (model.get('isNew')) {
model.deleteRecord();
};
};