Как лучше задать структуру для данных разных типов?
Наиболее подходящий вариант нельзя посоветовать не зная ваших объемов данных и того как вы планируете это использовать.
Если время поиска не критично, типов данных мало, нужно простое и переносимое решение, то я бы посоветовал вариант 1 с сериализацией различных типов в строку.
Вариант с постгревыми json/jsonb добавляет гибкости/производительности, но в json простые типы это число, строка и булев. Даты и прочих типов там нету. Для jsonb поддерживаются индексы. Это решение означает жесткую привязку к PG.
Есть еще вариант похожий на 1, но с заданием разнотипных колонок и хранением в каждом свойстве его типа. Запросы будут выглядет как-то такSELECT * FROM profile_field_values
WHERE 
  (property_field="дата рождения"
  and value_type="date" and value_date > ?)
and
  (property_field="размер ноги"
  and value_type="integer" and value_integer < ?)
По скорости вы выиграете, но получите сложности с реализацией и интеграцией всего этого в рельсы.
Еще есть вариация на тему решения N3 - внешний сервис для поиска: Sphinx, Solr, etc...
Очевидно, что самое разумное решение в данной постановке вопроса - json поле. имхо
В будущем, если некоторое поле будет часто встречаться, его можно будет добавить к модели User, чтобы поиск по этом полю происходил быстрее.