我正在创建一个动态数据库,用户可以在其中创建资源类型,他/她可以添加自定义字段(多个文本,字符串和文件)
每种资源类型都能够显示,导入,导出其数据;
我一直在考虑它,这是我的方法。我很想听听你们的想法。
思路:
只是在数据字段中散列所有自定义数据(专业:写作更容易,con:读回来可能更难);
子字段(模型将包含多个字符串字段,文本字段和文件路径字段);
同一个表中固定数量的自定义字段,其中键映射数据哈希存储在同一行中;
非SQL方法,但问题是动态生成/更改模型以使用不同的自定义字段;
答案 0 :(得分:6)
首先,你可以创建几个模型:
- StringData
- BooleanData
- TextData
- FileData
等(您需要的所有数据和字段格式)
每个模型都会参考某个项目,其中包含有关字段的信息
IE:
class Project < ActiveRecord::Base
has_many :project_fields
has_many :string_datas :through => project_fields
has_many :file_datas :through => project_fields
has_many :boolean_datas :through => project_fields
etc ...
end
class ProjectField < ActiveRecord::Base
# title:string field_type:string project_id:integer name:string
belongs_to :project
has_many :string_datas
has_many :file_datas
has_many :boolean_datas
etc ...
end
class StringData < ActiveRecord::Base
# data:string project_field_id:integer
belongs_to :project_field, :conditions => { :field_type => 'String' }
end
class FileData < ActiveRecord::Base
# data:file project_field_id:integer
belongs_to :project_field, :conditions => { :field_type => 'File' }
end
project = Project.new
project.project_fields.new(:title => "Product title", :field_type => "String", :name => 'product_title')
project.project_fields.new(:title => "Product photo", :field_type => "File", :name => 'product_photo')
project.save
<% form_for project do |f| -%>
<% project.project_fields.each do |field| -%>
<%= field_setter field %>
#=> field_setter is a helper method wich creates form element (text_field, text_area, file_field etc) for each type of prject_field
#=> ie: if field.field_type == 'String' it will return
#=> text_field_tag field.name => <input name='product_name' />
<% end -%>
<% end -%>
创建(更新)方法
def create
project = Project.new(params[:project])
project.project_fields.each do |field|
filed.set_field params[field.name]
# where set_field is model method for setting value depending on field type
end
project.save
end
它没有经过测试和优化,只是展示了实现它的方式。
更新:我已经更新了代码,但它只是模型,你必须认为自己有点:)你可以尝试找出另一个实现
答案 1 :(得分:3)
为什么不为DynamicField创建一个模型?
列:
t.integer :dynamic_field_owner_id
t.string :dynamic_field_owner_type
t.string :name, :null => false
t.string :value
t.string :value_type_conversion, :default => 'to_s'
# any additional fields from paperclip, has_attachment, etc.
t.timestamps
模特课:
class DynamicField > ActiveRecord::Base
belongs_to :dynamic_field_owner, :polymorphic => true
validates_presence_of :name
validates_inclusion_of :value_type_conversion, :in => %w(to_s to_i to_f)
validates :value_or_attachment
def value
read_attribute(:value).send(value_type_conversion)
end
private
def value_or_attachment
unless value? || file?
errors.add_to_base('Must have either value or file')
end
end
end