7

У меня есть приложение SaaS, где учетные записи хотят сохранять различные типы информации в модели пользователя. Так, например, одна учетная запись может захотеть сохранить возраст и дату рождения, но в другой учетной записи они не будут использовать эти столбцы и захотят сохранить информацию о цвете волос и высоте.Rails: динамические столбцы/атрибуты на моделях?

Это просто примеры, но как бы я структурировал свою модель и db так, чтобы она хорошо работала с «настраиваемыми динамическими» столбцами, не создавая слишком много пустых атрибутов.

+0

х, где ты в конечном итоге происходит с этим? – mmcrae

+1

@mmcrae Я закончил использование структуры данных .json postgresql и сбросил любой пользовательский столбец в это поле данных .json. – kibaekr

ответ

5

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

Или (если вы хотите придерживаться SQL), вы можете иметь базовую модель User с ассоциацией has_many :attributes. В атрибуте есть всего лишь комбинация key («возраст», «день рождения», «цвет волос») и значение. Сложность связана с различными типами данных и запросами, охватывающими сразу несколько атрибутов.

0

Ваша схема может быть как:

create_table "accounts", :force => true do |t| 
    t.integer "user_id" 
    t.string "data_key" 
    t.string "data_value" 
end 

модель счета

belongs_to :user  
DATA_KEYS = ['age', 'birthdate', 'hair_color', 'height' ] # etc.. 

модели пользователя

has_many :accounts 
Account::DATA_KEYS.each do |method| 
    # getter method 
    define_method(method) do 
    accounts.find_by_data_key(method).try(:data_value) 
    end 

    # setter method 
    define_method("#{method}=") do |value| 
    data = accounts.find_or_initialize_by_data_key(method) 
    data.data_value = value.strip 
    data.save 
    end 
end 

Вы можете получить и установить данные учетной записи значения

Э.Г. user.age => вернет возраст пользователя

user.hair_color = 'brown' => установит цвет волос

+0

Будет ли этот код изменяться вообще, если Пользователь принадлежит ко многим учетным записям? И Accounts выбрали бы, хотят ли они поддерживать определенную data_key, и пользователи этой учетной записи будут иметь data_values ​​для этих data_keys. – kibaekr

+0

. Я получаю эту ошибку: «NoMethodError: undefined method' find_by_data_key» для # <Пользователь: 0x00000109a7da00> " – kibaekr

+0

@ kibaekr, модель пользователя имеет 'has_many: accounts' И метод' find_by_data_key' не для объекта 'User', а для модели' Account'. – shweta

0

Я хотел бы предложить собирается для базы данных NoSQL. Они разработаны специально для таких случаев, поэтому вам не придется делать сумасшедшие вещи, чтобы заставить все работать. MongoDB в сочетании с MongoID - очень прочное решение.

Единственным недостатком может быть хостинг, поскольку он имеет тенденцию быть слегка, по крайней мере, более дорогим.

7

Вот два варианта. 1. База данных NoSQL. 2. Rails 4 Store особенность.

+1

Rails Store выглядит действительно интересным и подходящим для многих случаев, когда вы хотите придерживаться своей обычной базы данных и моделей, и «когда вы не заботитесь о возможности запросить это хранилище вне контекста одной записи» - цитата из документации. Идеально для меня. – DannyB

1

Если вы используете Postgresql, вы можете взглянуть на hstore, тогда вы можете сохранить информацию в сериализованном виде, и на самом деле вы можете сделать несколько запросов к этим хэшам. Btw Rails 4 включил эту функцию, но если вы используете старую версию Rails вы можете включить этот драгоценный камень. https://github.com/diogob/activerecord-postgres-hstore в вашем Gemfile, и вы должны быть в состоянии начать играть, как:

user = User.new 
user.preferences = { 
    email: "[email protected]", 
    github: "heridev" 
} 

user.save! 
user.reload 

# Searching 
User.where("preferences @> hstore(:key, :value)", key: "email", value: "[email protected]").first 
Смежные вопросы