Reputation: 119
I have Backbone.js collection and model for a project object:
window.Project = Backbone.Model.extend();
window.Projects = Backbone.Collection.extend({
model: Project,
url: '/projects'
});
I have setup a rails controller to respond to the Backbone.js collection:
class ProjectsController < ApplicationController
def index
render :json => Project.all
end
def create
project = Project.create! params
render :json => project
end
end
Index works fine and I get a list of projects in my web app. The problem is if I try and create a model on the Projects collection I get a 500 error from the server.
The error message on the server is as follows:
Started POST "/projects" for 127.0.0.1 at 2011-08-21 08:27:56 +0100
Processing by ProjectsController#create as JSON
Parameters: {"title"=>"another test"}
Completed 500 Internal Server Error in 16ms
ActiveRecord::UnknownAttributeError (unknown attribute: action):
app/controllers/projects_controller.rb:8:in `create'
I am not sure what the unknown attribute: action
is referring to.
For info I have set up the projects_controller
as resources :projects
. I have also set rails to ActiveRecord::Base.include_root_in_json = false
.
Upvotes: 4
Views: 1600
Reputation: 2726
You can enable parameter wrapping. Add a file in the initializer directory with:
ActiveSupport.on_load(:action_controller) do
wrap_parameters format: [:json]
end
and, for json request, you post params will now be wrapped with the model name.
Upvotes: 0
Reputation: 434596
Yes, Rails always adds the action
and controller
to params
. The parameters come from ActionDispatch::Http::Parameters:
def parameters
@env["action_dispatch.request.parameters"] ||= begin
params = request_parameters.merge(query_parameters)
params.merge!(path_parameters)
encode_params(params).with_indifferent_access
end
end
And path_parameters
:
Returns a hash with the parameters used to form the path of the request. Returned hash keys are strings:
{'action' => 'my_action', 'controller' => 'my_controller'}
So you shouldn't be doing project = Project.create! params
. You could go the update_attributes
route:
project = Project.new
project.update_attributes params[:model_name]
But this assumes that you have what you need in a sub-hash of params
and it won't call your validators. Backbone won't namespace your attributes by default but you could override Backbone.sync
and do it yourself. Still, you probably want your validations so update_attributes
should generally be avoided.
Your best bet is to pull exactly the attributes out of params
that you're expecting to be there. This is even the Backbone recommended practise:
*(In real code, never use update_attributes blindly, and always whitelist the attributes you allow to be changed.)*
Upvotes: 5