Trunk model without collection. Sending duplicate data to the server?

I have a Backbone application running on a log of rails. I have an Invitation resource, and I can send invitations by sending a POST request for the action of the invitation controller action.

My Backbone model looks like this (coffeescript):

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

The following is a form template for sending an invitation. I tried to make this as close as possible to conventional rail forms, as it seems that Rails will handle this best of all:

 <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> 

Here is my Backbone View for this model and template.

 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() 

The problem is that when I click the submit button and the sendInvite method is sendInvite , my server receives data with the following structure:

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

Now it really works, since my invitations#create action involves working with form parameters: params[:invitations] , this is the standard for rails. However, the fact that the name and email address are sent twice in the request seems like a sign that something is wrong with my setup.

Am I doing something wrong or is it right?

Here is my controller action if someone wants to see it:

  # 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 

Change This looks like my invitation model if I set the attributes and write them right before saving:

  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 

This log is generated by the following btw code:

 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 

Edit 2
This is how I create my view in my router. How can I change this so that Backbone automatically tracks my model attributes even if I do not receive and install them from the server?

  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); } }); 
+7
source share
3 answers

The params[:recipient_name] and params[:recipient_email] model.save() are the result of your call to model.save() . Passed parameters are optional. You do not need to transfer anything to save if the model is already created with the correct values. The downside is the way you created the view.

I would also change the event to "submit #new_invitation" . This is more descriptive. You care about the submitted form ... not that they pressed a button. It also catches a case when they submit a form without pressing a button (for example, by pressing a key).

To associate a view with a model, use the initialize method.

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

The main thing to remember is that model events accumulate through collections and listen to someone else. So now, when you save, if any of the properties has been changed, the change event will change , which will then lead to a re-rendering of the view.

+2
source

The reason for the duplication of data in the parameters is due to the fact that, by default, the ActiveSupport.wrap_parameters parameter ActiveSupport.wrap_parameters included in Rails for JSON requests. Check out /config/initializers/wrap_parameters.rb in a Rails project.

You can disable it by changing:

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

to

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

For more information: http://guides.rubyonrails.org/action_controller_overview.html#parameters

+1
source

I recently decided to try backbone.js with the backbone-rails gem and ran into this problem. The solution is to set the paramRoot parameter in the model:

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

For some reason, they do not mention it in readme in the codeber, but the parameter is included in the provided generators.

0
source

All Articles