我有一个型号Product,它有一个属性属性。它将其作为哈希值存储在单个数据库列中(在http://api.rubyonrails.org/classes/ActiveRecord/Store.html之后)
class Product < ActiveRecord::Base
store :properties
end
如何为此属性属性(哈希)创建动态表单字段?我对意识形态正确的做法感兴趣(&#34; rails way&#34;)。我想有需要使用fields_for帮助器。但我不完全明白该怎么做。请告诉我解决这个问题的正确方法。
结果,我想得到一张如图所示的工作表格。
用户可以添加无限数量的字段并提供任何属性名称及其值。
答案 0 :(得分:8)
rails方式不需要包括使用单个表的限制,理想情况下,您可以使用2个表以非常有轨的方式执行此操作。继续前进。
在我看来,您不应该将Active Record :store
用于此目的。
这种实现非常适合开发人员需要存储模型元数据的情况,这些元数据在代码中是灵活的,但在任何给定的时间点都是明确定义的。也就是说,您需要在模型中指定键。
还有另一个陷阱,您无法对保存的结果序列化文本运行SQL查询。
如果你坚持,你可以这样做:
在你的模特中:
class Product < ActiveRecord::Base
store :properties
def prop_hash
self.properties.collect{|k,v| [k,v]}
end
def prop_hash=(param_hash)
# need to ensure deleted values from form don't persist
self.properties.clear
param_hash.each do |name, value|
self.properties[name.to_sym] = value
end
end
end
在视图中:
<%= form_for @product do |f| %>
<% f.object.prop_hash.each do |k,v| %>
<%= text_field 'product[prop_hash][][name]', k %>
<%= text_field 'product[prop_hash][][value]', v %>
<% end %>
<% end %>
然后你还可以添加一个'添加另一个属性'链接,该链接应该使用JS分别插入名为product[prop_hash][][name]
和product[prop_hash][][value]
的另一对输入。
很久以前,我已经推出了元数据的自定义实现,它将密钥保存在序列化XML中,原因之一是 - 它可以在SQL中查询。我的博客文章http://geniitech.tumblr.com/post/14916592782/storing-metadata-as-xml-hash-in-ror
的链接答案 1 :(得分:1)
简而言之,您希望在某个地方有一个包含此内容的表单:
<% @product.properties_hash.each do |k,v| %>
<%= f.field_for k %>
<%= f.field_for v %>
<# link to action that will remove this key/value pair from the serialized hash saved in the database %>
<% end -%>
您将不得不以某种方式创建一个空白键和值对(或者在表单中使用表单助手,或者通过向哈希本身的末尾添加空白(ish)键和值对通过在将其加载到@product中后修改控制器中的product
(就像使用@ product.add_blank_properties方法一样)。否则,您将无法在结尾处找到空白字段。循环......
我可以详细介绍在使用以前存在的空行创建属性之后为属性添加新的空行,但是当你到达目前为止,你应该很好地掌握你需要寻找什么解决这个问题(并且有很多资源(你可能会使用ajax
)。
答案 2 :(得分:-2)
我认为您应该使用rails标准scaffold
,但在这里您可能需要很少的自定义。
1)需要为属性声明resourceful route
property name
将成为resource id
2)Index view
将遍历属性hash
以填充相关字段。
product.properties.each do |name, value|
puts name
puts value
end
2)Create
操作应创建一条记录,如果不存在(基于名称)已经否则会出错
product.properties[:price] = 10
3)Update
将根据名称找到属性并以哈希方式更新
product.properties[:price] = 25
4)delete
实际上会根据属性key-value
name
对
product.properties.delete(:price)