Rails 3 的动态字段
我有一个设计问题想要解决。
我正在构建一个 Rails 3 应用程序,它将包含来自各种不同公司的产品。我想定义一大组字段,每个产品都可以选择适用于它的字段。
字段类型将是单行文本字段、多行文本字段、单选或选择选项、复选框选项、日期、持续时间或更自定义的内容。我需要能够基于此类型动态渲染字段以进行编辑和显示。
我当前的想法是使用 MongoDB 并将所有内容存储在产品上的哈希中。
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
然后呈现用于新建/编辑的字段,例如:
= 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"
然后,我对每个字段类型都有一个部分用于编辑和显示。
创建后,产品在 mongodb 中可能如下所示:
{"field_data":{
"itinerary": "FUN!",
"code": "AHKDYK",
"infant_age": { "max": 2, "min": 0 }
}}
这是一个好方法吗?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当然,这会起作用 - 但你知道吗,你不需要去 Mongo 只是为了能够在数据库中存储值的哈希值。您还可以将属性设置为
serialize
然后 Rails 会将其转换为 YAML,并在返回时返回为(简单)对象。对于您所描述的模式来说,这是一种相当常见(并且非常可行)的方法。
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.
您可以将这些字段定义为 Mongoid::Document 字段并使用 Product.fields 作为内省。然后,您可以利用 ActiveModel 的功能,例如验证以及 i18n(如果需要)。
You can define those fields as Mongoid::Document fields and use Product.fields as a introspection. You can then leverage the ActiveModel's features such as validations, as well as i18n (if needed).