Dynamic custom fields for data model

I create a dynamic database where the user will be able to create a resource type, where he can add custom fields (several texts, lines and files)

Each type of resource will be able to display, import and export its data;

I thought about it, and here are my approaches. I would love to hear what you guys think.

Ideas:

  • just hashing all user data in the data field (pro: writing is easier, con: reading backwards can be more difficult);

  • child fields (the model will have several line fields, text fields and fields for the file path);

  • a fixed number of custom fields in one table with a key mapping data hash stored on the same row;

  • Non-SQL approach, but then the problem will generate / modify models on the fly to work with different custom fields;

+4
source share
2 answers

First, you can create several models:
- StringData
- BooleanData - FileData
etc. (all necessary data and field formats)

Each model will be assigned to some project, which will contain information about the fields.

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

And create (update) the method

 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 

It is not tested and not optimized, but simply shows how to implement it.

UPDATE: I updated the code, but it is only a model, you need to think a bit :), and you can try to find another implementation

+6
source

Why not just create a model for DynamicField?

Columns:

  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 

model class:

 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 
+3
source

Source: https://habr.com/ru/post/1306252/


All Articles