Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create form fields for hash attribute

I have a model Product, which has a properties attribute. It stores it in a single database column as a hash (following http://api.rubyonrails.org/classes/ActiveRecord/Store.html)

class Product < ActiveRecord::Base
  store :properties
end

How can I create dynamic form fields for this property attribute (which is a hash)? I'm interested in ideologically correct way of doing this ("rails way"). I guess that there is need to use fields_for helper. But I do not fully understand how to do it. Tell me the correct way of solving this problem, please.

In result, I'd like to get a working form like shown on image.

enter image description here

Where a user can add unlimited number of fields and give any property names and its values.

like image 738
Molfar Avatar asked Apr 15 '14 17:04

Molfar


1 Answers

The rails way needn't include the limitation of using a single table, ideally, you can do this in a very rails way with 2 tables. Moving on.

You shouldn't use Active Record :store for this purpose in my opinion.

That implementation is ideal for situations where the developers need to store model metadata that is flexible in-code but well-defined at any given point of time. Which is to say, you need to specify keys in the model.

There is another pit-fall, you can't run SQL queries on the resulting serialized text that is saved.

If you insist, you can do this:

In your model:

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

In the view:

<%= 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 %>

Then you can also add an 'add another property' link which should use JS to insert another pair of inputs with the names product[prop_hash][][name] and product[prop_hash][][value] respectively.

Long ago I had rolled a custom implementation for metadata which saves the keys in serialized XML, for one reason - it can be queried in SQL. The link to my blog article http://geniitech.tumblr.com/post/14916592782/storing-metadata-as-xml-hash-in-ror

like image 152
vvohra87 Avatar answered Oct 09 '22 02:10

vvohra87