2012-05-09 4 views
3

В моем приложении Rails3 я использую ActiveRecord и Postgresql.Разрешить пользователям создавать динамические атрибуты модели?

Скажем, у меня есть модель под названием Части. Модель имеет небольшой список стандартных атрибутов, таких как цена, количество и т. Д.

Однако, заказчик может хотеть добавить LotNumber, а CustomerB может захотеть добавить OriginalLocation.

Как я могу позволить им это сделать?

Я думал о создании модели PartsDetail, которая позволила им иметь тип.

class PartsDetail < ActiveRecord::Base 
    attr_accessible :type, :value, :part_id 
    belongs_to :parts 
end 

Так что «типа» может быть «LotNumber» и т.д.

Но я не совсем уверен, как это будет работать в моих ассоциаций и запросов.

Любые идеи?

Спасибо.

+1

Для SQL: либо ne динамическая схема (новые столбцы), денормализация в столбце (например, JSON) или схему, которая представляет схему в столбцах (например, EAV). –

+3

Использование клиентов в качестве разработчиков баз данных - очень рискованный подход. –

+1

@Catcall Не обязательно «разработчики баз данных» (это подразумевает гораздо более широкий контекст, чем этот вопрос). Тем не менее, это * довольно часто * для * бизнес-требования * для присоединения дополнительных «настраиваемых» свойств к сущности. * Не позволяя * это (в некотором роде) может быть отрицательным по отношению к потребностям конкретного бизнеса. (В этом случае для CustomerB требуется OriginalLocation.) –

ответ

3

Поскольку вы используете PostgreSQL, вы можете использовать hstore для хранения произвольных хэшей в столбцах базы данных:

Этот модуль реализует тип данных hstore для хранения наборов пар ключ/значение в пределах одного значения PostgreSQL. Это может быть полезно в различных сценариях, таких как строки со многими атрибутами, которые редко рассматриваются, или полуструктурированные данные. Ключи и значения - это просто текстовые строки.

Там даже камень для добавления поддержки hstore в ActiveRecord:

https://github.com/softa/activerecord-postgres-hstore

Тогда вы могли бы создать hstore колонку под названием, скажем, client_specific и заглянуть внутрь него с такими вещами как:

M.where("client_specific -> 'likes' = 'pancakes'") 
M.where("client_specific @> 'likes=>pancakes'") 

, чтобы узнать, какие клиенты отметили, что им нравятся блины.

Возможно, вам захочется сохранить список полей, предназначенных для клиентов, где-то с записью клиента, чтобы упростить работу с интерфейсом пользователя, но это довольно просто сделать.

+0

Будет ли этот подход лучше, чем решение EAV, или это одно и то же? Необходимые динамические атрибуты намного больше, чем «редко рассматриваются». Они являются ключевыми для их модели. Спасибо – cbmeeks

+0

@cbmeeks: Это не совсем то же самое, что и EAV, это в основном добавляет хеши в строку типа string-to-string. Вам не нужна дополнительная таблица или соединение для этого, и в отличие от различных подходов 'serialize', столбцы hstore' полностью индексируются, как и все остальное. PostgreSQL также имеет набор функций и операторов специально для 'hstore', поэтому они могут быть проще, чем делать все вручную с помощью EAV. –

+1

Достойное сообщение в блоге об использовании hstore в рельсах: http://neilmiddleton.com/the-wonders-of-hstore/ – jacklin

1

Вот суть, что кто-то написал, что позволяет использовать hstore атрибуты в моделях более плавно: https://gist.github.com/2834785

Для использования добавьте это в инициализаторе (или создать новый Initializer под названием active_record_extensions.Р.Б.)

require "hstore_accessor" 

Тогда в вашей модели вы можете иметь:

Class User < ActiveRecord::Base 
    hstore_accessor :properties, :first_name, :last_name 
end 

Это позволяет сделать:

u = User.new 
u.first_name = 'frank' 

Вы можете все еще добавить атрибуты в столбец hstore и обойти hstore_attributes:

u.properties['middle_name'] = 'danger' 
Смежные вопросы