Чтобы получить доступ к столбцам, которые в настоящее время определены для модели, используйте метод columns - он предоставит вам для каждого столбца его имя, тип и другую информацию (например, является ли она первичной). ключ и т. д.)
Однако изменение схемы во время выполнения деликатно.
Схема предварительно загружается (и кэшируется из драйвера БД) каждым классом модели при первой загрузке. В режиме production
Rails делает это один раз для каждой модели при запуске.
- Чтобы заставить Rails обновлять свою кэшированную схему после вашей модификации, вы должны заставить Ruby перезагружать класс уязвимой модели (почти то, что Rails делает для вас автоматически, после каждого запроса, при работе в режиме
development
- см. как перезагрузить класс, используя remove_const
, за которым следует load
.)
- Если у вас есть кластер Mongrel, вы также должны сообщить другим процессам в кластере, которые выполняются в отдельном пространстве памяти, чтобы также перезагрузить классы их модели (некоторые кластеры позволят вам создать файл restart.txt). 'файл, который приведет к автоматическому перезапуску всех процессов в вашем кластере без дополнительной работы от вашего имени.)
Теперь, как уже было сказано, в зависимости от реальной проблемы, которую вам нужно решить, вам, возможно, не понадобится динамически изменять схему. Вместо добавления, скажем, столбцов col1
, col2
и col3
в некоторую таблицу entries
(модель Entry
), вы можете использовать таблицу с именем dyn_attribs
, где Entry 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
вызов может быть вынесен в модель или даже в базовый класс, унаследованный всеми моделями, которым могут потребоваться дополнительные динамические столбцы / атрибуты (см. Полиморфные ассоциации о том, как заставить несколько моделей использовать одну и ту же таблицу dyn_attribs
для динамических атрибутов.)
UPDATE
Добавление или переименование столбца с помощью обычной 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
Вы можете продолжить редактирование контроллеров и представлений , как в этом учебном пособии , заменив Recipe
на DynAttrTable
и Ingredient
на DynAttrDef
.
В качестве альтернативы , используйте один из плагинов , рассмотренный здесь , для автоматического управления таблицами dyn_attr_tables
и dyn_attr_defs
с помощью автоматизированного интерфейса (со всеми его прибамбасами) , практически без усилий по реализации от вашего имени.
Это должно помочь вам.