Question

I am baffled by a seemingly simple ember question. I am using active_model_serializers meta data serialization to serialize my rails current_user method from a rails controller, then extracting and setting that current_user meta json to a global ember variable using this guy's temporary solution.

App.CustomRESTSerializer = DS.RESTSerializer.extend({
  extractMeta: function(loader, type, json) {
    var meta;
    meta = json[this.configOption(type, 'meta')];
    if (!meta) { return; }
    Ember.set('App.metaData', meta);
    this._super(loader, type, json);
  }
});

All good up until this point. Now I can access the current_user information from the console by typing in App.metaData.current_user and also from handlebars by calling a specific attribute, i.e.:

{{App.metaData.current_user.email}}

and that email attribute shows up in the template. The problem comes when I am trying to access that global variable from within an ember controller. It seems so ridiculously easy, but I can't seem to access current_user from within any ember controller. I have tried:

currentUserBinding: 'App.metaData.current_user',

currentUser: function() {
  return App.metaData.current_user;
}.property(),

Ember.get('App.metaData.current_user')

and a few other methods, but can't seem to access it. It's bizarre that I can access current_user so easily from within the console and handlebars with a direct path, but not from within an ember controller. I must be missing something obvious.

Would appreciate any help!

Was it helpful?

Solution

In our app we do it same as @MilkyWayJoe suggested, but I think your approach is really interesting. Passing current_user thru JSON is a really elegant approach.

I've not experimented too much, but from what I can tell in your example the problem is nothing to do with the serializer. It's a problem with the computed property - you need to specify that it depends on App.metaData.current_user.

App.ApplicationController = Ember.Controller.extend({
  currentUser: function() {
    return Ember.get('App.metaData.current_user')
  }.property('App.metaData.current_user')
});

This tells ember that it should re-calculate the currentUser property whenever App.metaData.currentUser changes. Otherwise it will run the fx once (before your ajax returns) and cache the response.

OTHER TIPS

You can define a variable to represent the user id in a script tag. This should be done in the server template:

<script type="text/javascript">
    window.user_id = 1;
</script>

Then in your app, you can define a property in the ApplicationController which will store the current user model, and then you can find with the user_id variable:

window.App = Ember.Application.create();

App.store = DS.Store.create({
    revision: 12
});

App.User = DS.Model.extend({
    firstName: DS.attr('string'),
    lastName: DS.attr('string'),
    fullName: function() {
        return '%@ %@'.fmt(
            this.get('firstName'),
            this.get('lastName')
        );
    }.property('firstName', 'lastName')
});

App.ApplicationController = Em.Controller.extend({
    userInfo: null,
    init: function() {
        // this will fire a GET request to users_controller 
        this.set('userInfo', App.User.find(window.user_id));
    }
});

Then your template, you can use the properties in ApplicationController#userInfo.

<script type="text/x-handlebars">
    <h1>App</h1>
    {{userInfo.fullName}}
</script>

If you need to use this data from a route, you can use controllerFor, or if you need to access from another controller, you can use needs.

(see fiddle)

Just keep in mind this might not be the best solution for all scenarios as it adds one more request to your app initialization, but it does the trick for me right now.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top