Сохранение логических значений в активном хранилище записей

#ruby-on-rails

#ruby-on-rails

Вопрос:

Я использую стандартную форму rails для обновления ActiveRecord ::Store

   store :settings, accessors: %i[is_public]
 

Моя форма выглядит так:

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

Когда я смотрю на сохраненный хэш, они были преобразованы в строки, есть ли способ сохранить логический тип здесь?

Комментарии:

1. Есть ли причина, по которой это не является истинным атрибутом (т. Е. Хранится в таблице)? Если это так, вы можете перезаписать документы доступа

2. Я просто пытаюсь сохранить все свои пользовательские настройки в одном столбце, а не иметь много столбцов для более чем 30 параметров настроек, есть ли лучший способ?

3. Нет, это нормально и теперь более понятно, но в этом случае я бы рекомендовал перезаписать средство доступа, как показано в документах.

4. Я создал пользовательский модуль для добавления методов перезаписи средства доступа, как предлагает @engineersmnky (см. Ниже).

Ответ №1:

Я смог написать модуль CustomStoreAccessor для перезаписи средства доступа для этих атрибутов:

 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
 

Затем это позволяет мне добавлять эти методы в мою модель:

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

Комментарии:

1. поскольку ваши методы логически названы, я бы рекомендовал изменить boolean_store_accessor на super(value == 'true') и super() == 'true' соответственно, потому что, если это действительно должно быть логическим значением, я бы всегда ожидал логического значения. Также to_sym in "#{attr_name}=".to_sym не требуется, a String вполне приемлемо

2. Это действительно просто вызывает вопрос «Но почему?». Собственные типы JSON существуют уже много лет, и ваш драйвер преобразует логические значения и числа в столбцы JSON и из них без каких-либо этого.

Ответ №2:

Не использовать store . Ему вообще нет места, кроме как в устаревших приложениях.

Хранение сериализованных данных в столбце varchar / text является полностью устаревшим подходом, поскольку ваша база данных почти наверняка имеет собственный тип JSON / JSONB, к которому на самом деле можно эффективно запрашивать, тогда как сериализованные данные либо не подлежат запросу, если они упорядочены Ruby или YAML, либо требуют от вас де-сериализации данных во время запроса, еслиоказывается, оно хранится в виде строки JSON.

Драйвер базы данных также автоматически сериализует / десериализует столбец. Использование store или его двоюродного serialize брата фактически «преобразует его в два раза», так что в итоге вы получите строки JSON вместо реальных значимых типов, таких как объекты и массивы.

Если вы хотите создать средства доступа для «атрибутов» в объекте JSON, используйте store_accessor .

Комментарии:

1. Я хотел бы иметь возможность использовать столбец jsonb, но я должен был сказать, что причина, по которой я использую store, заключается в том, что я пытаюсь сохранить зашифрованный объект настроек, используя драгоценный камень lockbox. Пока мне не удалось заставить lockbox и JSON работать вместе. И lockbox говорит, что столбец должен быть текстовым. Есть ли лучший способ?

2. Это зависит от БД и требований — в Postgres вы можете использовать расширение pgcrypto вместе со столбцом bytea для шифрования «всего столбца» на стороне БД.