Closed kevinansfield closed 11 years ago
Sorry, just hit the Post button accidentally. Still working on this issue.
Updated original with full description.
I'll try to create a minimal test case for it, and I'll update you with results.
This could be something else.
I've just tested again now that I've got the rememberable
module working it seems that App.Auth.get('user')
returns null
in all model
and setupController
hooks, regardless of it being a redirect or not.
Running App.Auth.get('user')
in the console once the route has loaded works fine.
App.Auth.get('userId')
also returns null
I believe my server response is correct for the sign-in call:
{"user_id":26,"auth_token":"fvDeU9Ly8AMs63TUqiw8"}
Observation confirmed.
What is your expected behavior though? I can make signedIn
wait until post-sign in triggers have finished loading before becoming true
, but -
If we make it synchronous, such that it refuses to load your route until it has finished loading, then this would incur at least a double-roundtrip delay (sign in + fetch user), somewhat defeating the purpose of using an async-style ember app.
Or, if we make it async, then the model route would have been called before user
has finished loading anyway - 99% of time, that is, except for someone with lightning-fast network speed.
Yet a third option is to use ember's native observation pattern. Your controller would start with an empty user model - this becoming part of your app's expected behavior. You then define an observer for the path App.Auth.user
, and then populate the fields afterwards. You might also display a loading gif while this is happening (that's what I did for my own ember apps).
Your observation that
Running
App.Auth.get('user')
in the console once the route has loaded works fine.
is actually non-deterministic in the ember sense. It is just a coincidence that the model has finished loading when the route does - these two happen asynchronously. Try making your server delay, say, 10 secs before returning the user model, and you will see that the user is still not there when you test for it after the route has finished loading.
I was expecting it to work similarly to if I had App.User.find(x)
in the model
, i.e. I'd receive an empty User model in the loading state that is asynchronously populated when the data is available.
I have managed to get this working using your observation pattern by removing everything from the model
section of the route and adding this to the controller:
App.SignupStep2Controller = App.ObjectController.extend
content: null
loadProfile: (->
if App.Auth.get('user.profile')
@set('content', App.Auth.get('user.profile'))
).observes('App.Auth.user.profile')
Is there any way to use App.Auth.get('user')
in a route when it's possible that it hasn't been loaded yet?
No - this is actually not an ember-auth
specific issue; try replacing user.profile
with another "vanilla / innocent" model, e.g. comment.user
, product.stock
, etc, and (I think) you would get the same results.
The way I tackle this in my ember apps, is to simply set the model as user
, and then use
Name: {{profile.name}}
Email: {{profile.email}}
{{! OR }}
{{#with profile}}
Name: {{name}}
Email: {{email}}
{{/with}}
etc, and let ember's view layer bindings do its magic.
The way I tackle this in my ember apps, is to simply set the model as user, and then use
Sorry for all the questions, but where are you setting the model
?
I'm just trying out the observation pattern in a few other places and I'm getting inconsistent behaviour. Sometimes the content
gets set, other times it doesn't.
No problem, we're all exploring ember
:smile:
App.Foo = DS.Model.extend
fooValue: DS.attr 'string'
bar: DS.belongsTo 'App.Bar'
App.Bar = DS.Model.extend
barValue: DS.attr 'string'
baz: DS.belongsTo 'App.Baz'
App.Baz = DS.Model.extend
bazValue: DS.attr 'string'
App.FoosShowRoute = Em.Route.extend
model: (param) ->
App.Foo.find(param.foo_id) # model for a standard 'show' route
This is a show page for foo.
{{fooValue}} {{! let's say this would display a Foo's name? }}
{{bar.baz.bazValue}} {{! we can access nested belongsTo values directly}}
{{#with bar.baz}}
{{bazValue}} {{! or like this}}
{{/with}}
The way my suggested observation pattern works, is that it relies on an (implicit to userland code) App.User.find()
call in ember-auth
.
Normally, when you observe
something, you will, of course, call find()
somewhere in your code, in order to populate the data. You normally care about displaying the data, only that you don't mind its being blank before it's loaded. So you let ember take all the time it wants to load the model, and let ember automatically display it when it's ready.
A classic example is a hasMany
relationship.
App.Parent = DS.Model.extend
parentName: DS.attr 'string'
children: DS.hasMany 'App.Child'
App.Child = DS.Model.extend
childName: DS.attr 'string'
parent: DS.belongsTo 'App.Parent'
App.ParentsShowRoute = Em.Route.extend
model: (param) ->
App.Parent.find(param.parent_id)
{{! the parents.show template}}
<h1>{{parentName}}</h1>
<ul>
{{#each children}}
<li>{{childName}}</li>
{{/each}}
</ul>
Here, at first, parent
would be loaded into the model, but the list of children
would be empty. Ember would then load the parent
's children
asynchronously, and populate the list when it's done.
Updated docs to reflect this caveat.
I am having a similar issue. I have the user in a dropdown in the nav, so there isn't a route for this since it is show on every route.
I have this in my template: {{App.Auth.user.email}}
, but there is a timing issue so it isn't always populated. How can I set the user so I have access to it in the template and it has embers view layer bindings if there isn't a specific route on which to set the model?
Update: ember has got a new router, which is heavily relevant to authenticated-backed apps. I'm working with it to update ember-auth with the new APIs. For now, this issue is put on hold - I'll reproduce the scenario after I finish with the new router, and see if the issue persists.
Ref:
7.x
branch now released, with rc6 (new router!) support. changelog, upgrade guide, docs and demo all properly updated. Main notes:
ember-auth
now requires ember rc6
or aboveauthRedirectable
as "the ember way" of solving auth-only routes (with auth-only models)actionRedirectable
too for user experience@kevinansfield can you try upgrading and see if the issue persists?
Note however that, as stated above,
the new router now encourages you to use
authRedirectable
as "the ember way" of solving auth-only routes (with auth-only models)
This may prompt a rewrite of your original use case, as we pretty much have to embrace the promise pattern to solve auth-only use cases. (ref: detailed description in gist)
ember-auth
has already embraced the promise pattern, and all its redirects, server requests, etc, use promises and return promises. The new router will pick this up, and wait for these to resolve before progressing. On the flip side, redirections are also implemented in the same way, in that a redirection will abort the current route transition, and begin a new one (to the redirected destinatioin).
Hi,
Thanks for the nice Ember extension? plugin?
I'm a bit confused by the behaviour of the autoloading of the current user.
If I do App.User.find('123') I get the user alright. If I do App.Auth.get('userId') I get '123' But if I do App.Auth.get('user'), I get 'null'
What is the best way of accessing the details of the currently logged in user?
Straight from the docs:
App.Auth = Ember.Auth.create
# ...
userModel: 'App.Member' # default null
# pass the string, not a class App.Member
# access the current user model
# as with all things ember, this is loaded asynchronously
App.Auth.get('user')
If you didn't set the userModel
config, ember-auth
will not auto-load the model for you. That's still fine though, as you can still use App.Auth.get('userId')
to get the user ID, and call App.User.find(id)
when you need it.
Hi, I had read the documentation and set the model. That's why I expected the behaviour. It's working fine now. I got confused by (Note that it is not a string 'App.User'.)
on http://www.verious.com/code/heartsentwined/ember-auth/
I missed the # pass the string
in the docs. Thank you for your swift reply.
Closing due to inactivity (of the original issue).
Steps to reproduce the issue I'm seeing:
Now at this stage, the
console.log
calls both outputnull
yetApp.Auth.get('signedIn')
istrue
. Obviously this then causes themodel
not to be loaded sostep_2
my form is empty.However, immediately after the last redirect when I am on the page with the empty form, I can run
App.Auth.get('user)
in the console and the user object is available.Am I doing something wrong, or is there some way that the
model
can be lazily loaded?Thanks.
Relevant parts of router: