Last Updated: April 04, 2016
·
831
· tmartin314

Dynamic Model Attributes stored as a Hash

Create a text column named data on the model and serialize it as a hash:

class ProjectRequest < ActiveRecord::Base
  serialize :data, Hash
end

To create a form for this ProjectRequest model:

Use OpenStruct as it allows you to assign variable attributes to it on the fly. The fields will be stored as a Hash in the data attribute. This will also use the data property of the Model to fill the fields out when editing the Model.

= form_for ProjectRequest.new, remote: true do |f|
  = f.hidden_field :step, value: 1
  = f.fields_for :data, OpenStruct.new(f.object.data || {}) do |f2|
    = f2.text_field :expertise_sector
    = f2.text_field :expertise_country

Update the record and preserve existing data:

Found that we had to use deep_merge to merge the existing data with the passed params, otherwise it would be overwritten with just the data from the current form. (This is useful for multistep forms, or updating just one column via ajax)

def update
  ...
  @project_request.update(project_request_params.deep_merge(data: @project_request.data)
  ...
end