There is a workaround. Based on a pair of definitions and instances tables.
The first (definitions) is a description of the classes being created, it has two columns (in addition to id) - name: string and structure: text. In the class we serialize attr_list, it will be a hash, the keys will be the names of the attributes, the values will be their type.
The second table (instances) is actually objects. It contains columns id, definition_id: integer, instance_id: integer and values: text. Similarly, use serialized values to store the object. In it, the values are a hash from the first table according to the selected object type, the keys remain, but the values change to the actual values of the object fields.
That is, at first we define some “class” on the fly, save it to the first table, and then build the form and form a new object from it, which is saved in the second table. It remains only to provide standard CRUD methods for manipulating these objects, but this is already a matter of technology.
class CreateTables < ActiveRecord::Migration def change create_table :definitions do |t| t.string :name, null: false t.text :structure end create_table :instances do |t| t.references :definition, null: false t.integer :instance_id, null: false t.text :values end add_index :instances, :definition_id end end class Definition < ActiveRecord::Base serialize :structure, Hash end class Instance < ActiveRecord::Base serialize :values, Hash end