4

我对一个看似简单的 ember 问题感到困惑。我正在使用active_model_serializers 元数据序列化从 rails 控制器序列化我的 rails current_user 方法,然后使用这个人的临时解决方案提取该 current_user 元 json 并将其设置为全局 ember 变量。

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

到目前为止一切都很好。现在我可以通过输入 App.metaData.current_user 从控制台访问 current_user 信息,也可以通过调用特定属性从把手访问,即:

{{App.metaData.current_user.email}}

并且该电子邮件属性显示在模板中。当我尝试从 ember 控制器中访问该全局变量时,问题就出现了。这看起来非常简单,但我似乎无法从任何 ember 控制器中访问 c​​urrent_user。我试过了:

currentUserBinding: 'App.metaData.current_user',

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

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

和其他一些方法,但似乎无法访问它。奇怪的是,我可以通过直接路径从控制台和车把中如此轻松地访问 current_user,但不能从 ember 控制器中访问。我一定遗漏了一些明显的东西。

将不胜感激任何帮助!

4

2 回答 2

7

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.

于 2013-04-18T01:43:52.997 回答
6

您可以定义一个变量来表示脚本标记中的用户 ID。这应该在服务器模板中完成:

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

然后在您的应用程序中,您可以在其中定义一个属性,该属性ApplicationController将存储当前用户模型,然后您可以find使用user_id变量:

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.

于 2013-04-18T00:26:24.133 回答