2016-12-13 37 views
0

我的应用程序使用Ruby on Rails ActiveRecord模型,它不允许在没有安装第三方gem(如composite-primary-keys)的情况下使用复合键。有没有一种方法可以将组合键重构为一个简单的键,以便它适合这种范例,或者我应该咬紧牙关并安装宝石?重构复合主键到Rails的简单键?

我还处于设计初期阶段,所以我没有数据需要担心,我希望尽可能保持对Rails成语的真实性。

我正在创建一个食谱数据库,可以按步骤列出成分和说明。数据库模式与下面显示的类似,并在Recipe_Steps和Recipe_Step_Ingredients表中使用组合键(图像的底部中心)。

Database schema

回答

0

你很可能和得太多了过于复杂的问题。坚持使用名为id的单个主键的AR成语。

对于连接表使用外键代替化合物PK。还要坚持命名规则,除非你想通过违反最小惊喜原则来看起来无能或惹恼其他开发者。这意味着:一切

  • 使用snake_case(表名,列,索引名等)
  • 没有前缀的表名的列。它只是让您的应用程序中的每个变量都变得更长,并且不需要在ORM中使用。对于外键列,使用_id。前;对于时间戳,使用_at。前; confirmed_at
  • 使用thing_other_things用于连接表,除非有一个更具描述性的名称

而且许多情况下应该只使用一种间接的关系,加入了层次结构,而不是重复的外键。

这是一个例子DB模式:

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

    # These are extensions that must be enabled in order to support this database 
    enable_extension "plpgsql" 

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

    create_table "ingredients", force: :cascade do |t| 
    t.integer "ingredient_type_id" 
    t.datetime "created_at",   null: false 
    t.datetime "updated_at",   null: false 
    t.index ["ingredient_type_id"], name: "index_ingredients_on_ingredient_type_id", using: :btree 
    end 

    create_table "recipe_ingredients", force: :cascade do |t| 
    t.integer "recipe_id" 
    t.integer "ingredient_id" 
    t.float "quantity" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
    t.index ["ingredient_id"], name: "index_recipe_ingredients_on_ingredient_id", using: :btree 
    t.index ["recipe_id"], name: "index_recipe_ingredients_on_recipe_id", using: :btree 
    end 

    create_table "steps", force: :cascade do |t| 
    t.integer "recipe_id" 
    t.integer "ordinal" 
    t.text  "instruction" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
    t.index ["recipe_id"], name: "index_steps_on_recipe_id", using: :btree 
    end 

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

    add_foreign_key "ingredients", "ingredient_types" 
    add_foreign_key "recipe_ingredients", "ingredients" 
    add_foreign_key "recipe_ingredients", "recipes" 
    add_foreign_key "steps", "recipes" 
end 

class IngredientType < ApplicationRecord 
    has_many :ingredients 
end 

class Ingredient < ApplicationRecord 
    belongs_to :ingredient_type 
    has_many :recipe_ingredients 
    has_many :recipes, through: :recipe_ingredients 
end 

class RecipeIngredient < ApplicationRecord 
    belongs_to :recipe 
    belongs_to :ingredient 
    has_one :ingredient_type, through: :ingredient 
end 

class Step < ApplicationRecord 
    belongs_to :recipe 
end 

class Recipe < ApplicationRecord 
    has_many :recipe_ingredients 
    has_many :ingredients, through: :recipe_ingredients 
    has_many :steps 
end 
+0

这不是我的确切模式,我只是用它作为参考。但这些都是非常好的提示。我也不是专业的SQL数据库设计师......你如何推荐不使用组合键来建模recipe_step_ingredients?一个配方有很多步骤,每一步都可以有很多成分,所以我很难找出一个简单的模式来使用,而不涉及组合键。 –

+0

它本身可能只是一种过度复杂化。您是否真的需要在步骤中储存成分的数量,而不仅仅是在加入“食谱”和“成分”的连接表上? – max

+0

大多数食谱都将成分列在一起,然后您只需在步骤中写上“在蛋类中混合四分之一”的东西。吻。 – max