Добавить поля в ActiveRecord динамически в Rails 2.2.2?


3

Скажем, я хочу, чтобы административный пользователь мог добавить поле в модель ActiveRecord через интерфейс в приложении Rails. Я считаю, что нормальный код ActiveRecord :: Migration был бы адекватным для изменения структуры таблицы AR Model (что-то, что не было бы разумным для многих приложений - я знаю). Конечно, только некоторые типы полей могут быть добавлены ... теоретически.

Очевидно, что формы, которые добавляют (или редактируют) записи к этой недавно модифицированной модели ActiveRecord, должны быть динамически построены во время выполнения. Обычный метод form_for не будет работать. Это обсуждение предполагает, что это может быть выполнено только с помощью JavaScript.

http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/fc0b55fd4b2438a5

Я использовал рубин в прошлом для запроса объекта для его доступных методов. Кажется, я помню, что это было безумно медленным. Я слишком зелёный, чтобы Ruby и Rails знали элегантный способ приблизиться к этому. Надеюсь, кто-то здесь может. Я также открыт для совершенно разных подходов к этой проблеме, которые не связаны с изменением базы данных.

  0

Если я правильно понимаю, вам нужен административный интерфейс, который динамически добавляет _columns_ в разное. таблицы в схеме DB рельсов? 22 фев. 092009-02-22 08:40:49

  0

Да, это мысль. Из-за гибкости ActiveRecord я решил, что это будет возможно. 25 фев. 092009-02-25 00:48:14

3

Скажите, что я хотел, чтобы позволить пользователь с правами администратора, чтобы добавить поле в ActiveRecord модели через интерфейс в приложении Rails.

Я решил эту проблему раньше, добавив дополнительную модель под названием AdminAdditions. Таблица включает идентификатор, идентификатор пользователя администратора, строку имени модели, строку типа и строку значений по умолчанию.

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

По существу, виды и контроллеры могут притворяться, что каждый атрибут модели имеет свой собственный столбец. Это означает, что form_for и так далее все работают.


1

Для этого вы можете использовать Flex Attributes, хотя если вы хотите, чтобы иметь возможность искать или заказывать эти новые столбцы, вам придется писать (много) пользовательский SQL.


1

Я видел динамическое изменение/перемещение таблиц, предлагаемых в качестве решения, много раз, но я никогда не видел его реализованного. Существует много причин, почему это решение редко реализуется.

  • Если таблица большая, то таблица может/будет заблокирована в течение продолжительных периодов времени, который должен быть включен.
  • Почему ваша модель динамически меняется? Для структуры моделей довольно сложно динамически меняться. Это чаще всего указывает на то, что вы пытаетесь моделировать нечто конкретное обобщенным образом.
  • Это часто попытка создания модели с категорией, которая может быть лучше решена другим подходом.
  • Заявления DDL часто не допускаются тем же пользователем, который используется для ежедневных требований DML. Хотя это может иметь место и часто находится на арене ROR, это не всегда «правильный» способ сделать это.

Что вы пытаетесь достичь здесь? Лучшее понимание проблемы, вероятно, выявит более естественное решение.

  0

Моя цель - позволить административным пользователям добавлять пользовательские поля (ограниченных типов) к определенным (не всем) моделям в приложении. 25 фев. 092009-02-25 00:49:56


5

Чтобы получить доступ к столбцам, которые в настоящее время определены для модели, используйте метод columns - он даст вам для каждого столбца его имя, тип и другую информацию (например, является ли это первичным ключом и т. Д.),

Однако изменение схемы во время выполнения является деликатным.

Схема, предварительно загруженная (и кэшированная из драйвера БД) каждым классом модели при первой загрузке. В режиме production, Rails только делает это один раз за модель, вокруг запуска.

  1. Для того, чтобы заставить Rails обновить кэшированные схемы после вашего изменения, вы должны заставить рубин перезагрузить класс затронутого модели (довольно много, что делает Rails для вас автоматически, после каждого запроса, при работе в режиме development - см. how to reload a class using remove_const followed by load.)
  2. Если у вас есть кластер Mongrel, вы также должны сообщить другим процессам в кластере, которые работают в своем отдельном пространстве памяти, чтобы также перезагрузить классы своей модели (некоторые кластеры позволят вам создать «перезапуск». txt ", что приведет к автоматическому программному перезапуску всех процессов в вашем кластере без дополнительной работы, требуемой от вашего имени.)

Теперь, когда они были сказаны в зависимости от фактической проблемы, решить, вам может не понадобиться динамически изменять схему в конце концов. Вместо добавления, скажем, столбцов col1, col2 и col3 в некоторую таблицу entries (модель Entry), вы можете использовать таблицу с именем dyn_attribs, где Вступительные has_many :dyn_attribs, и где dyn_attribs имеет как key столбца (который в этом случае может иметь значения col1 , col2 или col3) и value столбца (в котором перечислены соответствующие значения для col1, col2 и т.д.)

Таким образом, вместо того, чтобы:

my_entry = Entry.find(123) 
col1 = my_entry.col1 
#do something with col1 

вы будете использовать:

my_entry = Entry.find(123, :include => :dyn_attribs) 
dyn_attribs = my_entry.dyn_attribs.inject(HashWithIndifferentAccess.new) { |s,a| 
    s[a.key] = a.value ; s 
} 
col1 = dyn_attribs[:col1] 
#do something with col1 

выше inject вызова может быть разложен прочь в модели, или даже в базовый класс, унаследованный от всех моделей, которые могут потребоваться дополнительные, динамические столбцы/атрибутов (см Polymorphic associations о том, как сделать несколько моделей одни и те же dyn_attribs таблицу динамических атрибутов.)


UPDATE

Аддин g или переименование столбца с помощью обычной формы HTML.

Предположим, что у вас есть модель DynAttrTable, представляющая таблицу с динамическими атрибутами, а также DynAttrDef, определяющую имена динамических атрибутов для данной таблицы.

Пробег:

script/generate scaffold_resource DynAttrTable name:string 
script/generate scaffold_resource DynAttrDef name:string 
rake db:migrate 

Затем редактировать сгенерированные модели:

class DynAttrTable < ActiveRecord::Base 
    has_many :dyn_attr_defs 
end 

class DynAttrDef < ActiveRecord::Base 
    belongs_to :dyn_attr_table 
end 

Вы можете продолжить редактирование контроллеров и мнения like in this tutorial, заменив Recipe с DynAttrTable и Ingredient с DynAttrDef.

Альтернативно, используйте один из плагинов reviewed here автоматически ставить dyn_attr_tables и dyn_attr_defs столы под управлением автоматизированной интерфейс (со всеми его прибамбасами), практически с нулевым усилием реализации от вашего имени.

Это должно вас заставить.

  0

Это элегантный подход к проблеме на заднем конце. Я обеспокоен поддержкой браузеров, поэтому есть простой способ использовать чистые HTML-формы (без AJAX), созданные Ruby, для динамического создания формы, чтобы автоматически включать новые динамические атрибуты? Googling не запускается простым способом. 25 фев. 092009-02-25 02:34:24


2

ActiveRecord :: Migration.add_column (Пользователь, «электронная почта»,: строка)

  0

ActiveRecord :: Migration.add_column (Пользователь, «электронная почта»,: строка); User.reset_column_information 17 сен. 102010-09-17 11:51:25


1

Если вы делаете это с PostgreSQL теперь вы, вероятно, может уйти с поля типа JSON, а затем просто хранить все, что в JSON хэш.