Posted over 1 year ago. Visible to the public.

ActiveRecord::Store: migrate data in store

When you need to store structured data (like Ruby hashes) in a single database column with ActiveRecord, a simple way is to use PostgreSQL's jsonb columns. ActiveRecord will automatically serialize and deserialize your Hash to and from JSON, and you can index JSON paths for fast reads.

As an alternative, ActiveRecord::Store offers a way to store hashes in a single database column. This card will show you how to migrate those hashes in an ActiveRecord::Migration by example:

Let's assume you have got a model User with settings stored as YAML in a single column:

class User < ActiveRecord::Base typed_store :settings, coder: YAML do |s| s.string :lang s.integer :show_number_of_posts end end

Note: in this example we used a typed_store, which basically is a store with type constraints.

Now you notice that the setting lang was not named well and you'd rather have language. So let's rename the settings key:

class RenameLanguageKeyInUser < ActiveRecord::Migration class User < ActiveRecord::Base def rename_settings_key!(from, to) from, to = from.to_s, to.to_s old_settings = YAML.load(self.settings) new_settings = old_settings.dup if new_settings.has_key?(from) new_settings[to] = new_settings.delete(from) self.update_attributes!(settings: YAML.dump(new_settings)) puts "Migrated User settings from #{old_settings.to_s} to #{new_settings.to_s}" else puts "Did not migrate User settings, '#{from}' was not a settings key" end end end def up User.find_each { |user| user.rename_settings_key!(:lang, :language) } end def down User.find_each { |user| user.rename_settings_key!(:language, :lang) } end end

Here are some key pointers of this migration:

  • you should never use your actual application models in migrations as those might change over time. That's why we embed the model into the migration
  • use the specified coder to deserialize/serialize your store
  • manipulate the data in between
  • the output is optional of course but might be helpful when you first test the migration and rollback

makandra has been working exclusively with Ruby on Rails since 2007. Our laser focus on a single technology has made us a leader in this space.

Owner of this card:

Daniel Straßner
Last edit:
over 1 year ago
by Thomas Eisenbarth
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Daniel Straßner to makandra dev
This website uses cookies to improve usability and analyze traffic.
Accept or learn more