3
votes

I'm trying to write some logic where if a user is logged in (and hence a currentUser variable is defined, more details in edit section below), he should not be able to access the root URL of the application, which is the log-in page. I'm trying to achieve this using a redirect to the users.show page before/as soon as the page loads, but I can't seem to figure out how to do it.

Reading ember documentation, you can do redirects from the route or the controller. I've attempted both and neither have worked. In the route:

App.ApplicationRoute = Ember.Route.extend
  redirect: ->
    currentUser = @controllerFor('Application').get('currentUser') # this works
    currentPath = @controllerFor('Application').get('currentPath') # this returns undefined
    if currentUser && currentPath == '/'
      @transitionTo('users.show', currentUser)

The problem here is that I can't read the currentPath for some reason, even though I can access it from within App.ApplicationController.

In the controller, I've tried:

App.ApplicationController = Ember.Controller.extend
  init: -> # never gets called
    if @get('currentUser') && @get('currentPath') == '/'
      @transitionToRoute('users.show', @get('currentUser'))

Except the init never gets called when loading the page, and I can't figure out from the documentation which hook gets called on page load.

If there are any other problems with the code, feel free to point them out. How do I fix my code in order to achieve the redirect?

EDIT: it was suggested for the route implementation to change 'application' to lowercase in @controllerFor('application'). Tried this and it returns the error

Assertion failed: The controller named 'application' could not be found. Make sure that this route exists and has already been entered at least once. If you are accessing a controller not associated with a route, make sure the controller class is explicitly defined.

Not sure what's going on, as doing a @controllerFor for other routes in all lowercase works, but not 'application'.

The Current User variable is obtained via an injection in an ember initializer. I'm using Rails and Devise on my backend, and the way I get currentUser into ember essentially more or less follows this tutorial. The general flow is Rails -> meta tag -> initializer -> injection.

SOLUTION: Inspired by the discussion following the accepted answer, I ended up doing it in ApplicationRoute like so:

App.ApplicationRoute = Ember.Route.extend
  beforeModel: (transition) ->
    currentUser = @controllerFor('currentUser')
    if currentUser && transition.targetName == 'index'
        @transitionTo('users.show', currentUser)
1
I think your problem is that you capitalized Application. I don't know about user created routes, but the application route is definitely all lowercase.GJK
See my edit to the bottom of original question. It doesn't seem to like @controllerFor('application') within App.ApplicationRoute...xph

1 Answers

0
votes

I didn't see that you were trying to get the application controller from the application route. I'm not 100% sure that will work. I believe the redirect hook is called fairly early on in the routing process, before setupController is called. That means that your init method is unlikely to be called before your redirect hook.

I have two potential solutions:

  1. It seems like the currentUser variable is created from some kind of global information. If that's the case, create it in the route, and transition if necessary. If you still want the data injected in the controller, use the setupController hook to put it there.

  2. If the currentUser variable happens to be the model for that particular route, try transitioning in the afterModel hook instead. This way you'll have direct access to the data.

Also, I would try to avoid transitions like that in controllers. Try to keep them in the routes if possible.

If you can give me a little more information about where the currentUser variable comes from, I can probably give you a more specific answer.

EDIT: This piece of code comes from the article you posted:

controller = container.lookup('controller:currentUser').set('content', user)

If that's similar to what you're using, try injecting it into the route rather than the controller.

controller = container.lookup('route:currentUser').set('currentUserModel', user)

You can then just use @get('currentUserModel') right in your route. And, if for some reason that doesn't work, just place the user in the global scope, just to make sure you don't have other errors. So instead of the line above:

App.TEMP_CURRENT_USER = user;