为哈希属性创建表单字段

时间:2014-04-15 17:39:23

标签: ruby-on-rails ruby activerecord ruby-on-rails-4

我有一个型号Product,它有一个属性属性。它将其作为哈希值存储在单个数据库列中(在http://api.rubyonrails.org/classes/ActiveRecord/Store.html之后)

class Product < ActiveRecord::Base
  store :properties
end

如何为此属性属性(哈希)创建动态表单字段?我对意识形态正确的做法感兴趣(&#34; rails way&#34;)。我想有需要使用fields_for帮助器。但我不完全明白该怎么做。请告诉我解决这个问题的正确方法。

结果,我想得到一张如图所示的工作表格。

enter image description here

用户可以添加无限数量的字段并提供任何属性名称及其值。

3 个答案:

答案 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)