Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested strong parameters in rails - AssociationTypeMismatch MYMODEL expected, got ActionController::Parameters()

I'm rendering a model and it's children Books in JSON like so:

{"id":2,"complete":false,"private":false, "books" [{ "id":2,"name":"Some Book"},.....

I then come to update this model by passing the same JSON back to my controller and I get the following error:

ActiveRecord::AssociationTypeMismatch (Book (#2245089560) expected, got ActionController::Parameters(#2153445460))

In my controller I'm using the following to update:

@project.update_attributes!(project_params)

private

def project_params
    params.permit(:id, { books: [:id] } )
end

No matter which attributes I whitelist in permit I can't seem to save the child model.

Am I missing something obvious?

Update - another example:

Controller:

def create
    @model = Model.new(model_params)
end
def model_params
    params.fetch(:model, {}).permit(:child_model => [:name, :other])
end

Request:

post 'api.address/model', :model => { :child_model => { :name => "some name" } }

Model:

accepts_nested_attributes_for :child_model

Error:

expected ChildModel, got ActionController::Parameters

Tried this method to no avail: http://www.rubyexperiments.com/using-strong-parameters-with-nested-forms/

like image 538
Alan H Avatar asked Jan 31 '14 21:01

Alan H


People also ask

What is strong parameters in Rails?

Strong Parameters, aka Strong Params, are used in many Rails applications to increase the security of data sent through forms. Strong Params allow developers to specify in the controller which parameters are accepted and used.

What is params require in rails?

The require method ensures that a specific parameter is present, and if it's not provided, the require method throws an error. It returns an instance of ActionController::Parameters for the key passed into require . The permit method returns a copy of the parameters object, returning only the permitted keys and values.


3 Answers

Are you using accepts_nested_attributes_for :books on your project model? If so, instead of "books", the key should be "books_attributes".

def project_params
  params.permit(:id, :complete, :false, :private, books_attributes: [:id, :name])
end
like image 110
Josh Kovach Avatar answered Sep 26 '22 19:09

Josh Kovach


I'm using Angular.js & Rails & Rails serializer, and this worked for me:

Model:

  • has_many :features
  • accepts_nested_attributes_for :features

ModelSerializer:

  • has_many :features, root: :features_attributes

Controller:

  • params.permit features_attributes: [:id, :enabled]

AngularJS:

  • ng-repeat="feature in model.features_attributes track by feature.id
like image 28
user3712451 Avatar answered Sep 22 '22 19:09

user3712451


My solution to this using ember.js was setting the books_attributes mannualy.

In controller:

def project_params      
  params[:project][:books_attributes] = params[:project][:books_or_whatever_name_relationships_have] if params[:project][:books_or_whatever_name_relationships_have]
  params.require(:project).permit(:attr1, :attr2,...., books_attributes: [:book_attr1, :book_attr2, ....])

end

So rails checks and filters the nested attributes as it expected them to come

like image 23
Alexphys Avatar answered Sep 23 '22 19:09

Alexphys