【问题标题】:Backbone model without collection. Sending duplicate data to server?没有集合的骨干模型。向服务器发送重复数据?
【发布时间】:2011-11-14 19:46:25
【问题描述】:

我有一个由 Rails 后端驱动的 Backbone 应用程序。我有一个Invitation 资源,我可以通过向邀请控制器的创建操作发送 POST 请求来发送邀请。

我的 Backbone 模型如下所示(coffeescript):

class Invitation extends Backbone.Model
  urlRoot: '/invitations'

然后是发送邀请的表单模板。我试图让它尽可能接近正常的 Rails 形式,因为 Rails 似乎能处理得最好:

<form action="/invitations" accept-charset="UTF-8" id="new_invitation" class="new_invitation" method="post">
  <input id="invitation_recipient_name" class="invitation_recipient_name" type="text" name="invitation[recipient_name]" />
  <input id="invitation_recipient_email" class="invitation_recipient_email" type="text" name="invitation[recipient_email]" />
  <input type="submit" class="btn primary" name="commit" id="invite" value="Send Invitation" />
</form>

这是该模型和模板的主干视图

class InvitationView extends Backbone.View
  # this is the template shown above
  template: JST['backbone/templates/invitation']
  events:
    'click #invite': 'sendInvite'

  render: ->
    $(this.el).html this.template()
    this
  sendInvite: (e) ->
    e.preventDefault()
    name = this.$('#invitation_recipient_name')
    email = this.$('#invitation_recipient_email')
    this.model.save
      recipient_name: name.val()
      recipient_email: email.val()

问题是当我单击提交按钮并调用sendInvite 方法时,我的服务器接收到具有以下结构的数据:

Parameters: {"recipient_name"=>"A name", "recipient_email"=>"name@example.com", "invitation"=>{"recipient_email"=>"name@example.com", "recipient_name"=>"A name"}}

现在这确实有效,因为我的 invitations#create 操作期望使用以下形式的参数:params[:invitations],这是 rails 的标准。然而,在请求中两次发送姓名和电子邮件这一事实似乎表明我的设置有问题。

我做错了什么还是正确的?

如果有人想看,这是我的控制器操作:

  # POST /invitations
  def create
    @invitation = current_user.sent_invitations.new params[:invitation]

    respond_to do |format|
      if @invitation.save
        format.json { render_for_api :invitation, json: @invitation, status: :created }
      else
        format.json { render json: @invitation.errors, status: :unproccessible_entity }
      end
    end
  end

编辑如果我在保存之前设置属性并记录它,这就是我的邀请模型的样子:

  Invitation
    _changed: false
    _changing: false
    _escapedAttributes: Object
      __proto__: Object
    _previousAttributes: Object
      recipient_email: "dave@example.com"
      recipient_name: "Dave"
      __proto__: Object
    attributes: Object
      recipient_email: "dave@example.com"
      recipient_name: "Dave"
      __proto__: Object
    cid: "c17"
    __proto__: ctor

该日志由以下代码生成:

sendInvite: (e) ->
    e.preventDefault()
    name = @$('#invitation_recipient_name')
    email = @$('#invitation_recipient_email')
    @model.set recipient_name: name.val(), recipient_email: email.val()
    console.log "THe model to save", @model

编辑 2
这就是我在路由器中实例化视图的方式。我应该如何更改它,以便 Backbone 自动跟踪我的模型属性,即使我没有从服务器获取和设置它们?。

  var TeamRouter = Backbone.Router.extend({
    routes: {
      'members': 'members'
    },

    members: function() {
      @invite = new MoveOutOrg.Models.Invitation();
      @inviteView = new MoveOutOrg.Views.InvitationView({
        model: @invite
      });
      $('#stage').append(@inviteView.render().el);
    }
  });

【问题讨论】:

  • 如果您在模型上设置值,然后在 sendInvite 方法中调用console.log(this.model),您会看到什么?
  • hmmm...您是否偶然使用了自定义 Backbone.sync 方法?
  • 不,我从来没有弄乱过 Backbone.sync。
  • 模型中有哪些属性(invitiation.attributes)?

标签: javascript ruby-on-rails ruby-on-rails-3 backbone.js javascript-framework


【解决方案1】:

params[:recipient_name]params[:recipient_email] 字段是您调用 model.save() 的结果。传入的参数是可选的。如果已经使用正确的值创建了模型,则无需传递任何内容即可保存。缺少的部分是您如何实例化视图。

我还将事件更改为"submit #new_invitation"。它更具描述性。您关心正在提交的表单......而不是他们点击了按钮。它还捕获了他们提交表单而不单击按钮(例如按回车键)的情况。

要将视图链接到模型,请使用initialize 方法。

initialize: ->
  @model.bind('change', @render)

要记住的基本事项是model 事件会通过集合和其他任何收听的人冒泡。所以现在当你保存时,如果任何属性被更改,change 事件将被触发,这将导致视图重新渲染。

【讨论】:

  • 好的。你能告诉我如何正确地实例化一个视图,以便 Backbone 将跟踪属性并将它们发送到服务器吗?当视图不是通过从服务器发送的数据实例化时(就像这里的情况),如果不将值显式传递给save 方法,我似乎无法让它发送任何东西。我用我用来实例化视图的代码附加了这个问题。
【解决方案2】:

我最近决定尝试使用 backbone-rails gem 的主干.js 并遇到了这个问题。解决方案是在模型中设置一个 paramRoot 选项:

class Invitation extends Backbone.Model
  urlRoot: '/invitations'
  paramRoot: 'invitation'

在 codebrew 中,出于某种原因,他们没有在自述文件中提及它,但参数包含在提供的生成器中。

【讨论】:

  • 注意:backbone-rails 修改了 vanillabackbone.js 以添加此功能。因此,它不适用于包含主干.js 的其他 gem/项目。
【解决方案3】:

params 中数据重复的原因是 Rails 中默认为 JSON 请求打开了 ActiveSupport.wrap_parameters 设置。在 Rails 项目中查看/config/initializers/wrap_parameters.rb

您可以通过更改禁用它:

ActiveSupport.on_load(:action_controller) do
  wrap_parameters format: [:json]
end

ActiveSupport.on_load(:action_controller) do
  wrap_parameters format: []
end

欲了解更多信息:http://guides.rubyonrails.org/action_controller_overview.html#parameters

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-17
    • 1970-01-01
    • 1970-01-01
    • 2012-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多