Ответ 1
Да, ActiveRecord позволяет использовать поля Postgres json
просто как хэши в своих моделях. Однако есть несколько вещей, которые следует учитывать:
-
Хеш может быть NULL при инициализации
В вашей миграцииcreate_table
вы разрешаете поле:game_board
бытьNULL
. Таким образом, при первом использовании поле:game_board
вашего экземпляра модели будетNULL
, и вы должны сначала инициализировать Hash перед его использованием. (См. Пример ниже) -
В JSON все клавиши являются строками
Таким образом, при сохранении (и перезагрузке) все ключи будут преобразованы в строки, если раньше вы использовали Символы или Числа. Таким образом, для предотвращения нежелательного поведения рекомендуется использовать String-ключи, если ваш ORM не настроен для обозначения всех ключей.
Ваши примеры:
self.game_board ||= {}
self.game_board[:player1] = 1
self.game_board[:cards] = cards.to_hash
# after reload from database (access via String-key):
self.game_board['player1'] # And retrieve value 1 (that we put here before)
@Производительность:
-
Да, каждый раз, когда ActiveRecord считывает запись из базы данных и создает экземпляр модели, JSON-поля получают unserialized в хэши. Но если вы считаете, что это поражает ваше приложение, вы должны либо использовать текстовое поле, либо сериализовать/десериализовать JSON/хэши, когда вам нужно, или, что еще лучше, вообще не использовать ActiveRecord. Создавая кучи классов и используя магические методы, ActiveRecord создает так много накладных расходов, что вам не следует беспокоиться о десериализации JSON. У удобства есть свои затраты.
-
Да, каждый раз, когда вы изменяете значение в Hash, (целое) JSON-поле заменяется и обновляется новой сериализованной версией.
Две заметки об этом:- Даже в Postgres (не только в ActiveRecord) возможность выполнения обновлений некоторых JSON-элементов отсутствует до сих пор. fooobar.com/info/550736/...
- В общем, JSON-поля должны использоваться с фиксированной структурой или, по крайней мере, в управляемых размерах, а тип поля не должен быть хранилищем документов, например, например. в MongoDB. Сравните документацию Postgres