Search code examples
ruby-on-railsdatabaseserializationruby-on-rails-4strong-parameters

How to permit the proper storage of serialized arrays?


I am using Rails 4.0.0 and I am trying to properly store a serialized array to the database permitting values with the StrongParameters gem. That is, I have:

# Model class
class Article < ActiveRecord::Base
  serialize :links, Array

  ...
end

# Controller class
class ArticlesController < ApplicationController
  ...

  def update
    ...
    @article.update_attributes(article_params)
    ...
  end


  private

  def article_params
    params.require(:article).permit(<PERMITTED_PARAMETERS>) # Keep reading for more information.
  end
end

From the view submitted parameters are:

"links"=>{"0"=>{"name"=>"Web Site Name 0", "url"=>"www.website0.com"}, "1"=>{"name"=>"Web Site Name 1", "url"=>"www.website1.com"}, "2"=>{"name"=>"Web Site Name 2", "url"=>"www.website2.com"}, "3"=>{"name"=>"", "url"=>""}, "4"=>{"name"=>"", "url"=>""}, "5"=>{"name"=>"", "url"=>""}}}

In the above code, in place of <PERMITTED_PARAMETERS> I tried to put in turn the following:

:links => [:name, :url]
[:links => [:name, :url]]
{:links => [:name, :url]}
[{:links => [:name, :url]}]

In all the above cases the StrongParameters correctly permits values without raising errors, however in my database it is always stored the following serialized data:

---
- !ruby/hash:ActionController::Parameters
  name: Web Site Name 0
  url: www.website0.com
- !ruby/hash:ActionController::Parameters
  name: Web Site Name 1
  url: www.website1.com
- !ruby/hash:ActionController::Parameters
  name: Web Site Name 3
  url: www.website2.com

What !ruby/hash:ActionController::Parameters means? Is it correct? If no, how can I store data the proper way? Is it the StrongParameters gem to cause that strange behavior?

Note: All seems to work in my system even if data is "strange".


Solution

  • This could lead to an issue if you're loading your data outside of rails, when ActionController::Parameters isn't defined. Outside of that, this means you get an ActionController::Parameters object instead of a Hash. Since they both behave the same way, you can just use them similarly.

    For now, if you need a hash anyway, you should be able to do the following in your model:

    before_save :serialize_to_hash
    def serialize_to_hash
      self.links = self.links.to_hash
    end