Backbone.js and Rails - How to handle params from

2019-03-09 18:52发布

In a standard Rails controller, I'd create a record like this:

@user = User.new(params[:user])

This assumes that the form parameters that come in are nested.

I've been playing with Backbone.js and I noticed that by default, Backbone doesn't nest the parameters the way a normal Rails form might, which is actually something I expected. So I'm wondering what I should do...

Do I

figure out on the server-side if it's a request from Backbone by looking at accepts headers, etc and manipulate the params myself so I can keep my controller code small:

do_some_params_manipulation_with(params)
@user = User.new(params[:user])
respond_to do |format|
  if @user.save
    format.html {redirect_to users_url}
    format.json {render :json => @user.to_json }
  end
end

Or, do I instantiate the object in each branch which ends up with repeated code but might be more maintainable in the long run....

respond_to do |format|
  format.html do
    @user = User.new(params[:user])
    if @user.save
      redirect_to users_url
    end
  end

  format.json do
    @user = User.new(params) # and rely on mass-assignment protection
    if @user.save
      render :json => @user.to_json
    end
  end

end

or do I modify my Backbone.js models by overriding the .toJSON method (which I'm not entirely sure how to do because I don't know enough about Backbone.js yet) so that it nests the params?

In this situation, I have access to both sides of the app, but I am interested in what others are doing.

6条回答
爷的心禁止访问
2楼-- · 2019-03-09 19:18

If you are using the backbone-rails gem, looks like you can do

var User = Backbone.Model.extend({
   paramRoot: 'user'
});

Around line 45 on github

Credit PL J and stream 7 on this link

查看更多
相关推荐>>
3楼-- · 2019-03-09 19:27

It's nice when you can have the general Rails forms and Backbone forms match with respect to the root node. That's why in my last application I chose to override the Backbone models' toJSON method.

You could override the global toJSON method as Raimonds Simanovskis suggested. But even the non-DRY way approach isn't so bad. Just one line of boilerplate for each model definition:

// Depends on Underscore.js
User = Backbone.Model.extend({
  toJSON: function() {
    return { user: _.clone( this.attributes ) }
  },
  // Your other methods here
});

Edit: Corrected code sample. Sorry for the errors, I was translating from CoffeeScript to JavaScript.

查看更多
我欲成王,谁敢阻挡
4楼-- · 2019-03-09 19:31

In one of the answers to Rails mass assignment and Backbone.js there is mentioned patch https://gist.github.com/719080 which I think will do what you need.

查看更多
冷血范
5楼-- · 2019-03-09 19:32

I have made a little hack to namespace save requests under model.name property. It monkey patches toJSON() during sync() call only and restores original method so you can use it as usual.

I have implemented it in CoffeeScript.

Check it here

查看更多
可以哭但决不认输i
6楼-- · 2019-03-09 19:32

It should be noted that if you opt for the currently accepted answer (patching toJSON at the model level) you are affecting reading as well. Maybe that goes without saying, maybe not. But you will have a lot of work to do when rendering models/collections if you put this patch into affect in a backbone app. Therefore, I personally wouldn't use it as-is.

查看更多
兄弟一词,经得起流年.
7楼-- · 2019-03-09 19:39

As of Rails 3.1 there's now a new initializer called wrap_parameters.rb which handles this problem by default. The code that handle this case is:

# Disable root element in JSON by default.
ActiveSupport.on_load(:active_record) do
  self.include_root_in_json = false
end

Bada bing!

查看更多
登录 后发表回答