diff --git a/backend/app/models/language.rb b/backend/app/models/language.rb new file mode 100644 index 0000000..cd37ec3 --- /dev/null +++ b/backend/app/models/language.rb @@ -0,0 +1,3 @@ +class Language < ApplicationRecord + has_many :languages, class_name: 'Locale', foreign_key: :language_code +end diff --git a/backend/app/models/locale.rb b/backend/app/models/locale.rb new file mode 100644 index 0000000..06b644b --- /dev/null +++ b/backend/app/models/locale.rb @@ -0,0 +1,6 @@ +class Locale < ApplicationRecord + belongs_to :language_code, class_name: 'Language', foreign_key: :code + belongs_to :script_code, class_name: 'Script', foreign_key: :code + + def self.nipponese = Locale.find('ja') +end diff --git a/backend/app/models/script.rb b/backend/app/models/script.rb new file mode 100644 index 0000000..43abe1f --- /dev/null +++ b/backend/app/models/script.rb @@ -0,0 +1,3 @@ +class Script < ApplicationRecord + ; +end diff --git a/backend/db/migrate/20260919030000_add_columns_to_tag_names.rb b/backend/db/migrate/20260919030000_add_columns_to_tag_names.rb index c0e3784..083a414 100644 --- a/backend/db/migrate/20260919030000_add_columns_to_tag_names.rb +++ b/backend/db/migrate/20260919030000_add_columns_to_tag_names.rb @@ -1,9 +1,12 @@ class AddColumnsToTagNames < ActiveRecord::Migration[8.0] def up + add_reference :tag_names, :tag, after: :id, foreign_key: true add_column :tag_names, :language_code, :string, - limit: 16, null: false, after: :id, default: 'ja' + limit: 16, null: false, after: :tag_id, default: 'ja' add_column :tag_names, :script_code, 'CHAR(4)', null: false, after: :name, default: 'Jpan' + add_column :tag_names, :primary_flg, :boolean, + null: false, after: :script_code, default: true add_foreign_key :tag_names, :languages, column: :language_code, primary_key: :code add_foreign_key :tag_names, :scripts, column: :script_code, primary_key: :code @@ -13,16 +16,44 @@ class AddColumnsToTagNames < ActiveRecord::Migration[8.0] change_column_default :tag_names, :language_code, from: 'ja', to: nil change_column_default :tag_names, :script_code, from: 'Jpan', to: nil + + execute <<~SQL + UPDATE + tag_names tn + LEFT JOIN + tags AS t + ON + t.tag_name_id = COALESCE(tn.canonical_id, tn.id) + SET + tn.tag_id = t.id + , tn.primary_flg = CASE + WHEN tn.canonical_id IS NULL THEN + 1 + ELSE + 0 + END + SQL + + change_column_default :tag_names, :primary_flg, from: true, to: nil + + add_column :tag_names, :primary_tag_id, :bigint, + as: 'CASE WHEN primary_flg THEN tag_id ELSE NULL END' + add_index :tag_names, [:primary_tag_id, :language_code], unique: true end def down + remove_index :tag_names, [:primary_tag_id, :language_code] + remove_column :tag_names, :primary_tag_id + remove_foreign_key :tag_names, column: :language_code remove_foreign_key :tag_names, column: :script_code remove_index :tag_names, [:language_code, :name] add_index :tag_names, :name, unique: true + remove_column :tag_names, :primary_flg remove_column :tag_names, :script_code remove_column :tag_names, :language_code + remove_reference :tag_names, :tag, foreign_key: true end end diff --git a/backend/db/schema.rb b/backend/db/schema.rb index 5ebbcc5..74bc2d4 100644 --- a/backend/db/schema.rb +++ b/backend/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[8.0].define(version: 2026_07_27_123600) do +ActiveRecord::Schema[8.0].define(version: 2026_09_19_030000) do create_table "active_storage_attachments", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.string "name", null: false t.string "record_type", null: false @@ -130,6 +130,24 @@ ActiveRecord::Schema[8.0].define(version: 2026_07_27_123600) do t.index ["ip_address"], name: "index_ip_addresses_on_ip_address", unique: true end + create_table "languages", primary_key: "code", id: { type: :string, limit: 16 }, charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.string "name", null: false + t.datetime "deprecated_at" + t.datetime "created_at", null: false + t.index ["deprecated_at"], name: "index_languages_on_deprecated_at" + end + + create_table "locales", primary_key: "code", id: { type: :string, limit: 32 }, charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.string "language_code", limit: 16, null: false + t.string "script_code", limit: 4, null: false + t.string "name", null: false + t.datetime "deprecated_at" + t.datetime "created_at", null: false + t.index ["deprecated_at"], name: "index_locales_on_deprecated_at" + t.index ["language_code"], name: "index_locales_on_language_code" + t.index ["script_code"], name: "fk_rails_0b74ce96a8" + end + create_table "material_export_items", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.bigint "material_id", null: false t.string "profile", default: "legacy_drive", null: false @@ -384,6 +402,13 @@ ActiveRecord::Schema[8.0].define(version: 2026_07_27_123600) do t.check_constraint "`version_no` > 0", name: "chk_posts_version_no_positive" end + create_table "scripts", primary_key: "code", id: { type: :string, limit: 4 }, charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.string "name", null: false + t.datetime "deprecated_at" + t.datetime "created_at", null: false + t.index ["deprecated_at"], name: "index_scripts_on_deprecated_at" + end + create_table "settings", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.bigint "user_id", null: false t.datetime "created_at", null: false @@ -395,19 +420,6 @@ ActiveRecord::Schema[8.0].define(version: 2026_07_27_123600) do t.index ["user_id"], name: "index_settings_on_user_id", unique: true end - create_table "wiki_assets", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| - t.bigint "wiki_page_id", null: false - t.integer "no", null: false - t.string "alt_text" - t.binary "sha256", limit: 32, null: false - t.bigint "created_by_user_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["created_by_user_id"], name: "index_wiki_assets_on_created_by_user_id" - t.index ["wiki_page_id", "no"], name: "index_wiki_assets_on_wiki_page_id_and_no", unique: true - t.index ["wiki_page_id", "sha256"], name: "index_wiki_assets_on_wiki_page_id_and_sha256", unique: true - end - create_table "tag_implications", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.bigint "tag_id", null: false t.bigint "parent_tag_id", null: false @@ -429,14 +441,22 @@ ActiveRecord::Schema[8.0].define(version: 2026_07_27_123600) do end create_table "tag_names", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "tag_id" + t.string "language_code", limit: 16, null: false t.string "name", null: false + t.string "script_code", limit: 4, null: false + t.boolean "primary_flg", null: false t.bigint "canonical_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.datetime "discarded_at" + t.virtual "primary_tag_id", type: :bigint, as: "(case when `primary_flg` then `tag_id` else NULL end)" t.index ["canonical_id"], name: "index_tag_names_on_canonical_id" t.index ["discarded_at"], name: "index_tag_names_on_discarded_at" - t.index ["name"], name: "index_tag_names_on_name", unique: true + t.index ["language_code", "name"], name: "index_tag_names_on_language_code_and_name", unique: true + t.index ["primary_tag_id", "language_code"], name: "index_tag_names_on_primary_tag_id_and_language_code", unique: true + t.index ["script_code"], name: "fk_rails_dd783b3d1c" + t.index ["tag_id"], name: "index_tag_names_on_tag_id" end create_table "tag_similarities", primary_key: ["tag_id", "target_tag_id"], charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| @@ -632,7 +652,6 @@ ActiveRecord::Schema[8.0].define(version: 2026_07_27_123600) do t.datetime "created_at", null: false t.datetime "updated_at", null: false t.datetime "discarded_at" - t.integer "next_asset_no", default: 1, null: false t.integer "version_no", null: false t.index ["created_user_id"], name: "index_wiki_pages_on_created_user_id" t.index ["discarded_at"], name: "index_wiki_pages_on_discarded_at" @@ -701,6 +720,8 @@ ActiveRecord::Schema[8.0].define(version: 2026_07_27_123600) do add_foreign_key "gekanator_question_suggestions", "users" add_foreign_key "gekanator_questions", "gekanator_question_suggestions" add_foreign_key "gekanator_questions", "users", column: "created_by_id" + add_foreign_key "locales", "languages", column: "language_code", primary_key: "code" + add_foreign_key "locales", "scripts", column: "script_code", primary_key: "code" add_foreign_key "material_export_items", "materials" add_foreign_key "material_export_items", "users", column: "created_by_user_id" add_foreign_key "material_import_blocks", "users", column: "created_by_user_id" @@ -736,7 +757,10 @@ ActiveRecord::Schema[8.0].define(version: 2026_07_27_123600) do add_foreign_key "settings", "users" add_foreign_key "tag_implications", "tags" add_foreign_key "tag_implications", "tags", column: "parent_tag_id" + add_foreign_key "tag_names", "languages", column: "language_code", primary_key: "code" + add_foreign_key "tag_names", "scripts", column: "script_code", primary_key: "code" add_foreign_key "tag_names", "tag_names", column: "canonical_id" + add_foreign_key "tag_names", "tags" add_foreign_key "tag_similarities", "tags" add_foreign_key "tag_similarities", "tags", column: "target_tag_id" add_foreign_key "tag_versions", "tags" @@ -766,8 +790,6 @@ ActiveRecord::Schema[8.0].define(version: 2026_07_27_123600) do add_foreign_key "user_post_views", "posts" add_foreign_key "user_post_views", "users" add_foreign_key "user_theme_slots", "users" - add_foreign_key "wiki_assets", "users", column: "created_by_user_id" - add_foreign_key "wiki_assets", "wiki_pages" add_foreign_key "wiki_pages", "tag_names" add_foreign_key "wiki_pages", "users", column: "created_user_id" add_foreign_key "wiki_pages", "users", column: "updated_user_id"