Возможно, мое понимание того, как это должно работать, неверно, но я вижу строки, хранящиеся в моей БД, когда я ожидаю, что они будут jsonb array
. Вот как у меня настроены вещи:
Миграция
t.jsonb :variables, array: true
Модель
attribute :variables, :variable, array: true
Пользовательская ActiveRecord :: Тип
ActiveRecord::Type.register(:variable, Variable::Type)
Тип пользовательской переменной
class Variable::Type < ActiveRecord::Type::Json
include ActiveModel::Type::Helpers::Mutable
# Type casts a value from user input (e.g. from a setter). This value may be a string from the form builder, or a ruby object passed to a setter. There is currently no way to differentiate between which source it came from.
# - value: The raw input, as provided to the attribute setter.
def cast(value)
unless value.nil?
value = Variable.new(value) if !value.kind_of?(Variable)
value
end
end
# Converts a value from database input to the appropriate ruby type. The return value of this method will be returned from ActiveRecord::AttributeMethods::Read#read_attribute. The default implementation just calls #cast.
# - value: The raw input, as provided from the database.
def deserialize(value)
unless value.nil?
value = super if value.kind_of?(String)
value = Variable.new(value) if value.kind_of?(Hash)
value
end
end
Так что этот метод работает с точки зрения приложения. Я могу установить значение как variables = [Variable.new, Variable.new]
, и оно правильно хранится в БД и получает обратно как массив [Variable, Variable]
.
Что касается меня и корня этого вопроса, так это то, что в базе данных переменная хранится с использованием строк с двойным экранированием, а не объектов json:
{
"{\"token\": \"a\", \"value\": 1, \"default_value\": 1}",
"{\"token\": \"b\", \"value\": 2, \"default_value\": 2}"
}
Я ожидаю, что в них будет храниться нечто более похожее на объект json, например:
{
{"token": "a", "value": 1, "default_value": 1},
{"token": "b", "value": 2, "default_value": 2}
}
Причина этого в том, что, насколько я понимаю, будущие запросы к этому столбцу напрямую из БД будут выполняться быстрее / проще, если в формате json, а не в формате строки. Запросы через рельсы останутся без изменений.
Как мне заставить мою Postgres DB правильно хранить массив jsonb через рельсы?