【问题标题】:Ember.js Railscast #410 undefined is not a function TypeError: at RandomRaffle.EntriesRoute.Ember.Route.extend.setupControllerEmber.js Railscast #410 undefined is not a function TypeError: at RandomRaffle.EntriesRoute.Ember.Route.extend.setupController
【发布时间】:2026-01-07 11:50:01
【问题描述】:

我正在关注 Ember.js Railscast 第 410 集。当我更改我的 router.js 文件时

RandomRaffle.EntriesRoute = Ember.Route.extend({
  setupController: function (controller) {
    controller.set('content', []);
  }

});

到这里

RandomRaffle.EntriesRoute = Ember.Route.extend({
  setupController: function (controller) {
    controller.set('content', RandomRaffle.Entry.find());
  }

});

我得到错误:

处理路由时出错:条目未定义不是函数类型错误:未定义不是 RandomRaffle.EntriesRoute.Ember.Route.extend.setupController 的函数

我的模型/entry.js 文件包含:

RandomRaffle.Entry = DS.Model.extend({
  name: DS.attr('string'),
  winner: DS.attr('boolean')
});

我的控制器/entries_controller.js 包含:

RandomRaffle.EntriesController = Ember.ArrayController.extend({
// newEntryName: "",

  actions: {

    addEntry: function () {
      RandomRaffle.Entry.createRecord({name: this.get('newEntryName')});
      this.set('newEntryName', "");
    },

    drawWinner: function () {
      this.setEach('highlight', false);
      var pool = this.rejectBy('winner');
      if (pool.length > 0){
        var entry = pool[Math.floor(Math.random() * pool.length)];
        entry.set('winner', true);
        entry.set('highlight', true);
        this.get('store').commit();
      }
    }

  }
});

javascripts/store.js

RandomRaffle.Store = DS.Store.extend({});

// Override the default adapter with the `DS.ActiveModelAdapter` which
// is built to work nicely with the ActiveModel::Serializers gem.
RandomRaffle.ApplicationAdapter = DS.ActiveModelAdapter.extend({});

我错过了什么?

【问题讨论】:

  • 我认为您必须在 model 挂钩中使用 find。在setupController 之前,添加一个名为model 的函数,即return RandomRaffle.Entry.find()
  • @MilkyWayJoe 我尝试使用返回 RandomRaffle.Entry.find() 的模型函数添加和替换 setupController。我得到了同样的错误。
  • 对于以随机代码编辑此帖子的任何人,请知道在问题中添加代码是不可接受的。唯一可行的情况是 OP 在 cmets 中提供了代码,而忽略了将其包含在问题本身中。
  • @BradleyDotNET 不幸的是我。我无法保持登录状态,因此我错误地将代码添加为匿名。抱歉,感谢您的关注。
  • 没问题。请注意,该编辑应该已在审核队列中被拒绝(当然不是,但那是一个不同的问题...),因此您需要确保以您自己的身份进行编辑,以便它们实际出现:)。

标签: javascript ember.js ember-data


【解决方案1】:

如果您的store 定义正确,您应该在您的route 中创建一个model 函数,类似于:

RandomRaffle.EntriesRoute = Ember.Route.extend({
  model: function() {
       return RandomRaffle.Entry.find(); 

       // This is deprecated. Latest versions of ember-data use the following:
       // return this.store.find('entry');

       // this method returns a promise that will
       // carry the model data once it resolves
       // This is internally passed as a param of `setupController`
  },
  setupController: function (controller, model) {

       controller.set('content', model);
       // this is the same as the default implementation, so if you're *NOT* doing
       // anything different than this, get rid of `setupController` altogether

       // the `model` param, is the return of the `model` function just above. 
       // It is returned a `promise` rather than data, and will be made 
       // available once the promise is resolved, materializing the records 

       // the param doesn't have to be called `model`, but the 
       // function above *HAS* to be named `model` 
  }

});

我不是 100% 确定,但我相信错误可能正在发生,因为您调用 RandomRaffle.Entry.find() 而应该是 this.store.find('entry')

【讨论】:

  • 这解决了我的错误。我是否正确假设 RandomRaffle.Entry.createRecord({name: this.get('newEntryName')});应该改为 this.store.createRecord('entry', {name: this.get('newEntryName')});也一样?
  • 是的。根据guides 应该是this.store.createRecord('modelName', { key1: 'value1', keyN: 'valueN'});
  • addEntry 函数按预期工作,并在我最后添加 save() 时持续存在。我的新错误是:Uncaught TypeError: undefined is not a function。错误发生在 this.get('store').commit();。我试过 this.store.save() 和 this.get('store').save()。有什么想法吗?
  • 你必须在模型记录上调用save。为此,您将createRecord 分配给一个变量,也许您想将其称为“条目”,那么它就是var entry = this.store.createRecord('entry', {...}); entry.save();。但是,嘿.. 也许,只是也许,你想去看看guides
【解决方案2】:

models/entry.js 和 store.js 文件在原始问题中是正确的。另外...

路由器.js

RandomRaffler.EntriesRoute = Ember.Route.extend({

    model: function() {
       return this.store.find('entry');
   }
});

entries_controller.js

RandomRaffler.EntriesController = Ember.ArrayController.extend({

actions: {
    addEntry: function(name) {
        //Create the entry record
        var entry = this.store.createRecord('entry', {
            name: name,
            winner: false
        });
        // Save the changes
        entry.save();           
    },

此外,您可能会在您的 rails 服务器日志中注意到 csrf 令牌存在问题,可以通过将此代码放在 rails 控制器文件(例如 entries_controller.rb)的前几行来解决此问题

skip_before_action :verify_authenticity_token

Railscast 项目的完整应用程序可以在https://github.com/markwiggles/raffler找到

【讨论】: