Ruby on RailsMiddleCoding

Что такое метод serialize в ActiveRecord и когда его следует избегать?

serialize сохраняет объект Ruby (Hash, Array) в текстовое поле БД как YAML/JSON. Избегайте его, когда нужна фильтрация, индексация или типобезопасность — используйте jsonb-колонку или отдельную таблицу.

serialize в ActiveRecord

Что это и как работает

serialize позволяет хранить произвольные Ruby-объекты (Hash, Array, custom class) в текстовой или бинарной колонке БД. При чтении ActiveRecord автоматически десериализует значение обратно в Ruby-объект.

# Старый способ (Rails < 7.1) — YAML по умолчанию
class UserProfile < ApplicationRecord
  serialize :preferences, Hash
  serialize :tags, Array
end

# Запись
profile = UserProfile.create(
  preferences: { theme: "dark", notifications: true },
  tags: ["ruby", "rails"]
)

# Чтение — автоматически десериализуется
profile.preferences[:theme]  # => "dark"

Rails 7.1+: store_as и новый API

# Rails 7.1 ввёл typed attributes через attribute API
class EventLog < ApplicationRecord
  serialize :metadata, coder: JSON  # явно JSON вместо YAML
end

# Ещё лучше — store для именованных ключей
class User < ApplicationRecord
  store :settings, accessors: %i[color_scheme locale], coder: JSON
end

user = User.new
user.color_scheme = "dark"
user.locale = "en"
user.settings  # => { "color_scheme" => "dark", "locale" => "en" }

Лучшая альтернатива — PostgreSQL jsonb

# migration
class AddMetadataToProducts < ActiveRecord::Migration[7.1]
  def change
    add_column :products, :metadata, :jsonb, null: false, default: {}
    add_index :products, :metadata, using: :gin
  end
end

# Модель — никакого serialize не нужно
class Product < ApplicationRecord
  # jsonb работает нативно
end

# Запрос по содержимому jsonb
Product.where("metadata @> ?", { category: "electronics" }.to_json)
Product.where("metadata->>? = ?", "color", "red")

Когда serialize допустим

  • Прототипирование или хранение опциональных настроек, по которым никогда не будет фильтрации.
  • Миграция легаси-кода, где нет возможности изменить схему БД.
  • Нереляционные данные с непредсказуемой структурой (логи, события).

Когда избегать serialize

  • Нужна фильтрация по вложенным полям (WHERE preferences->>'theme' = 'dark' не работает на text-колонке).
  • Нужен индекс на поле внутри объекта.
  • Сериализованные данные меняются независимо (нормализуйте в отдельную таблицу).

Подводные камни

  • YAML-сериализация по умолчанию небезопасна для данных из ненадёжных источников — старые версии Rails содержали RCE-уязвимости через YAML.load.
  • Dirty tracking не работает корректно для вложенных мутаций: profile.preferences[:theme] = "light" не помечает preferences как changed — нужно использовать profile.preferences_will_change!.
  • Тип данных проверяется при записи, но не при чтении легаси-данных с неверным типом — десериализация падает молча или возвращает строку.
  • Поиск и сортировка по полю внутри YAML/text-сериализации невозможны без LIKE, что неэффективно и ненадёжно.
  • Миграция между форматами (YAML → JSON) требует ручного rake task для конвертации всех строк.
  • serialize с классом (serialize :data, MyClass) привязывает схему БД к конкретному Ruby-классу — переименование класса ломает десериализацию.
  • Использование store без coder: JSON хранит данные в YAML — проблемы при использовании из других языков или инструментов.
  • jsonb-колонки в PostgreSQL поддерживают GIN-индексы и операторы @>, ? — serialize на text-колонке лишён всех этих возможностей.

Common mistakes

  • Сводить serialize method к названию метода без lifecycle и failure path.
  • Игнорировать модель runtime: Rails 8.1 строит приложение вокруг Rack, routing, controllers, Active Record, views и conventions over configuration.
  • Не отделять validation, authorization, transaction boundary и business logic.

What the interviewer is testing

  • Объясняет serialize method через конкретную точку lifecycle в Ruby on Rails.
  • Приводит корректный минимальный пример без вымышленных методов или callbacks.
  • Называет edge cases: пустые значения, ошибки, транзакции, безопасность или concurrency.

Sources

Related topics