2016-12-13 5 views
0

私のアプリケーションは、composite-primary-keysのようなサードパーティの宝石をインストールせずにコンポジットキーを許可しないRuby on Rails ActiveRecordモデルを使用しています。コンポジットキーを単純なキーにリファクタリングしてこのパラダイムに合うようにする方法はありますか?または、弾丸を噛んで宝石をインストールする必要がありますか?複合主キーをRailsの簡単なキーにリファクタリングしますか?

私はまだ初期の設計段階にありますので、私は心配する必要のあるデータがなく、可能な限りRailsの慣用句にしておきたいと思います。

私は原料と手順を段階的にリストすることができるレシピデータベースを作成しています。データベーススキーマは、以下に示すものと似ており、Recipe_StepsおよびRecipe_Step_Ingredientsテーブル(イメージの中央下部)に複合キーを使用しています。

Database schema

答えて

0

あなたは可能性が非常に高いoverthinkingと、問題が複雑になり過ぎています。単一の主キーidを使用するARのイディオムを守ってください。

結合テーブルでは、複合PKの代わりに外部キーを使用します。また、少なくとも驚きの原則に違反することによって、他の開発者を無益に見せたり、悩ませたりしない限り、命名規則に従ってください。それは意味:すべてのため

  • 使用snake_case(テーブル名、カラム、インデックス名など)
  • は、テーブル名と列の接頭辞はありませんが。これは、アプリケーション内のすべての変数を長くし、ORMで必要としないだけです。
  • 外部キー列に_idを使用します。 ex。 parent_id
  • タイムスタンプは_atです。 ex。 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

恐らくそれ自体が過度に複雑すぎます。 'recipes'と' ingredients'を結びつける結合テーブルだけでなく、ステップの原料の量を本当に保存する必要がありますか? – max

+0

ほとんどのレシピは、一緒にリストアップされた成分を持っています。そして、ステップの中に「卵と4つの半分を混ぜる」のようなものを書きます。キッス。 – max

関連する問題