【问题标题】:backbone model saving, validation fails骨干模型保存,验证失败
【发布时间】:2012-12-30 09:28:29
【问题描述】:

没有多少谷歌搜索能够解决我的困惑,所以我想我会在这里问这个问题。

我正在尝试保存模型并使用成功/错误回调。在backbone documentation 上,它声明您保存模型,如下所示:model.save([attributes], [options])

我在文档中找不到任何地方告诉您如何保存整个模型(即不指定属性),但遇到了this question,第二个答案说要保存整个模型,您可以这样做model.save({}, [options]) .

但是我尝试这样做无济于事。我的代码如下:

主干模型:

class Student extends Backbone.Model
  url: ->
    '/students' + (if @isNew() then '' else '/' + @id)

  validation:
    first_name:
      required: true
    last_name:
      required: true
    email:
      required: true
      pattern: 'email'

  schema: ->
    first_name:
      type: "Text"
      title: "First Name"
    last_name:
      type: "Text"
      title: "Last Name"
    email:
      type: "Text"
      title: "Email"

在我看来,我有以下功能:

class Students extends CPP.Views.Base
  ...
  saveModel = ->
    console.log "model before", @model.validate()
    console.log "model attrs", @model.attributes
    @model.save {},
      wait: true
      success: (model, response) ->
        notify "success", "Updated Profile"
      error: (model, response) =>
        console.log "model after", @model.validate()
        console.log "model after is valid", @model.isValid()
        console.log "response", response
        notify "error", "Couldn't Update"

在保存之前的第一个 console.log 中,我被告知模型是有效的,通过 undefined 响应。如果我确实查看模型,我可以看到所有三个字段都已填写。

类似地,在接下来的两个控制台日志中,错误@model.validate()@model.isValid() 都分别返回undefinedtrue。 但是我尝试保存模型得到的响应是Object {first_name: "First name is required", last_name: "Last name is required", email: "Email is required"}

最后在我得到的模型属性的console.log中:

Object
  created_at: "2012-12-29 23:14:54"
  email: "email@email.com"
  first_name: "John"
  id: 2
  last_name: "Doe"
  type: "Student"
  updated_at: "2012-12-30 09:25:01"
  __proto__: Object

这让我相信,当我将 {} 传递给我的模型时,它实际上是在尝试将属性保存为 nil,否则为什么会出错?

有人可以指出我做错了什么吗?我宁愿不必将每个属性单独传递给保存!

提前致谢

【问题讨论】:

    标签: backbone.js coffeescript


    【解决方案1】:

    根据Hui Zheng 的建议答案,我修改了服务器中的控制器,以 JSON 格式返回学生。

    然而,为了找到问题的真正根源,我在保存时阅读了backbone documentation,发现当wait: true 作为选项提供时,它会执行以下操作:

    if (!done && options.wait) {
            this.clear(silentOptions);
            this.set(current, silentOptions);
    }
    

    进一步调查清楚我发现

    clear: function(options) {
      var attrs = {};
      for (var key in this.attributes) attrs[key] = void 0;
      return this.set(attrs, _.extend({}, options, {unset: true}));
    },
    

    从这里看起来好像每个属性都被清除然后被重置。然而,在清除我的模型时,我编写的验证将失败(因为需要 first_namelast_nameemail)。

    backbone.validation documentation 上,我们被告知可以使用参数forceUpdate: true,因此我在保存模型时选择使用此参数。我现在假设(尽管这可能不是一个好的做法)来自服务器的数据是正确的,因为这也已经过验证。

    因此我的最终代码是:

    saveModel = ->
      @model.save {},
        wait: true
        forceUpdate: true
        success: (model, response) ->
          notify "success", "Updated Profile"
        error: (model, response) ->
          notify "error", "Couldn't Update"
    

    【讨论】:

    • 我有点困惑。我以为您使用的是 Backbone 0.9.1 或 0.9.2,因为方法 isValid 已在版本 0.9.9 中删除。但是现在您引用的是 Backbone 0.9.9 中的代码 sn-p。据我所知,clear 方法在 0.9.9 之前的 save 方法中没有被调用。实际上clear 方法甚至在最新的 0.9.9(raw.github.com/documentcloud/backbone/master/backbone.js) 中已经被删除。更糟糕的是,方法isValid 在这个最新版本中复活了。那么您实际使用的是哪个版本?
    • 0.9.9,但现在我很困惑。该文档谈到了明确的内容,实际上是更改日志(backbonejs.org/)does 确实说 isValid 已被删除,但正如您指出的那样,最新版本仍然包含 isValid。
    • 作为一个快速更新,我意识到我的 isValid 来自主干验证 (github.com/thedersen/backbone.validation),而不是主干本身
    【解决方案2】:

    您确定在save 之前已正确设置模型的属性吗?即使没有设置它的属性,它仍然可以通过validate(取决于validate 函数的定义方式)。请尝试在控制台中打印模型以验证这一点。顺便说一句,在save 中最好传递null 而不是{},这样就不会调用模型的set 方法。

    更新:

    根据Backbone的源代码,如果将null作为save的第一个参数传递,则模型的属性将保持不变,直到模型成功保存在服务器上。所以另一种可能是你的服务器成功保存了模型但是返回了一个损坏的对象,导致模型的set方法失败。如果仍然无法解决问题,跟踪model.set 方法可能会有所帮助。

    【讨论】:

    • 我之前在我的问题中添加了模型的日志供您查看。将 {} 更改为 null 似乎也没有帮助,但我会在我的模式下更改它以获得更好的做法
    • @SarahTattersall 我刚刚更新了我的答案,请检查是否有帮助。
    • 这是一个 PUT 请求,所以我在 Rails 控制器中用 head :no_content 响应。我已经尝试过 respond_with @student ,但这似乎也不能解决它?当它是 PUT 请求时,我对与学生进行响应也有点怀疑?
    • @SarahTattersall 如果您在save 中传递了null{},则服务器有责任响应具有所有更新属性的对象。之后,Backbone 将调用model.parse(response, xhr)(默认只返回传入的响应)并使用返回的值来设置模型的属性。如果服务器返回适当的 JSON 对象,您的问题可能会得到解决。顺便说一句,在 PUT 请求中响应学生对象是完全合理的。
    • @SarahTattersall 如果您仍然无法解决问题,跟踪model.set 方法可能会有所帮助。
    猜你喜欢
    • 2012-02-13
    • 1970-01-01
    • 2013-07-23
    • 2012-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-19
    • 1970-01-01
    相关资源
    最近更新 更多