2016-12-13 55 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