0

我正在关注这个示例https://github.com/codebrew/backbone-rails#example-usage以获取主干导轨 gem。它适用于具有一个单词名称的模型,但Uncaught TypeError: Cannot call method 'bind' of undefined如果我尝试对具有两个名称的模型遵循相同的模式,则会出现错误。这是我所做的:

rails new blog

然后我将rails-backbonegem 添加到 Gemfile

bundle install

rails g backbone:install

rails g scaffold FriendRequest sender_gender:string recipient_gender:string

rake db:migrate

rails g backbone:scaffold FriendRequest sender_gender:string recipient_gender:string

我的app/views/friend_requests/index.html.erb文件如下所示:

<h1>Listing friend_requests</h1>

<table>
  <tr>
    <th>Sender gender</th>
    <th>Recipient gender</th>
    <th></th>
    <th></th>
    <th></th>
  </tr>

<% @friend_requests.each do |friend_request| %>
  <tr>
    <td><%= friend_request.sender_gender %></td>
    <td><%= friend_request.recipient_gender %></td>
    <td><%= link_to 'Show', friend_request %></td>
    <td><%= link_to 'Edit', edit_friend_request_path(friend_request) %></td>
    <td><%= link_to 'Destroy', friend_request, method: :delete, data: { confirm: 'Are you sure?' } %></td>
  </tr>
<% end %>
</table>

<br />

<%= link_to 'New Friend request', new_friend_request_path %>


<div id="friend_requests"></div>

<script type="text/javascript">
  $(function() {
    // Blog is the app name
    window.router = new Blog.Routers.FriendRequestRouter({friend_requests: <%= @friend_requests.to_json.html_safe -%>});
    Backbone.history.start();
  });
</script>

当我点击时,http://localhost:3000/friend_requests我收到此错误

Uncaught TypeError: Cannot call method 'bind' of undefined 

我从控制台复制了代码,其中显示了内部错误。我不确定 StackOverflow 的正确协议是否有这样的错误,但你可以看到它,它被 * 包围。如果有人想编辑这个问题以正确显示,那将不胜感激。

(function() {
  var _base,
    __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

  (_base = Blog.Views).FriendRequests || (_base.FriendRequests = {});

  Blog.Views.FriendRequests.IndexView = (function(_super) {

    __extends(IndexView, _super);

    function IndexView() {
      this.render = __bind(this.render, this);

      this.addOne = __bind(this.addOne, this);

      this.addAll = __bind(this.addAll, this);
      return IndexView.__super__.constructor.apply(this, arguments);
    }

    IndexView.prototype.template = JST["backbone/templates/friend_requests/index"];

    IndexView.prototype.initialize = function() {
      return this.options.friendRequests.bind('reset', this.addAll);
***Uncaught TypeError: Cannot call method 'bind' of undefined***
    };

    IndexView.prototype.addAll = function() {
      return this.options.friendRequests.each(this.addOne);
    };

    IndexView.prototype.addOne = function(friendRequest) {
      var view;
      view = new Blog.Views.FriendRequests.FriendRequestView({
        model: friendRequest
      });
      return this.$("tbody").append(view.render().el);
    };

    IndexView.prototype.render = function() {
      $(this.el).html(this.template({
        friendRequests: this.options.friendRequests.toJSON()
      }));
      this.addAll();
      return this;
    };

    return IndexView;

  })(Backbone.View);

}).call(this);

index_view.js.coffee最后,产生上述错误的咖啡脚本文件是

Blog.Views.FriendRequests ||= {}

class Blog.Views.FriendRequests.IndexView extends Backbone.View
  template: JST["backbone/templates/friend_requests/index"]

  initialize: () ->
    @options.friendRequests.bind('reset', @addAll)

  addAll: () =>
    @options.friendRequests.each(@addOne)

  addOne: (friendRequest) =>
    view = new Blog.Views.FriendRequests.FriendRequestView({model : friendRequest})
    @$("tbody").append(view.render().el)

  render: =>
    $(@el).html(@template(friendRequests: @options.friendRequests.toJSON() ))
    @addAll()

    return this

我假设这只是一些简单的事情,比如没有对具有两个名称的模型使用正确的大写或其他约定,但我似乎无法弄清楚。

提前致谢!

编辑 - - -

我只是想到了这一点,但我会密切关注我的app/views/friend_requests/index.html.erb文件,因为它是我实际手动编辑代码的地方。其他一切都是由rails-backbonegem 自动生成的。

--------编辑#2-------------

根据第一条评论询问 IndexView 的实例化位置,它位于/app/assets/javascripts/backbone/routers/friend_requests_router.js.coffee

class Blog.Routers.FriendRequestsRouter extends Backbone.Router
  initialize: (options) ->
    @friendRequests = new Blog.Collections.FriendRequestsCollection()
    @friendRequests.reset options.friendRequests

  routes:
    "new"      : "newFriendRequest"
    "index"    : "index"
    ":id/edit" : "edit"
    ":id"      : "show"
    ".*"        : "index"

  newFriendRequest: ->
    @view = new Blog.Views.FriendRequests.NewView(collection: @friend_requests)
    $("#friend_requests").html(@view.render().el)

  index: ->
    @view = new Blog.Views.FriendRequests.IndexView(friend_requests: @friend_requests)
    $("#friend_requests").html(@view.render().el)

  show: (id) ->
    friend_request = @friend_requests.get(id)

    @view = new Blog.Views.FriendRequests.ShowView(model: friend_request)
    $("#friend_requests").html(@view.render().el)

  edit: (id) ->
    friend_request = @friend_requests.get(id)

    @view = new Blog.Views.FriendRequests.EditView(model: friend_request)
    $("#friend_requests").html(@view.render().el)
4

1 回答 1

0

您的路由器会这样做:

index: ->
  @view = new Blog.Views.FriendRequests.IndexView(friend_requests: @friend_requests)
  #...

注意friend_requests:部分。但是,您Blog.Views.FriendRequests.IndexView总是在寻找@options.friendRequests

initialize: () ->
  @options.friendRequests.bind('reset', @addAll)

Backbone 将负责@options

创建新视图时,您传递的选项将附加到视图中this.options,以供将来参考。

但它不会将带下划线的名称转换为驼峰式名称。您的视图应该查看@options.friend_requests而不是@options.friendRequests(或friendRequests:在实例化您的视图时使用)。对于变量,您可能只想坚持一种命名约定(小写和下划线或驼峰式)。下划线在 Ruby 和 Rails 中更常见,所以这可能是一个不错的选择(OTOH,camel-case 在 JavaScript 中很常见,所以......)。

PS:Backbone 视图已经有一个 jQuery 版本的@elin@$el所以你不必去$(@el)任何地方,只需使用@$el.


Backbone 1.1.0 更新:从 1.1.0 开始,Backbone 视图不再this.options自动设置为视图的选项,如果你想要这种行为,那么你必须自己做:

initialize: (options) ->
  @options = options
  #...

或者:

initialize: (@options) ->
  #...

您还可以从options需要的选项中获取选项并丢弃其余选项:

initialize: (options) ->
  @friend_requests = options.friendRequests
  #...

我更喜欢后一种方法,因为它使您的视图选项非常明确且易于跟踪。

于 2012-11-04T00:25:33.840 回答