Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic fields with Rails 3

I have a design issue I want to walk through.

I'm building a Rails 3 app which will hold products from a variety of different companies. I'd like to define a large set of fields and each product can select the fields that are applicable to it.

The field types will be single line text fields, multi line text fields, radio or select options, checkbox options, dates, durations or something more custom. I'll need to be able to dynamically render the fields based on this type for edit and show.

My current idea is to use MongoDB and store everything in a Hash on the Product.

class Product
  include Mongoid::Document
  def self.field_definitions
    [{ :name => :code, :label => 'Code' },
     { :name => :itinerary, :type => :multiline, :label => 'Itinerary', :category => :tour},
     { :name => :infant_age, :type => :age_range, :label => 'Infante age range', :category => :tour},
        ...
     ]
  end

  embedded_in :company
  field :field_data, type:Hash
end

Then render the fields for new/edit something like:

= form_for Product.new do |f|
  = f.fields_for :field_data do |f|
    %ol
      - Product.field_definitions.each do |field_definition|
        %li
          = f.label field_definition[:name], field_definition[:label]
          = render "products/edit_fields/#{field_definition[:type] || 'singleline'}", :f => f, :field_definition => field_definition

  = f.submit "Create"

I then have a partial for each field type for edit and show.

After creation, a Product might look like this in mongodb:

{"field_data":{
    "itinerary": "FUN!",
    "code": "AHKDYK", 
    "infant_age": { "max": 2, "min": 0 } 
}}

Is this a good approach?

like image 674
whatupdave Avatar asked Apr 14 '11 23:04

whatupdave


1 Answers

Sure, that'll work - but do you know that you don't need to go to Mongo just to be able to store a hash of values in the DB. You can also set an attribute as serialize then Rails will convert it to YAML and back to a (simple) object on the way back out for you.

This is a fairly common (and very workable) approach for the pattern that you describe.

like image 189
smathy Avatar answered Sep 29 '22 12:09

smathy