Dav*_*ite 7 javascript ruby-on-rails javascript-framework backbone.js ruby-on-rails-3
我有一个由rails后端驱动的Backbone应用程序.我有一个Invitation资源,我可以通过向邀请控制器的创建操作发送POST请求来发送邀请.
我的Backbone模型看起来像这样(coffeescript):
class Invitation extends Backbone.Model
urlRoot: '/invitations'
Run Code Online (Sandbox Code Playgroud)
然后是表单发送邀请的模板.我试图尽可能接近普通的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>
Run Code Online (Sandbox Code Playgroud)
这是我的模型和模板的Backbone View
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()
Run Code Online (Sandbox Code Playgroud)
问题是当我单击提交按钮并sendInvite调用该方法时,我的服务器接收具有以下结构的数据:
Parameters: {"recipient_name"=>"A name", "recipient_email"=>"name@example.com", "invitation"=>{"recipient_email"=>"name@example.com", "recipient_name"=>"A name"}}
Run Code Online (Sandbox Code Playgroud)
现在这实际上有效,因为我的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
Run Code Online (Sandbox Code Playgroud)
编辑这是我的邀请模型,如果我设置属性并在保存之前记录它:
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
Run Code Online (Sandbox Code Playgroud)
该日志由以下代码btw生成:
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
Run Code Online (Sandbox Code Playgroud)
编辑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);
}
});
Run Code Online (Sandbox Code Playgroud)
和params[:recipient_name]字段params[:recipient_email]是您调用 的结果model.save()。传入的参数是可选的。如果模型已使用正确的值创建,则无需传递任何内容来保存。缺少的部分是如何实例化视图。
我还将事件更改为"submit #new_invitation". 它更具描述性。您关心的是正在提交的表单...而不是他们单击了按钮。它还捕获了他们在未单击按钮(例如按 Enter 键)的情况下提交表单的情况。
要将视图链接到模型,请使用initialize方法。
initialize: ->
@model.bind('change', @render)
Run Code Online (Sandbox Code Playgroud)
要记住的基本事情是,model事件通过集合冒泡并传递给其他正在收听的人。因此,现在当您保存时,如果任何属性发生更改,change将会触发一个事件,从而导致视图重新渲染。