假设我想允许管理用户通过Rails应用程序中的界面向ActiveRecord模型添加字段。我相信正常的ActiveRecord :: Migration代码足以修改AR模型的表结构(对于许多应用程序来说这是不明智的 - 我知道)。当然,理论上只能添加某些类型的字段。
显然,需要在运行时动态构建向这个新修改的ActiveRecord模型添加(或编辑)记录的表单。一种常见的form_for方法是行不通的。这个讨论表明这只能通过JavaScript实现。
http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/fc0b55fd4b2438a5
我过去曾使用Ruby来查询对象的可用方法。我似乎记得它非常慢。我太过绿了,Ruby和Rails知道一种优雅的方法来解决这个问题。我希望有人在这里。我也对这个问题完全不同,不涉及修改数据库。
答案 0 :(得分:6)
要访问当前为模型定义的列,请使用columns方法 - 它将为每列提供其名称,类型和其他信息(例如它是否为主键,等)
但是,在运行时修改模式很复杂。
架构在首次加载时由每个模型类预加载(并从DB驱动程序缓存)。在production
模式下,Rails仅在启动时为每个模型执行一次。
development
模式下运行时,Rails会在每次请求后自动为你做什么 - 见how to reload a class using remove_const
followed by load
。)现在,已经说过,根据您需要解决的实际问题,您可能不需要动态地改变架构。您可以使用名为{{1的表格,而不是将列col1
,col2
和col3
添加到某个表entries
(模型Entry
)中。 }},其中,条目dyn_attribs
和has_many :dyn_attribs
都有dyn_attribs
列(在这种情况下可以包含值key
,col1
或{{1 }}和col2
列(列出col3
,value
等的相应值。)
因此,而不是:
col1
你会用:
col2
上述my_entry = Entry.find(123)
col1 = my_entry.col1
#do something with col1
调用可以被分解到模型中,甚至可以分解为可能需要额外的动态列/属性的所有模型继承的基类(有关如何制作,请参阅Polymorphic associations有几个模型为动态属性共享相同的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
表。)
<强>更新强>
通过常规HTML表单添加或重命名列。
假设您有一个表示具有动态属性的表的inject
模型,以及一个定义给定表的动态属性名称的dyn_attribs
。
执行命令
DynAttrTable
然后编辑生成的模型:
DynAttrDef
您可以继续编辑控制器和视图like in this tutorial,将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
。
或者,使用其中一个插件reviewed here自动将Ingredient
和DynAttrDef
表格置于自动界面管理之下(包括所有的铃声和口哨),几乎没有代表你的实施工作。
这应该让你去。
答案 1 :(得分:3)
说我想允许 管理用户添加字段 通过接口的ActiveRecord模型 在Rails应用程序中。
我之前通过一个名为AdminAdditions的额外模型解决了这类问题。该表包括id,管理员用户标识,模型名称字符串,类型字符串和默认值字符串。
我覆盖模型的find和save方法,以便从admin_additions添加属性,并在更改时适当保存。模型表有一个大的文本字段,最初为空,我保存添加属性的非默认值。
本质上,视图和控制器可以假装模型的每个属性都有自己的列。这意味着form_for
等所有工作。
答案 2 :(得分:2)
ActiveRecord :: Migration.add_column(用户,“电子邮件”,:字符串)
答案 3 :(得分:1)
您可以使用Flex Attributes,但如果您希望能够通过这些新列进行搜索或排序,则必须编写(大量)自定义SQL。
答案 4 :(得分:1)
我已经看过多次作为解决方案提供的表的动态更改/迁移,但我从未真正看到它实现过。这个解决方案很少实现的原因有很多。
你想在这里实现什么?更好地理解这个问题可能会揭示更自然的解决方案。
答案 5 :(得分:1)
如果您现在使用PostgreSQL执行此操作,您现在可能会使用JSON类型字段,然后只需将其存储在json哈希中。