'Storing booleans in Active Record Store

I am using a standard rails form to update an ActiveRecord::Store

  store :settings, accessors: %i[is_public]

My form looks like this:

<%= form.select(:is_public, options_for_select([['True', true], ['False', false]])) %>

When I look at the saved hash these have been converted to strings, is there a way to preserve the boolean type here?



Solution 1:[1]

I was able to write a CustomStoreAccessor module to overwrite the accessor for these attributes:

module CustomStoreAccessor
  def boolean_store_accessor(attr_name)
    define_method "#{attr_name}=" do |value|
      super(value=='true')
    end

    define_method attr_name do
       super()=='true'
    end
  end

  def integer_store_accessor(attr_name)
    define_method "#{attr_name}=" do |value|
      super(value.to_i)
    end

    define_method attr_name do
      super().to_i
    end
  end
end

This then allows me to add these methods to my model:

class Client < ApplicationRecord
  extend CustomStoreAccessor
  store :settings_object, accessors: %i[is_public max_sessions]
  boolean_store_accessor :is_public
  integer_store_accessor :max_sessions

Solution 2:[2]

Do not use store. It has no place at all except in legacy applications.

Storing serialized data in a varchar/text column is a completely outdated approach since you database almost certainly has a native JSON/JSONB type - which actually can be queried efficiently whereas serialized data is either non-queryable if its marshalled Ruby or YAML or requires you to de-serialize the data at query time if it happens to be stored as a JSON string.

The database driver will also automatically serialize/deserialize the column. Using store or its cousin serialize will actually "double convert" it so you end up with JSON strings instead of actual meaningful types such as objects and arrays.

If you want to create accessors for "attributes" in a JSON object use store_accessor.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 marc_s