我的应用程序使用Ruby on Rails ActiveRecord模型,如果不安装第三方gem(例如 composite-primary-keys ),则不允许使用复合键。有没有办法可以将复合键重构成一个简单的键,这样它就适合这个范例,或者我应该咬一口并安装宝石?
我还处于早期设计阶段,所以我没有需要担心的数据,我希望尽可能保持对Rails习语的忠诚。
我正在创建一个配方数据库,可以逐步列出成分和说明。数据库模式类似于下面显示的模式,并在Recipe_Steps和Recipe_Step_Ingredients表(图像的底部中心)中使用复合键。
答案 0 :(得分:0)
你很可能过度思考并使问题过于复杂。坚持使用名为id
的单个主键的AR惯用语。
对于连接表,使用外键而不是复合PK。同时坚持命名惯例,除非你想通过违反最小惊喜的原则看起来无能为力或惹恼其他开发者。这意味着:
snake_case
表示所有内容(表名,列,索引名等)_id
用于外键列。前; parent_id
_at
作为时间戳。前; confirmed_at
thing_other_things
用于连接表,除非有更具描述性的名称这些情况中的许多情况也应该使用间接关系来连接层次结构而不是复制外键。
这是一个示例数据库架构:
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