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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With