【问题标题】:Dynamic Custom Fields for Data Model数据模型的动态自定义字段
【发布时间】:2011-02-05 07:23:20
【问题描述】:

我正在创建一个动态数据库,用户可以在其中创建资源类型,他/她可以在其中添加自定义字段(多个文本、字符串和文件)

每种资源类型都可以显示、导入、导出其数据;

我一直在考虑,这是我的方法。我很想听听你们的想法。

想法:

  1. 只是散列数据字段中的所有自定义数据(优点:写入更容易,缺点:读回可能更难);

  2. 子字段(模型将有多个字符串字段、文本字段和文件路径字段);

  3. 固定数量的自定义字段在同一个表中,键映射数据哈希存储在同一行中;

  4. 非 SQL 方法,但问题是动态生成/更改模型以使用不同的自定义字段;

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    首先你可以创建几个模型:
    - 字符串数据
    - 布尔数据
    - 文本数据
    - 文件数据
    等(您需要的所有数据和字段格式)

    每个模型都将引用到某个项目,其中将包含有关字段的信息

    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
    

    它没有经过测试和优化,只是展示了您可以实现它的方式。

    更新:我已经更新了代码,但它只是模型,你必须自己考虑一下 :) 你可以尝试找出另一个实现

    【讨论】:

    • 当我们需要传入某些条件时,如何查询这些自定义字段?
    • 我已经更新了我的答案。但是写在一条评论中是相当大的问题。因此,请尝试通过查看此代码来实现您的实现
    • 感谢所有的灵感。我对 MongoDB 方法进行了一些测试,我认为我将继续使用您的类似实现。我仍然有点不确定查询的速度有多慢。
    【解决方案2】:

    为什么不直接为 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
    

    【讨论】:

      猜你喜欢
      • 2012-01-06
      • 1970-01-01
      • 2010-10-16
      • 2014-04-16
      • 1970-01-01
      • 2021-01-29
      • 2014-04-02
      • 2014-07-01
      • 1970-01-01
      相关资源
      最近更新 更多