如何构建复杂的嵌套表单来表示动态属性

时间:2015-10-27 16:58:54

标签: ruby-on-rails nested-forms

我有一个由下图所代表的数据模型: enter image description here

基本上,我们的想法是有很多不同的收藏品。单个集合中的所有将具有相同的属性,但每个集合的属性列表将不同。每个项目的每个属性的值将存储在项目属性值

我正在尝试构建一个页面,用户可以在其中填充项目的属性。我假设嵌套表单是要走的路,但我不知道如何在控制器和页面上表示这一点,考虑到属性的名称在一个表中而值在另一个表中。 / p>

如果有人遇到或不得不处理类似的情况,我们将不胜感激。

由于

1 个答案:

答案 0 :(得分:1)

这是一个潜在的解决方案。

class Collection
  has_and_belongs_to_many :items
  has_and_belongs_to_many :attributes
end

class Item
  has_and_belongs_to_many :collections
  has_many :item_attributes
  has_many :attributes, though: :item_attributes
end

class Attributes
  has_and_belongs_to_many :collections
  has_many :item_attributes
  has_many :items, though: :item_attributes
end

class ItemAttribute
  belongs_to :item
  belongs_to :attribute
end

让我们看一下数据库布局来支持这些模型:

ActiveRecord::Schema.define(version: 20151027173337) do

  create_table "attributes_collections", id: false, force: :cascade do |t|
    t.integer "attribute_id",  null: false
    t.integer "collection_id", null: false
  end

  create_table "collections", force: :cascade do |t|
    t.string   "title"
    t.integer  "user_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  add_index "collections", ["user_id"], name: "index_collections_on_user_id"

  create_table "collections_items", id: false, force: :cascade do |t|
    t.integer "collection_id", null: false
    t.integer "item_id",       null: false
  end

  create_table "item_attributes", force: :cascade do |t|
    t.integer  "item_id"
    t.integer  "attribute_id"
    t.string   "value"
    t.datetime "created_at",   null: false
    t.datetime "updated_at",   null: false
  end

  add_index "item_attributes", ["attribute_id"], name: "index_item_attributes_on_attribute_id"
  add_index "item_attributes", ["item_id"], name: "index_item_attributes_on_item_id"

  create_table "items", force: :cascade do |t|
    t.string   "name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

end

更好的方式?

但当然,由于许多连接,性能将受到影响。此外,每个属性都将存储为VARCHAR,这意味着您无法在数据库中进行任何数字比较。

如果你真的需要灵活的架构,我会考虑使用HSTORE, JSON或其他动态列类型或无架构数据库,例如MongoDB。

如何为此创建表单/控制器?

首先,您应该非常熟悉使用accepts_nested_attributes_forfields_for可以完成的工作,并且可以考虑使用AJAX将操作委托给CollectionControllerItemController后端,而不是把它全部塞进一个怪物。