NielMalhotra
NielMalhotra

Reputation: 1375

Modifying the params hash in Rails

I'm creating a nested model in Rails, but I want to add fields to the nested models in the controller. I'm not using hidden_field_tag since it could be tampered with.

Here is my params hash:

 Parameters: {"dummy"=>{"users_attributes"=>{"0"=>{"email"=>"[email protected]", "id"=>"", "_destroy"=>"false"}, "1"=>{"email"=>"[email protected]", "id"=>"", "_destroy"=>"false"}}}, "commit"=>"Create Dummy"}

What I want is for there to be a field under each user_attributes called companyid. Let's say I wanted companyid to be "company", then I thought that this would work:

len = params["dummy"]["users_attributes"].size
 counter = 0
 while counter < len
  params["dummy"]["users_attributes"][counter]["companyid" => "company"]
  counter = counter + 1
end

But, I get "undefined method `[]' for nil:NilClass" error for the first line in the while loop. I'm not exactly sure why.

Can someone help me out so I can modify the params hash?

EDIT: So, I finally figured it out. I didn't really use any of the solutions exactly. First, I set a hidden_field tag to be blank for companyid. Then, in my controller I put:

 params["dummy"]["users_attributes"].each do |key, val|
  params["dummy"]["users_attributes"][key]["companyid"] = "company"
 end

Not the most elegant code, but it'll work.

Upvotes: 6

Views: 7150

Answers (3)

Tom Harrison
Tom Harrison

Reputation: 14078

The params hash is special since (especially with forms) is it mapped one-for-one with the model(s) it is related to, and Rails expects there to be either a database column, or a method in the model having that name.

Hidden fields are the typical solution to the problem of getting at additional data, but if you don't want users to see those fields, you run into the problem that HTTP is stateless. So in this case, the session[:something] is your friend. Before displaying a form or page that may have hidden data, instead add the data to a session variable (encrypt it first), which you can then read (and decrypt) when the user submits the form. Or you can save it in a database table and put only the row id in the session so the data can be read back when the form is posted.

If the data was part of the model, but you just didn't want to display it, you could just display the parts the user could see in the view, but then look up the rest of it in the controller action when the user submitted the form or request.

If the data is not sensitive you can just make sure to declare the values that the user can change as attr_accessible in their respective models (prevents mass assignment) and put the others in hidden fields.

Upvotes: 4

MrDanA
MrDanA

Reputation: 11647

That's not how hashes work. Try this:

params["dummy"]["users_attributes"][counter]["companyid"] = "company"

EDIT In addition to fl00r's answer, yes, you'd have to set ["companyid"] to be {} first.

Upvotes: 0

fl00r
fl00r

Reputation: 83680

This looks ugly and I don't understand what is going on, but your mistake is:

len = params["dummy"]["users_attributes"].size
counter = 0
while counter < len
  params["dummy"]["users_attributes"][counter] = { "companyid" => "company" }
  counter = counter + 1
end

I believe you should use accepts_nested_attributes_for here and initialize new companies in controller, not this ugly code

http://railscasts.com/episodes/196-nested-model-form-part-1

http://railscasts.com/episodes/197-nested-model-form-part-2

Upvotes: 0

Related Questions