Reputation: 2804
I'm having problems saving a hash in my Rails 3 application. I can save it OK when using the console - it just doesn't work when I submit the hash through a form.
This SO question addresses it but the solution's not working for me. Moreover, if I use:
serialize :bulk_action, Hash
I get the error:
Attribute was supposed to be a Hash, but was a String
The hash, when saved through the form looks like this:
"{\"location\"=>{\"commands\"=>{\"custom_command_one\"=>\"true\", \"custom_command_two\"=>\"true\"}}}"
Whereas, through the console:
{"location"=>{"commands"=>{"custom_command_one"=>"true", "custom_command_two"=>"true"}}}
My database field is a text field. What's the best way to go about saving a hash through a form?
-- EDIT --
I've found I can sort of get around the problem if I use symbols not strings for the names but it still outputs one long string, not the hash.
Upvotes: 4
Views: 5412
Reputation: 416
I lately run over this kind of error too. The chain of causing actions were:
data
NOT NULL
the sqlite db-adapter from the build-matrix was failing, because it cannot allow default-value NULL
on a NOT NULL
restricted fielddefault: ''
instance.data = ''
as we upgraded on rails4“Attribute was supposed to be a Hash, but was a String”
, because there wasn't anything overwriting this faulty field-valueThe solution:
- add a migration with: change_column :model, :data, :text, default: '--- {}'
as a valid serializable empty default-value
Upvotes: 1
Reputation: 3868
From the link http://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/Serialization/ClassMethods.html#method-i-serialize
serialize(attr_name, class_name = Object)
[...] The serialization is done through YAML.
So the column should contain a YAMLized version of your bulk_action but '
"{\"location\"=>{\"commands\"=>{\"custom_command_one\"=>\"true\", \"custom_command_two\"=>\"true\"}}}"
Is not a YAML hash. If you want to muck around with the raw serialized data then you should use something like
"{\"location\"=>{\"commands\"=>{\"custom_command_one\"=>\"true\", \"custom_command_two\"=>\"true\"}}}".to_yaml
Upvotes: 0
Reputation: 466
I've not found correct answer too (YAML.dump, to_yaml - the same error in Rails 4.0.1). Only eval helps me. It's not a big security problem because I use it in admin pane.
params[:branch][:features_attributes][:primary] = eval params[:branch][:features_attributes][:primary]
params[:branch][:features_attributes][:secondary] = eval params[:branch][:features_attributes][:secondary]
if @branch.update_attributes(params[:branch]) ...
Upvotes: 0
Reputation: 25757
Can you switch to JSON within the textarea so that parsing it isn't so dangerous. Because what you would have to do is eval the respective params entry in a controller or the model which enables users to do whatever they want with the user under which your app is running. With JSON, you could just use JSON.parse
before setting the model attribute.
Upvotes: 1