From 69a68ae3e7d2fa3fbde11b53f91b9d9516eb36fd Mon Sep 17 00:00:00 2001 From: adi-herwana-nus Date: Fri, 28 Aug 2026 16:57:25 +0800 Subject: [PATCH 1/2] fix(personal_times): make index unique on course_user_id,lesson_plan_item_id - resolve wrongly-named sequence for programming_test_results table --- ...d_unique_index_to_course_personal_times.rb | 15 + ...8084949_stabilize_schema_dump_artifacts.rb | 50 + db/schema.rb | 1118 ++++++++--------- 3 files changed, 624 insertions(+), 559 deletions(-) create mode 100644 db/migrate/20260828083444_add_unique_index_to_course_personal_times.rb create mode 100644 db/migrate/20260828084949_stabilize_schema_dump_artifacts.rb diff --git a/db/migrate/20260828083444_add_unique_index_to_course_personal_times.rb b/db/migrate/20260828083444_add_unique_index_to_course_personal_times.rb new file mode 100644 index 0000000000..6e06c0c706 --- /dev/null +++ b/db/migrate/20260828083444_add_unique_index_to_course_personal_times.rb @@ -0,0 +1,15 @@ +class AddUniqueIndexToCoursePersonalTimes < ActiveRecord::Migration[8.1] + def change + # There is at most one personal time per (course_user, lesson_plan_item) pair. This was only ever + # enforced by a model-level uniqueness validation (a check-then-insert), which two concurrent + # personalized-timeline writers can both pass, each inserting a row. Back the invariant with a + # database unique index so the losing writer's transaction fails instead of silently duplicating. + add_index :course_personal_times, [:course_user_id, :lesson_plan_item_id], + unique: true, name: 'index_course_personal_times_on_user_and_item' + + # The composite index above leads with course_user_id, so it serves every lookup the standalone + # course_user_id index did. Drop the now-redundant single-column index. + remove_index :course_personal_times, :course_user_id, + name: 'index_course_personal_times_on_course_user_id' + end +end diff --git a/db/migrate/20260828084949_stabilize_schema_dump_artifacts.rb b/db/migrate/20260828084949_stabilize_schema_dump_artifacts.rb new file mode 100644 index 0000000000..127c40e8bc --- /dev/null +++ b/db/migrate/20260828084949_stabilize_schema_dump_artifacts.rb @@ -0,0 +1,50 @@ +class StabilizeSchemaDumpArtifacts < ActiveRecord::Migration[8.1] + # Two pre-existing objects whose Rails 8.1 schema.rb rendering is unstable (it flips depending on + # whether a database was built by running migrations or by `db:schema:load`). Both are semantically + # unchanged here; we only pin them to their dumper-stable form so schema.rb stops drifting. + + # 1. The id sequence of course_assessment_answer_programming_test_results kept a truncated name from + # an old table rename, so it no longer matches the `_id_seq` convention and the PK dumps as + # an explicit `nextval(...)` default instead of `id: :serial`. Renaming is catalog-only; the + # column default references the sequence by OID and follows the rename automatically. + OLD_SEQUENCE = 'course_assessment_answer_programming_auto_grading_test_r_id_seq' + NEW_SEQUENCE = 'course_assessment_answer_programming_test_results_id_seq' + + # 2. A partial unique index whose predicate was written as `evaluation_type IN (...)`. Postgres + # normalises IN to a whole-array cast that pg_get_expr renders one way from the migration and + # another way after a schema.rb round-trip. The per-element form below is a fixed point of that + # round-trip, so we recreate the index with it. + RUBRIC_INDEX = 'index_course_rubric_playground_evaluation_on_answer_rubric' + PLAYGROUND_PREDICATE_STABLE = + "((evaluation_type)::text = ANY (ARRAY[('playground'::character varying)::text, " \ + "('playground_hidden'::character varying)::text]))" + PLAYGROUND_PREDICATE_ORIGINAL = "evaluation_type IN ('playground', 'playground_hidden')" + + def up + rename_sequence(OLD_SEQUENCE, NEW_SEQUENCE) + recreate_playground_index(PLAYGROUND_PREDICATE_STABLE) + end + + def down + rename_sequence(NEW_SEQUENCE, OLD_SEQUENCE) + recreate_playground_index(PLAYGROUND_PREDICATE_ORIGINAL) + end + + private + + # Only rename when the source name is present: databases built via `db:schema:load` already carry the + # conventional sequence name, so there is nothing to rename there. + def rename_sequence(from, to) + return unless connection.select_value( + "SELECT 1 FROM pg_class WHERE relkind = 'S' AND relname = #{connection.quote(from)}" + ) + + execute("ALTER SEQUENCE #{from} RENAME TO #{to}") + end + + def recreate_playground_index(predicate) + remove_index :course_rubric_answer_evaluations, name: RUBRIC_INDEX + add_index :course_rubric_answer_evaluations, [:answer_id, :rubric_id], + unique: true, where: predicate, name: RUBRIC_INDEX + end +end diff --git a/db/schema.rb b/db/schema.rb index e3346acf8e..661ef9e92b 100644 --- a/db/schema.rb +++ b/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_08_04_222525) do +ActiveRecord::Schema[8.1].define(version: 2026_08_28_084949) do # These are extensions that must be enabled in order to support this database enable_extension "pg_catalog.plpgsql" enable_extension "uuid-ossp" @@ -18,11 +18,11 @@ create_table "activities", id: :serial, force: :cascade do |t| t.integer "actor_id", null: false - t.integer "object_id", null: false - t.string "object_type", limit: 255, null: false + t.datetime "created_at", precision: nil, null: false t.string "event", limit: 255, null: false t.string "notifier_type", limit: 255, null: false - t.datetime "created_at", precision: nil, null: false + t.integer "object_id", null: false + t.string "object_type", limit: 255, null: false t.datetime "updated_at", precision: nil, null: false t.index ["actor_id"], name: "fk__activities_actor_id" end @@ -31,12 +31,12 @@ t.integer "attachable_id" t.string "attachable_type", limit: 255 t.integer "attachment_id", null: false - t.string "name", limit: 255, null: false - t.datetime "expires_at", precision: nil - t.integer "creator_id", null: false - t.integer "updater_id", null: false t.datetime "created_at", precision: nil, null: false + t.integer "creator_id", null: false + t.datetime "expires_at", precision: nil + t.string "name", limit: 255, null: false t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false t.index ["attachable_type", "attachable_id"], name: "fk__attachment_references_attachable_id" t.index ["attachment_id"], name: "fk__attachment_references_attachment_id" t.index ["creator_id"], name: "fk__attachment_references_creator_id" @@ -44,48 +44,48 @@ end create_table "attachments", id: :serial, force: :cascade do |t| - t.string "name", limit: 255, null: false - t.text "file_upload", null: false t.datetime "created_at", precision: nil, null: false + t.text "file_upload", null: false + t.string "name", limit: 255, null: false t.datetime "updated_at", precision: nil, null: false t.index ["name"], name: "index_attachments_on_name", unique: true end create_table "cikgo_users", force: :cascade do |t| - t.bigint "user_id", null: false t.string "provided_user_id", null: false + t.bigint "user_id", null: false t.index ["user_id"], name: "index_cikgo_users_on_user_id" end create_table "course_achievements", id: :serial, force: :cascade do |t| + t.text "badge" t.integer "course_id", null: false - t.string "title", limit: 255, null: false + t.datetime "created_at", precision: nil, null: false + t.integer "creator_id", null: false t.text "description" - t.text "badge" - t.integer "weight", null: false t.boolean "published", null: false - t.integer "creator_id", null: false - t.integer "updater_id", null: false - t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false t.integer "satisfiability_type", default: 0 + t.string "title", limit: 255, null: false + t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false + t.integer "weight", null: false t.index ["course_id"], name: "fk__course_achievements_course_id" t.index ["creator_id"], name: "fk__course_achievements_creator_id" t.index ["updater_id"], name: "fk__course_achievements_updater_id" end create_table "course_announcements", id: :serial, force: :cascade do |t| - t.integer "course_id", null: false - t.string "title", limit: 255, null: false t.text "content" - t.boolean "sticky", default: false, null: false - t.datetime "start_at", precision: nil, null: false - t.datetime "end_at", precision: nil, null: false - t.integer "creator_id", null: false - t.integer "updater_id", null: false + t.integer "course_id", null: false t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false + t.integer "creator_id", null: false + t.datetime "end_at", precision: nil, null: false t.float "opening_reminder_token" + t.datetime "start_at", precision: nil, null: false + t.boolean "sticky", default: false, null: false + t.string "title", limit: 255, null: false + t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false t.index ["course_id"], name: "fk__course_announcements_course_id" t.index ["creator_id"], name: "fk__course_announcements_creator_id" t.index ["updater_id"], name: "fk__course_announcements_updater_id" @@ -95,9 +95,9 @@ t.integer "actable_id" t.string "actable_type", limit: 255 t.integer "answer_id", null: false + t.datetime "created_at", precision: nil, null: false t.uuid "job_id" t.json "result" - t.datetime "created_at", precision: nil, null: false t.datetime "updated_at", precision: nil, null: false t.index ["actable_id", "actable_type"], name: "index_course_assessment_answer_auto_gradings_on_actable", unique: true t.index ["answer_id"], name: "index_course_assessment_answer_auto_gradings_on_answer_id", unique: true @@ -111,14 +111,14 @@ create_table "course_assessment_answer_forum_posts", force: :cascade do |t| t.bigint "answer_id", null: false t.integer "forum_topic_id", null: false - t.integer "post_id", null: false - t.string "post_text", null: false - t.integer "post_creator_id", null: false - t.datetime "post_updated_at", precision: nil, null: false + t.integer "parent_creator_id" t.integer "parent_id" t.string "parent_text" - t.integer "parent_creator_id" t.datetime "parent_updated_at", precision: nil + t.integer "post_creator_id", null: false + t.integer "post_id", null: false + t.string "post_text", null: false + t.datetime "post_updated_at", precision: nil, null: false t.index ["answer_id"], name: "index_course_assessment_answer_forum_posts_on_answer_id" end @@ -139,9 +139,9 @@ end create_table "course_assessment_answer_programming_auto_gradings", id: :serial, force: :cascade do |t| - t.text "stdout" - t.text "stderr" t.integer "exit_code" + t.text "stderr" + t.text "stdout" end create_table "course_assessment_answer_programming_file_annotations", id: :serial, force: :cascade do |t| @@ -152,17 +152,17 @@ create_table "course_assessment_answer_programming_files", id: :serial, force: :cascade do |t| t.integer "answer_id", null: false - t.string "filename", limit: 255, null: false t.text "content", default: "", null: false + t.string "filename", limit: 255, null: false t.index "answer_id, lower((filename)::text)", name: "index_course_assessment_answer_programming_files_filename", unique: true t.index ["answer_id"], name: "fk__course_assessment_answer_programming_files_answer_id" end create_table "course_assessment_answer_programming_test_results", id: :serial, force: :cascade do |t| t.integer "auto_grading_id", null: false - t.integer "test_case_id" - t.boolean "passed", null: false t.jsonb "messages", default: {}, null: false + t.boolean "passed", null: false + t.integer "test_case_id" t.index ["auto_grading_id"], name: "fk__course_assessment_answe_3d4bf9a99ed787551e4454c7106971fc" t.index ["test_case_id"], name: "fk__course_assessment_answe_ca0d5ba368869806d2a9cb8717feed4f" end @@ -171,8 +171,8 @@ t.bigint "answer_id", null: false t.bigint "category_id", null: false t.bigint "criterion_id" - t.integer "grade" t.text "explanation" + t.integer "grade" t.index ["answer_id"], name: "fk__course_assessment_answer_rubric_based_response_selections" t.index ["category_id"], name: "fk__course_assessment_answer_rubric_based_category_selections" t.index ["criterion_id"], name: "fk__course_assessment_answer_rubric_based_question_criterions" @@ -183,10 +183,10 @@ end create_table "course_assessment_answer_scribing_scribbles", id: :serial, force: :cascade do |t| - t.text "content" t.integer "answer_id", null: false - t.integer "creator_id", null: false + t.text "content" t.datetime "created_at", precision: nil, null: false + t.integer "creator_id", null: false t.datetime "updated_at", precision: nil, null: false t.index ["answer_id"], name: "fk__course_assessment_answer_scribing_scribbles_scribing_answer" t.index ["creator_id"], name: "fk__course_assessment_answer_scribing_scribbles_creator_id" @@ -205,19 +205,19 @@ create_table "course_assessment_answers", id: :serial, force: :cascade do |t| t.integer "actable_id" t.string "actable_type", limit: 255 - t.integer "submission_id", null: false - t.integer "question_id", null: false - t.string "workflow_state", limit: 255, null: false - t.datetime "submitted_at", precision: nil - t.decimal "grade", precision: 4, scale: 1 + t.bigint "client_version" t.boolean "correct" - t.integer "grader_id" - t.datetime "graded_at", precision: nil t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false t.boolean "current_answer", default: false, null: false + t.decimal "grade", precision: 4, scale: 1 + t.datetime "graded_at", precision: nil + t.integer "grader_id" t.string "last_session_id" - t.bigint "client_version" + t.integer "question_id", null: false + t.integer "submission_id", null: false + t.datetime "submitted_at", precision: nil + t.datetime "updated_at", precision: nil, null: false + t.string "workflow_state", limit: 255, null: false t.index ["actable_type", "actable_id"], name: "index_course_assessment_answers_actable", unique: true t.index ["grader_id"], name: "fk__course_assessment_answers_grader_id" t.index ["question_id"], name: "fk__course_assessment_answers_question_id" @@ -226,12 +226,12 @@ create_table "course_assessment_categories", id: :serial, force: :cascade do |t| t.integer "course_id", null: false - t.string "title", limit: 255, null: false - t.integer "weight", null: false - t.integer "creator_id", null: false - t.integer "updater_id", null: false t.datetime "created_at", precision: nil, null: false + t.integer "creator_id", null: false + t.string "title", limit: 255, null: false t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false + t.integer "weight", null: false t.index ["course_id"], name: "fk__course_assessment_categories_course_id" t.index ["creator_id"], name: "fk__course_assessment_categories_creator_id" t.index ["updater_id"], name: "fk__course_assessment_categories_updater_id" @@ -246,48 +246,48 @@ end create_table "course_assessment_live_feedback_code", force: :cascade do |t| + t.text "content", null: false t.bigint "feedback_id", null: false t.string "filename", null: false - t.text "content", null: false t.index ["feedback_id"], name: "index_course_assessment_live_feedback_code_on_feedback_id" end create_table "course_assessment_live_feedback_comments", force: :cascade do |t| t.bigint "code_id", null: false - t.integer "line_number", null: false t.text "comment", null: false + t.integer "line_number", null: false t.index ["code_id"], name: "index_course_assessment_live_feedback_comments_on_code_id" end create_table "course_assessment_live_feedbacks", force: :cascade do |t| t.bigint "assessment_id", null: false - t.bigint "question_id", null: false - t.bigint "creator_id", null: false t.datetime "created_at", null: false + t.bigint "creator_id", null: false t.string "feedback_id" + t.bigint "question_id", null: false t.index ["assessment_id"], name: "index_course_assessment_live_feedbacks_on_assessment_id" t.index ["creator_id"], name: "index_course_assessment_live_feedbacks_on_creator_id" t.index ["question_id"], name: "index_course_assessment_live_feedbacks_on_question_id" end create_table "course_assessment_marketplace_access_blocks", force: :cascade do |t| - t.bigint "user_id", null: false - t.bigint "creator_id", null: false t.datetime "created_at", null: false + t.bigint "creator_id", null: false t.datetime "updated_at", null: false + t.bigint "user_id", null: false t.index ["creator_id"], name: "idx_on_creator_id_becaf2e041" t.index ["user_id"], name: "index_course_assessment_marketplace_access_blocks_on_user_id", unique: true end create_table "course_assessment_marketplace_adoptions", force: :cascade do |t| - t.bigint "listing_id", null: false - t.bigint "destination_course_id", null: false - t.bigint "duplicated_assessment_id", null: false t.datetime "adopted_version_at" - t.bigint "creator_id", null: false - t.bigint "updater_id", null: false t.datetime "created_at", null: false + t.bigint "creator_id", null: false + t.bigint "destination_course_id", null: false + t.bigint "duplicated_assessment_id", null: false + t.bigint "listing_id", null: false t.datetime "updated_at", null: false + t.bigint "updater_id", null: false t.index ["creator_id"], name: "fk__cama_creator_id" t.index ["destination_course_id"], name: "fk__cama_destination_course_id" t.index ["duplicated_assessment_id"], name: "fk__cama_duplicated_assessment_id", unique: true @@ -297,12 +297,12 @@ end create_table "course_assessment_marketplace_allowlist_rules", force: :cascade do |t| - t.integer "rule_type", null: false - t.bigint "user_id" - t.bigint "instance_id" - t.string "email_domain" t.datetime "created_at", null: false + t.string "email_domain" + t.bigint "instance_id" + t.integer "rule_type", null: false t.datetime "updated_at", null: false + t.bigint "user_id" t.index ["email_domain"], name: "idx_on_email_domain_6577b88d4e" t.index ["email_domain"], name: "index_marketplace_allowlist_rules_one_per_email_domain", unique: true, where: "(rule_type = 2)" t.index ["instance_id"], name: "idx_on_instance_id_77af5cff27" @@ -313,14 +313,14 @@ end create_table "course_assessment_marketplace_listing_versions", force: :cascade do |t| + t.bigint "assessment_id", null: false + t.datetime "created_at", null: false + t.bigint "creator_id", null: false t.bigint "listing_id", null: false t.datetime "published_at", null: false - t.bigint "assessment_id", null: false t.bigint "published_by_id", null: false - t.bigint "creator_id", null: false - t.bigint "updater_id", null: false - t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.bigint "updater_id", null: false t.index ["assessment_id"], name: "fk__camlv_assessment_id" t.index ["creator_id"], name: "fk__camlv_creator_id" t.index ["listing_id", "published_at"], name: "index_camlv_on_listing_id_and_published_at", unique: true @@ -331,19 +331,19 @@ create_table "course_assessment_marketplace_listings", force: :cascade do |t| t.bigint "authoring_assessment_id" - t.boolean "published", default: false, null: false + t.datetime "created_at", null: false + t.bigint "creator_id", null: false + t.bigint "current_version_id" + t.bigint "fallback_maintainer_id" t.datetime "first_published_at" t.datetime "last_published_at" + t.boolean "published", default: false, null: false + t.bigint "publisher_id", null: false t.bigint "source_course_id" t.string "source_course_name" t.bigint "source_instance_id" - t.bigint "current_version_id" - t.bigint "fallback_maintainer_id" - t.bigint "publisher_id", null: false - t.bigint "creator_id", null: false - t.bigint "updater_id", null: false - t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.bigint "updater_id", null: false t.index ["authoring_assessment_id"], name: "index_caml_on_authoring_assessment_id", unique: true, where: "(authoring_assessment_id IS NOT NULL)" t.index ["creator_id"], name: "fk__course_assessment_marketplace_listings_creator_id" t.index ["current_version_id"], name: "fk__caml_current_version_id" @@ -356,21 +356,21 @@ end create_table "course_assessment_plagiarism_checks", force: :cascade do |t| + t.bigint "assessment_id", null: false t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false + t.uuid "job_id" t.datetime "last_started_at", precision: nil + t.datetime "updated_at", precision: nil, null: false t.string "workflow_state", limit: 255, default: "not_started", null: false - t.bigint "assessment_id", null: false - t.uuid "job_id" t.index ["assessment_id"], name: "fk__course_assessment_plagiarism_checks_assessment_id", unique: true t.index ["job_id"], name: "fk__course_assessment_plagiarism_checks_job_id", unique: true end create_table "course_assessment_question_bundle_assignments", force: :cascade do |t| - t.bigint "user_id", null: false t.bigint "assessment_id", null: false - t.bigint "submission_id" t.bigint "bundle_id", null: false + t.bigint "submission_id" + t.bigint "user_id", null: false t.index ["assessment_id"], name: "idx_course_assessment_question_bundle_assignments_on_assmt_id" t.index ["bundle_id"], name: "idx_course_assessment_question_bundle_assignments_on_bundle_id" t.index ["submission_id"], name: "idx_course_assessment_question_bundle_assignments_on_sub_id" @@ -387,25 +387,25 @@ end create_table "course_assessment_question_bundles", force: :cascade do |t| - t.string "title", null: false t.bigint "group_id", null: false + t.string "title", null: false t.index ["group_id"], name: "index_course_assessment_question_bundles_on_group_id" end create_table "course_assessment_question_forum_post_responses", force: :cascade do |t| + t.boolean "ai_grading_enabled", default: true, null: false t.boolean "has_text_response", default: false t.integer "max_posts", limit: 2, null: false - t.boolean "ai_grading_enabled", default: true, null: false end create_table "course_assessment_question_grading_contexts", force: :cascade do |t| - t.bigint "question_id", null: false t.string "context_type", null: false - t.string "source_type" - t.bigint "source_id" + t.datetime "created_at", null: false t.string "identifier", null: false t.jsonb "options", default: {}, null: false - t.datetime "created_at", null: false + t.bigint "question_id", null: false + t.bigint "source_id" + t.string "source_type" t.datetime "updated_at", null: false t.index ["question_id", "identifier"], name: "index_grading_contexts_on_question_and_identifier", unique: true t.index ["question_id"], name: "idx_on_question_id_46e914c3d4" @@ -413,17 +413,17 @@ end create_table "course_assessment_question_groups", force: :cascade do |t| - t.string "title", null: false t.bigint "assessment_id", null: false + t.string "title", null: false t.integer "weight", null: false t.index ["assessment_id"], name: "index_course_assessment_question_groups_on_assessment_id" end create_table "course_assessment_question_mock_answer_grading_contexts", force: :cascade do |t| - t.bigint "mock_answer_id", null: false - t.bigint "grading_context_id", null: false t.text "content", default: "", null: false t.datetime "created_at", null: false + t.bigint "grading_context_id", null: false + t.bigint "mock_answer_id", null: false t.datetime "updated_at", null: false t.index ["grading_context_id"], name: "idx_on_grading_context_id_dda5f396e5" t.index ["mock_answer_id", "grading_context_id"], name: "index_mock_answer_grading_contexts_on_mock_and_context", unique: true @@ -431,20 +431,20 @@ end create_table "course_assessment_question_mock_answers", force: :cascade do |t| - t.bigint "question_id", null: false t.text "answer_text" t.boolean "is_ai_generated", default: false, null: false t.string "name", default: "", null: false + t.bigint "question_id", null: false t.index ["question_id"], name: "index_course_assessment_question_mock_answers_on_question_id" end create_table "course_assessment_question_multiple_response_options", id: :serial, force: :cascade do |t| - t.integer "question_id", null: false t.boolean "correct", null: false - t.text "option", null: false t.text "explanation" - t.integer "weight", null: false t.boolean "ignore_randomization", default: false + t.text "option", null: false + t.integer "question_id", null: false + t.integer "weight", null: false t.index ["question_id"], name: "fk__course_assessment_multiple_response_option_question" end @@ -455,60 +455,60 @@ end create_table "course_assessment_question_programming", id: :serial, force: :cascade do |t| - t.integer "language_id", null: false - t.integer "memory_limit" - t.integer "time_limit" - t.uuid "import_job_id" t.integer "attempt_limit" - t.integer "package_type", default: 0, null: false - t.boolean "multiple_file_submission", default: false, null: false - t.boolean "is_codaveri", default: false t.text "codaveri_id" - t.integer "codaveri_status" t.text "codaveri_message" - t.boolean "live_feedback_enabled", default: false, null: false - t.string "live_feedback_custom_prompt", default: "", null: false + t.integer "codaveri_status" + t.uuid "import_job_id" + t.boolean "is_codaveri", default: false t.boolean "is_synced_with_codaveri", default: false, null: false + t.integer "language_id", null: false + t.string "live_feedback_custom_prompt", default: "", null: false + t.boolean "live_feedback_enabled", default: false, null: false + t.integer "memory_limit" + t.boolean "multiple_file_submission", default: false, null: false + t.integer "package_type", default: 0, null: false + t.integer "time_limit" t.index ["import_job_id"], name: "index_course_assessment_question_programming_on_import_job_id", unique: true t.index ["language_id"], name: "fk__course_assessment_question_programming_language_id" end create_table "course_assessment_question_programming_template_files", id: :serial, force: :cascade do |t| - t.integer "question_id", null: false - t.string "filename", limit: 255, null: false t.text "content", null: false + t.string "filename", limit: 255, null: false + t.integer "question_id", null: false t.index "question_id, lower((filename)::text)", name: "index_course_assessment_question_programming_template_filenames", unique: true t.index ["question_id"], name: "fk__course_assessment_quest_dbf3aed51f19fcc63a25d296a057dd1f" end create_table "course_assessment_question_programming_test_cases", id: :serial, force: :cascade do |t| - t.integer "question_id", null: false - t.string "identifier", limit: 255, null: false - t.integer "test_case_type", null: false - t.text "expression" t.text "expected" + t.text "expression" t.text "hint" + t.string "identifier", limit: 255, null: false + t.integer "question_id", null: false + t.integer "test_case_type", null: false t.index ["identifier", "question_id"], name: "index_course_assessment_question_programming_test_case_ident", unique: true t.index ["question_id"], name: "fk__course_assessment_quest_18b37224652fc59d955122a17ba20d07" end create_table "course_assessment_question_rubric_based_response_categories", force: :cascade do |t| - t.bigint "question_id", null: false - t.text "name", null: false t.boolean "is_bonus_category", default: false, null: false + t.text "name", null: false + t.bigint "question_id", null: false t.index ["question_id"], name: "fk__course_assessment_rubric_question_categories" end create_table "course_assessment_question_rubric_based_response_criterions", force: :cascade do |t| t.bigint "category_id", null: false - t.integer "grade", default: 0, null: false t.text "explanation", null: false + t.integer "grade", default: 0, null: false t.index ["category_id"], name: "fk__course_assessment_rubric_question_category_criterions" end create_table "course_assessment_question_rubric_based_responses", force: :cascade do |t| - t.boolean "ai_grading_enabled", default: true, null: false t.string "ai_grading_custom_prompt", default: "", null: false + t.boolean "ai_grading_enabled", default: true, null: false t.string "ai_grading_model_answer", default: "", null: false t.text "template_text" end @@ -524,8 +524,8 @@ end create_table "course_assessment_question_text_response_compre_groups", id: :serial, force: :cascade do |t| - t.integer "question_id", null: false t.decimal "maximum_group_grade", precision: 4, scale: 1, default: "0.0", null: false + t.integer "question_id", null: false t.index ["question_id"], name: "fk__course_assessment_text_response_compre_group_question" end @@ -536,42 +536,42 @@ end create_table "course_assessment_question_text_response_compre_solutions", id: :serial, force: :cascade do |t| + t.string "information" t.integer "point_id", null: false - t.integer "solution_type", default: 0, null: false t.string "solution", default: [], null: false, array: true t.string "solution_lemma", default: [], null: false, array: true - t.string "information" + t.integer "solution_type", default: 0, null: false t.index ["point_id"], name: "fk__course_assessment_text_response_compre_solution_point" end create_table "course_assessment_question_text_response_solution_spreadsheets", force: :cascade do |t| - t.bigint "solution_id", null: false - t.boolean "is_randomization_enabled", default: false, null: false t.boolean "is_random_seed_fixed", default: false, null: false - t.integer "test_random_seed" + t.boolean "is_randomization_enabled", default: false, null: false t.boolean "is_timestamp_fixed", default: false, null: false - t.datetime "test_timestamp" t.integer "num_random_tests", default: 2, null: false - t.jsonb "variables", default: [], null: false + t.bigint "solution_id", null: false t.string "target_sheet_name" + t.integer "test_random_seed" + t.datetime "test_timestamp" + t.jsonb "variables", default: [], null: false t.index ["solution_id"], name: "idx_on_solution_id_1073150e65" end create_table "course_assessment_question_text_response_solutions", id: :serial, force: :cascade do |t| + t.text "explanation" + t.decimal "grade", precision: 4, scale: 1, default: "0.0", null: false t.integer "question_id", null: false - t.integer "solution_type", default: 0, null: false t.text "solution", null: false - t.decimal "grade", precision: 4, scale: 1, default: "0.0", null: false - t.text "explanation" + t.integer "solution_type", default: 0, null: false t.index ["question_id"], name: "fk__course_assessment_text_response_solution_question" end create_table "course_assessment_question_text_responses", id: :serial, force: :cascade do |t| t.boolean "hide_text", default: false - t.boolean "is_comprehension", default: false t.boolean "is_attachment_required", default: false, null: false - t.integer "max_attachments", default: 0, null: false + t.boolean "is_comprehension", default: false t.integer "max_attachment_size" + t.integer "max_attachments", default: 0, null: false t.text "template_text" end @@ -581,19 +581,19 @@ create_table "course_assessment_questions", id: :serial, force: :cascade do |t| t.integer "actable_id" t.string "actable_type", limit: 255 - t.string "title", limit: 255 - t.text "description" - t.text "staff_only_comments" - t.decimal "maximum_grade", precision: 4, scale: 1, null: false - t.integer "creator_id", null: false - t.integer "updater_id", null: false + t.bigint "active_rubric_id" t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false + t.integer "creator_id", null: false + t.text "description" + t.string "grading_mode", default: "default", null: false t.boolean "is_low_priority", default: false - t.string "koditsu_question_id" t.boolean "is_synced_with_koditsu", default: false, null: false - t.bigint "active_rubric_id" - t.string "grading_mode", default: "default", null: false + t.string "koditsu_question_id" + t.decimal "maximum_grade", precision: 4, scale: 1, null: false + t.text "staff_only_comments" + t.string "title", limit: 255 + t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false t.index ["actable_type", "actable_id"], name: "index_course_assessment_questions_actable", unique: true t.index ["active_rubric_id"], name: "index_course_assessment_questions_on_active_rubric_id" t.index ["creator_id"], name: "fk__course_assessment_questions_creator_id" @@ -602,12 +602,12 @@ create_table "course_assessment_skill_branches", id: :serial, force: :cascade do |t| t.integer "course_id", null: false - t.string "title", limit: 255, null: false - t.text "description" - t.integer "creator_id", null: false - t.integer "updater_id", null: false t.datetime "created_at", precision: nil, null: false + t.integer "creator_id", null: false + t.text "description" + t.string "title", limit: 255, null: false t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false t.index ["course_id"], name: "fk__course_assessment_skill_branches_course_id" t.index ["creator_id"], name: "fk__course_assessment_skill_branches_creator_id" t.index ["updater_id"], name: "fk__course_assessment_skill_branches_updater_id" @@ -615,13 +615,13 @@ create_table "course_assessment_skills", id: :serial, force: :cascade do |t| t.integer "course_id", null: false + t.datetime "created_at", precision: nil, null: false + t.integer "creator_id", null: false + t.text "description" t.integer "skill_branch_id" t.string "title", limit: 255, null: false - t.text "description" - t.integer "creator_id", null: false - t.integer "updater_id", null: false - t.datetime "created_at", precision: nil, null: false t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false t.index ["course_id"], name: "fk__course_assessment_skills_course_id" t.index ["creator_id"], name: "fk__course_assessment_skills_creator_id" t.index ["skill_branch_id"], name: "fk__course_assessment_skills_skill_branch_id" @@ -637,16 +637,16 @@ end create_table "course_assessment_submission_logs", id: :serial, force: :cascade do |t| - t.integer "submission_id", null: false - t.jsonb "request" t.datetime "created_at", precision: nil, null: false + t.jsonb "request" + t.integer "submission_id", null: false t.index ["submission_id"], name: "fk__course_assessment_submission_logs_submission_id" end create_table "course_assessment_submission_questions", id: :serial, force: :cascade do |t| - t.integer "submission_id", null: false - t.integer "question_id", null: false t.datetime "created_at", precision: nil, null: false + t.integer "question_id", null: false + t.integer "submission_id", null: false t.datetime "updated_at", precision: nil, null: false t.index ["question_id"], name: "fk__course_assessment_submission_questions_question_id" t.index ["submission_id", "question_id"], name: "idx_course_assessment_submission_questions_on_sub_and_qn", unique: true @@ -655,18 +655,18 @@ create_table "course_assessment_submissions", id: :serial, force: :cascade do |t| t.integer "assessment_id", null: false - t.string "workflow_state", limit: 255, null: false - t.integer "creator_id", null: false - t.integer "updater_id", null: false t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false - t.integer "publisher_id" + t.integer "creator_id", null: false + t.datetime "force_submit_scheduled_at" + t.datetime "last_graded_time", precision: nil, default: "2021-11-09 00:08:09" t.datetime "published_at", precision: nil + t.integer "publisher_id" t.string "session_id", limit: 255 t.datetime "submitted_at", precision: nil - t.datetime "last_graded_time", precision: nil, default: "2021-11-09 00:08:09" t.datetime "unsubmitted_at" - t.datetime "force_submit_scheduled_at" + t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false + t.string "workflow_state", limit: 255, null: false t.index ["assessment_id", "creator_id"], name: "unique_assessment_id_and_creator_id", unique: true t.index ["assessment_id"], name: "fk__course_assessment_submissions_assessment_id" t.index ["creator_id"], name: "fk__course_assessment_submissions_creator_id" @@ -676,49 +676,49 @@ create_table "course_assessment_tabs", id: :serial, force: :cascade do |t| t.integer "category_id", null: false - t.string "title", limit: 255, null: false - t.integer "weight", null: false - t.integer "creator_id", null: false - t.integer "updater_id", null: false t.datetime "created_at", precision: nil, null: false + t.integer "creator_id", null: false + t.string "title", limit: 255, null: false t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false + t.integer "weight", null: false t.index ["category_id"], name: "fk__course_assessment_tabs_category_id" t.index ["creator_id"], name: "fk__course_assessment_tabs_creator_id" t.index ["updater_id"], name: "fk__course_assessment_tabs_updater_id" end create_table "course_assessments", id: :serial, force: :cascade do |t| - t.integer "tab_id", null: false + t.boolean "allow_partial_submission", default: false t.boolean "autograded", null: false - t.integer "creator_id", null: false - t.integer "updater_id", null: false + t.boolean "block_student_viewing_after_submitted", default: false t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false - t.string "session_password", limit: 255 - t.boolean "tabbed_view", default: false, null: false - t.boolean "skippable", default: false + t.integer "creator_id", null: false t.boolean "delayed_grade_publication", default: false - t.boolean "show_private", default: false - t.boolean "show_evaluation", default: false - t.string "view_password", limit: 255 - t.boolean "use_public", default: true - t.boolean "use_private", default: true - t.boolean "use_evaluation", default: false - t.boolean "allow_partial_submission", default: false + t.boolean "is_koditsu_enabled" + t.boolean "is_late_submission_allowed", default: true, null: false + t.boolean "is_synced_with_koditsu", default: false, null: false + t.string "koditsu_assessment_id" + t.integer "linkable_tree_id", default: 0, null: false + t.bigint "monitor_id" t.integer "randomization" + t.integer "satisfiability_type", default: 0 + t.string "session_password", limit: 255 + t.boolean "show_evaluation", default: false t.boolean "show_mcq_answer", default: true t.boolean "show_mcq_mrq_solution", default: true - t.boolean "block_student_viewing_after_submitted", default: false - t.integer "satisfiability_type", default: 0 - t.bigint "monitor_id" - t.integer "time_limit" - t.string "koditsu_assessment_id" - t.boolean "is_koditsu_enabled" - t.boolean "is_synced_with_koditsu", default: false, null: false + t.boolean "show_private", default: false t.boolean "show_rubric_to_students" + t.boolean "skippable", default: false t.uuid "ssid_folder_id" - t.integer "linkable_tree_id", default: 0, null: false - t.boolean "is_late_submission_allowed", default: true, null: false + t.integer "tab_id", null: false + t.boolean "tabbed_view", default: false, null: false + t.integer "time_limit" + t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false + t.boolean "use_evaluation", default: false + t.boolean "use_private", default: true + t.boolean "use_public", default: true + t.string "view_password", limit: 255 t.index ["creator_id"], name: "fk__course_assessments_creator_id" t.index ["linkable_tree_id"], name: "index_course_assessments_on_linkable_tree_id" t.index ["monitor_id"], name: "index_course_assessments_on_monitor_id" @@ -753,21 +753,21 @@ end create_table "course_condition_videos", force: :cascade do |t| - t.bigint "video_id", null: false t.float "minimum_watch_percentage" + t.bigint "video_id", null: false t.index ["video_id"], name: "fk__course_condition_videos_video_id" end create_table "course_conditions", id: :serial, force: :cascade do |t| t.integer "actable_id" t.string "actable_type", limit: 255 - t.integer "course_id", null: false t.integer "conditional_id", null: false t.string "conditional_type", limit: 255, null: false - t.integer "creator_id", null: false - t.integer "updater_id", null: false + t.integer "course_id", null: false t.datetime "created_at", precision: nil, null: false + t.integer "creator_id", null: false t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false t.index ["actable_type", "actable_id"], name: "index_course_conditions_on_actable_type_and_actable_id", unique: true t.index ["conditional_type", "conditional_id"], name: "index_course_conditions_on_conditional_type_and_conditional_id" t.index ["course_id"], name: "fk__course_conditions_course_id" @@ -776,24 +776,24 @@ end create_table "course_discussion_post_codaveri_feedbacks", force: :cascade do |t| - t.bigint "post_id", null: false - t.integer "status", default: 0 t.text "codaveri_feedback_id", null: false + t.datetime "created_at", null: false t.text "original_feedback", null: false + t.bigint "post_id", null: false t.integer "rating" - t.datetime "created_at", null: false + t.integer "status", default: 0 t.datetime "updated_at", null: false t.index ["post_id"], name: "fk__codaveri_feedback_discussion_post_id", unique: true t.index ["status"], name: "index_course_discussion_post_codaveri_feedbacks_on_status" end create_table "course_discussion_post_votes", id: :serial, force: :cascade do |t| - t.integer "post_id", null: false - t.boolean "vote_flag", null: false - t.integer "creator_id", null: false - t.integer "updater_id", null: false t.datetime "created_at", precision: nil, null: false + t.integer "creator_id", null: false + t.integer "post_id", null: false t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false + t.boolean "vote_flag", null: false t.index ["creator_id"], name: "fk__course_discussion_post_votes_creator_id" t.index ["post_id", "creator_id"], name: "index_course_discussion_post_votes_on_post_id_and_creator_id", unique: true t.index ["post_id"], name: "fk__course_discussion_post_votes_post_id" @@ -801,22 +801,22 @@ end create_table "course_discussion_posts", id: :serial, force: :cascade do |t| + t.boolean "answer", default: false + t.float "answer_relevance_score", default: 0.0, null: false + t.datetime "created_at", precision: nil, null: false + t.integer "creator_id", null: false + t.float "faithfulness_score", default: 0.0, null: false + t.boolean "is_ai_generated", default: false, null: false + t.boolean "is_anonymous", default: false, null: false + t.boolean "is_delayed", default: false, null: false + t.string "original_text" t.integer "parent_id" - t.integer "topic_id", null: false - t.string "title", limit: 255 t.text "text" - t.integer "creator_id", null: false - t.integer "updater_id", null: false - t.datetime "created_at", precision: nil, null: false + t.string "title", limit: 255 + t.integer "topic_id", null: false t.datetime "updated_at", precision: nil, null: false - t.boolean "answer", default: false - t.boolean "is_delayed", default: false, null: false + t.integer "updater_id", null: false t.string "workflow_state", default: "published" - t.boolean "is_anonymous", default: false, null: false - t.boolean "is_ai_generated", default: false, null: false - t.string "original_text" - t.float "faithfulness_score", default: 0.0, null: false - t.float "answer_relevance_score", default: 0.0, null: false t.index ["creator_id"], name: "fk__course_discussion_posts_creator_id" t.index ["parent_id"], name: "fk__course_discussion_posts_parent_id" t.index ["topic_id"], name: "fk__course_discussion_posts_topic_id" @@ -836,23 +836,23 @@ t.integer "actable_id" t.string "actable_type", limit: 255 t.integer "course_id", null: false - t.boolean "pending_staff_reply", default: false, null: false t.datetime "created_at", precision: nil, null: false + t.boolean "pending_staff_reply", default: false, null: false t.datetime "updated_at", precision: nil, null: false t.index ["actable_type", "actable_id"], name: "index_course_discussion_topics_on_actable_type_and_actable_id", unique: true t.index ["course_id"], name: "fk__course_discussion_topics_course_id" end create_table "course_enrol_requests", id: :serial, force: :cascade do |t| + t.datetime "confirmed_at", precision: nil + t.bigint "confirmer_id" t.integer "course_id", null: false - t.integer "user_id", null: false t.datetime "created_at", precision: nil - t.datetime "updated_at", precision: nil t.bigint "creator_id", null: false + t.datetime "updated_at", precision: nil t.bigint "updater_id", null: false + t.integer "user_id", null: false t.string "workflow_state", null: false - t.datetime "confirmed_at", precision: nil - t.bigint "confirmer_id" t.index ["confirmer_id"], name: "index_course_enrol_requests_on_confirmer_id" t.index ["course_id", "user_id"], name: "index_course_enrol_requests_on_course_id_and_user_id" t.index ["course_id"], name: "fk__course_enrol_requests_course_id" @@ -864,16 +864,16 @@ create_table "course_experience_points_records", id: :serial, force: :cascade do |t| t.integer "actable_id" t.string "actable_type", limit: 255 - t.integer "points_awarded" + t.datetime "awarded_at", precision: nil + t.integer "awarder_id" t.integer "course_user_id", null: false - t.string "reason", limit: 255 - t.integer "creator_id", null: false - t.integer "updater_id", null: false t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false + t.integer "creator_id", null: false t.integer "draft_points_awarded" - t.datetime "awarded_at", precision: nil - t.integer "awarder_id" + t.integer "points_awarded" + t.string "reason", limit: 255 + t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false t.index ["actable_type", "actable_id"], name: "index_course_experience_points_records_on_actable", unique: true t.index ["awarder_id"], name: "fk__course_experience_points_records_awarder_id" t.index ["course_user_id"], name: "fk__course_experience_points_records_course_user_id" @@ -882,14 +882,14 @@ end create_table "course_external_assessment_grades", force: :cascade do |t| - t.bigint "external_assessment_id", null: false t.bigint "course_user_id", null: false + t.datetime "created_at", null: false + t.bigint "creator_id", null: false + t.bigint "external_assessment_id", null: false t.decimal "grade", precision: 5, scale: 2 t.string "imported_identifier" - t.bigint "creator_id", null: false - t.bigint "updater_id", null: false - t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.bigint "updater_id", null: false t.index ["course_user_id"], name: "fk__course_external_assessment_grades_course_user_id" t.index ["creator_id"], name: "fk__course_external_assessment_grades_creator_id" t.index ["external_assessment_id", "course_user_id"], name: "index_course_external_assessment_grades_on_ea_id_and_cu_id", unique: true @@ -898,16 +898,16 @@ end create_table "course_external_assessments", force: :cascade do |t| - t.bigint "course_id", null: false - t.string "title", null: false - t.decimal "maximum_grade", precision: 5, scale: 2, null: false - t.boolean "floor_at_zero", default: true, null: false t.boolean "cap_at_maximum", default: true, null: false - t.bigint "creator_id", null: false - t.bigint "updater_id", null: false + t.bigint "course_id", null: false t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.bigint "creator_id", null: false + t.boolean "floor_at_zero", default: true, null: false + t.decimal "maximum_grade", precision: 5, scale: 2, null: false t.integer "position", null: false + t.string "title", null: false + t.datetime "updated_at", null: false + t.bigint "updater_id", null: false t.index ["course_id", "title"], name: "index_course_external_assessments_on_course_id_and_title", unique: true t.index ["course_id"], name: "fk__course_external_assessments_course_id" t.index ["creator_id"], name: "fk__course_external_assessments_creator_id" @@ -916,10 +916,10 @@ create_table "course_forum_discussion_references", force: :cascade do |t| t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false - t.bigint "forum_import_id", null: false - t.bigint "discussion_id", null: false t.bigint "creator_id", null: false + t.bigint "discussion_id", null: false + t.bigint "forum_import_id", null: false + t.datetime "updated_at", precision: nil, null: false t.bigint "updater_id", null: false t.index ["creator_id"], name: "fk__course_forum_discussion_references_creator_id" t.index ["discussion_id"], name: "fk__course_forum_discussion_references_discussion_id" @@ -928,20 +928,20 @@ end create_table "course_forum_discussions", force: :cascade do |t| - t.vector "embedding", limit: 1536, null: false t.jsonb "discussion", default: {}, null: false + t.vector "embedding", limit: 1536, null: false t.string "name", null: false t.index ["embedding"], name: "index_course_forum_discussions_on_embedding", opclass: :vector_cosine_ops, using: :hnsw t.index ["name"], name: "index_course_forum_discussions_on_name" end create_table "course_forum_imports", force: :cascade do |t| - t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false t.bigint "course_id", null: false + t.datetime "created_at", precision: nil, null: false t.bigint "imported_forum_id", null: false - t.string "workflow_state", limit: 255, default: "not_imported", null: false t.uuid "job_id" + t.datetime "updated_at", precision: nil, null: false + t.string "workflow_state", limit: 255, default: "not_imported", null: false t.index ["course_id"], name: "fk__course_forum_imports_course_id" t.index ["imported_forum_id"], name: "fk__course_forum_imports_imported_forum_id" t.index ["job_id"], name: "fk__course_forum_importings_job_id" @@ -949,24 +949,24 @@ create_table "course_forum_rag_auto_answerings", force: :cascade do |t| t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false - t.bigint "post_id", null: false t.uuid "job_id" + t.bigint "post_id", null: false + t.datetime "updated_at", precision: nil, null: false t.index ["job_id"], name: "fk__course_forum_rag_auto_answerings_job_id", unique: true t.index ["post_id"], name: "fk__course_forum_rag_auto_answerings_post_id", unique: true end create_table "course_forum_rag_wise_ratings", force: :cascade do |t| - t.bigint "post_id" - t.integer "rating" - t.text "original_content", null: false - t.text "edited_content" - t.float "faithfulness_score", default: 0.0, null: false t.float "answer_relevance_score", default: 0.0, null: false - t.bigint "creator_id", null: false - t.bigint "updater_id", null: false t.datetime "created_at", null: false + t.bigint "creator_id", null: false + t.text "edited_content" + t.float "faithfulness_score", default: 0.0, null: false + t.text "original_content", null: false + t.bigint "post_id" + t.integer "rating" t.datetime "updated_at", null: false + t.bigint "updater_id", null: false t.index ["creator_id"], name: "fk__cfrwr_creator_id" t.index ["post_id"], name: "index_cfrwr_on_post_id_unique_active", unique: true, where: "(post_id IS NOT NULL)" t.index ["updater_id"], name: "fk__cfrwr_updater_id" @@ -981,27 +981,27 @@ end create_table "course_forum_topic_views", id: :serial, force: :cascade do |t| - t.integer "topic_id", null: false - t.integer "user_id", null: false t.datetime "created_at", precision: nil, null: false + t.integer "topic_id", null: false t.datetime "updated_at", precision: nil, null: false + t.integer "user_id", null: false t.index ["topic_id"], name: "fk__course_forum_topic_views_topic_id" t.index ["user_id"], name: "fk__course_forum_topic_views_user_id" end create_table "course_forum_topics", id: :serial, force: :cascade do |t| + t.datetime "created_at", precision: nil, null: false + t.integer "creator_id", null: false t.integer "forum_id", null: false - t.string "title", limit: 255, null: false - t.string "slug", limit: 255 - t.boolean "locked", default: false t.boolean "hidden", default: false + t.datetime "latest_post_at", precision: nil, null: false + t.boolean "locked", default: false + t.boolean "resolved", default: false, null: false + t.string "slug", limit: 255 + t.string "title", limit: 255, null: false t.integer "topic_type", default: 0 - t.integer "creator_id", null: false - t.integer "updater_id", null: false - t.datetime "created_at", precision: nil, null: false t.datetime "updated_at", precision: nil, null: false - t.boolean "resolved", default: false, null: false - t.datetime "latest_post_at", precision: nil, null: false + t.integer "updater_id", null: false t.index ["creator_id"], name: "fk__course_forum_topics_creator_id" t.index ["forum_id", "slug"], name: "index_course_forum_topics_on_forum_id_and_slug", unique: true t.index ["forum_id"], name: "fk__course_forum_topics_forum_id" @@ -1010,14 +1010,14 @@ create_table "course_forums", id: :serial, force: :cascade do |t| t.integer "course_id", null: false + t.datetime "created_at", precision: nil, null: false + t.integer "creator_id", null: false + t.text "description" + t.boolean "forum_topics_auto_subscribe", default: true, null: false t.string "name", limit: 255, null: false t.string "slug", limit: 255 - t.text "description" - t.integer "creator_id", null: false - t.integer "updater_id", null: false - t.datetime "created_at", precision: nil, null: false t.datetime "updated_at", precision: nil, null: false - t.boolean "forum_topics_auto_subscribe", default: true, null: false + t.integer "updater_id", null: false t.index ["course_id", "slug"], name: "index_course_forums_on_course_id_and_slug", unique: true t.index ["course_id"], name: "fk__course_forums_course_id" t.index ["creator_id"], name: "fk__course_forums_creator_id" @@ -1026,12 +1026,12 @@ create_table "course_gradebook_assessment_contributions", force: :cascade do |t| t.bigint "assessment_id", null: false - t.decimal "weight", precision: 5, scale: 2 - t.boolean "excluded", default: false, null: false - t.bigint "creator_id", null: false - t.bigint "updater_id", null: false t.datetime "created_at", null: false + t.bigint "creator_id", null: false + t.boolean "excluded", default: false, null: false t.datetime "updated_at", null: false + t.bigint "updater_id", null: false + t.decimal "weight", precision: 5, scale: 2 t.index ["assessment_id"], name: "index_cgac_on_assessment_id", unique: true t.index ["creator_id"], name: "fk__cgac_creator_id" t.index ["updater_id"], name: "fk__cgac_updater_id" @@ -1039,12 +1039,12 @@ create_table "course_gradebook_external_contributions", force: :cascade do |t| t.bigint "course_id", null: false - t.bigint "external_assessment_id", null: false - t.decimal "weight", precision: 5, scale: 2, default: "0.0", null: false - t.bigint "creator_id", null: false - t.bigint "updater_id", null: false t.datetime "created_at", null: false + t.bigint "creator_id", null: false + t.bigint "external_assessment_id", null: false t.datetime "updated_at", null: false + t.bigint "updater_id", null: false + t.decimal "weight", precision: 5, scale: 2, default: "0.0", null: false t.index ["course_id"], name: "fk__cgec_course_id" t.index ["creator_id"], name: "fk__cgec_creator_id" t.index ["external_assessment_id"], name: "index_cgec_on_external_assessment_id", unique: true @@ -1052,17 +1052,17 @@ end create_table "course_gradebook_level_configs", force: :cascade do |t| + t.boolean "clamp", default: true, null: false t.bigint "course_id", null: false + t.datetime "created_at", null: false + t.bigint "creator_id", null: false t.boolean "enabled", default: false, null: false t.string "formula", default: "", null: false t.jsonb "formula_ast" - t.decimal "weight", precision: 5, scale: 2, default: "0.0", null: false t.boolean "show", default: false, null: false - t.boolean "clamp", default: true, null: false - t.bigint "creator_id", null: false - t.bigint "updater_id", null: false - t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.bigint "updater_id", null: false + t.decimal "weight", precision: 5, scale: 2, default: "0.0", null: false t.index ["course_id"], name: "index_course_gradebook_level_configs_on_course_id", unique: true t.index ["creator_id"], name: "fk__course_gradebook_level_configs_creator_id" t.index ["updater_id"], name: "fk__course_gradebook_level_configs_updater_id" @@ -1070,14 +1070,14 @@ create_table "course_gradebook_tab_contributions", force: :cascade do |t| t.bigint "course_id", null: false + t.datetime "created_at", null: false + t.bigint "creator_id", null: false + t.integer "keep_highest", default: 0, null: false t.bigint "tab_id", null: false + t.datetime "updated_at", null: false + t.bigint "updater_id", null: false t.decimal "weight", precision: 5, scale: 2, default: "0.0", null: false t.integer "weight_mode", default: 0, null: false - t.bigint "creator_id", null: false - t.bigint "updater_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "keep_highest", default: 0, null: false t.index ["course_id"], name: "fk__course_gradebook_tab_contributions_course_id" t.index ["creator_id"], name: "fk__course_gradebook_tab_contributions_creator_id" t.index ["tab_id"], name: "index_course_gradebook_tab_contributions_on_tab_id", unique: true @@ -1086,12 +1086,12 @@ create_table "course_group_categories", force: :cascade do |t| t.bigint "course_id", null: false - t.string "name", default: "", null: false - t.text "description" - t.bigint "creator_id", null: false - t.bigint "updater_id", null: false t.datetime "created_at", null: false + t.bigint "creator_id", null: false + t.text "description" + t.string "name", default: "", null: false t.datetime "updated_at", null: false + t.bigint "updater_id", null: false t.index ["course_id", "name"], name: "index_course_group_categories_on_course_id_and_name", unique: true t.index ["course_id"], name: "fk__course_group_categories_course_id" t.index ["creator_id"], name: "fk__course_group_categories_creator_id" @@ -1099,13 +1099,13 @@ end create_table "course_group_users", id: :serial, force: :cascade do |t| - t.integer "group_id", null: false t.integer "course_user_id", null: false - t.integer "role", null: false - t.integer "creator_id", null: false - t.integer "updater_id", null: false t.datetime "created_at", precision: nil, null: false + t.integer "creator_id", null: false + t.integer "group_id", null: false + t.integer "role", null: false t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false t.index ["course_user_id", "group_id"], name: "index_course_group_users_on_course_user_id_and_course_group_id", unique: true t.index ["course_user_id"], name: "fk__course_group_users_course_user_id" t.index ["creator_id"], name: "fk__course_group_users_creator_id" @@ -1114,13 +1114,13 @@ end create_table "course_groups", id: :serial, force: :cascade do |t| - t.string "name", limit: 255, null: false - t.integer "creator_id", null: false - t.integer "updater_id", null: false t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false + t.integer "creator_id", null: false t.text "description" t.bigint "group_category_id", null: false + t.string "name", limit: 255, null: false + t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false t.index ["creator_id"], name: "fk__course_groups_creator_id" t.index ["group_category_id", "name"], name: "index_course_groups_on_group_category_id_and_name", unique: true t.index ["group_category_id"], name: "fk__course_groups_group_category_id" @@ -1136,10 +1136,10 @@ create_table "course_learning_rate_records", force: :cascade do |t| t.bigint "course_user_id", null: false - t.float "learning_rate", null: false - t.float "effective_min", null: false - t.float "effective_max", null: false t.datetime "created_at", null: false + t.float "effective_max", null: false + t.float "effective_min", null: false + t.float "learning_rate", null: false t.datetime "updated_at", null: false t.index ["course_user_id"], name: "fk__course_learning_rate_records_course_user_id" end @@ -1152,29 +1152,29 @@ end create_table "course_lesson_plan_events", id: :serial, force: :cascade do |t| - t.string "location", limit: 255 t.string "event_type", limit: 255, null: false + t.string "location", limit: 255 end create_table "course_lesson_plan_items", id: :serial, force: :cascade do |t| t.integer "actable_id" t.string "actable_type", limit: 255 + t.boolean "affects_personal_times", default: false, null: false + t.integer "base_exp", null: false + t.float "closing_reminder_token" t.integer "course_id", null: false - t.string "title", limit: 255, null: false + t.datetime "created_at", precision: nil, null: false + t.integer "creator_id", null: false t.text "description" + t.boolean "has_personal_times", default: false, null: false + t.boolean "has_todo" + t.boolean "movable", default: false, null: false t.boolean "published", default: false, null: false - t.integer "base_exp", null: false t.integer "time_bonus_exp", null: false - t.integer "creator_id", null: false - t.integer "updater_id", null: false - t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false - t.float "closing_reminder_token" + t.string "title", limit: 255, null: false t.boolean "triggers_recomputation", default: false, null: false - t.boolean "movable", default: false, null: false - t.boolean "has_personal_times", default: false, null: false - t.boolean "affects_personal_times", default: false, null: false - t.boolean "has_todo" + t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false t.index ["actable_type", "actable_id"], name: "index_course_lesson_plan_items_on_actable_type_and_actable_id", unique: true t.index ["course_id"], name: "fk__course_lesson_plan_items_course_id" t.index ["creator_id"], name: "fk__course_lesson_plan_items_creator_id" @@ -1185,14 +1185,14 @@ end create_table "course_lesson_plan_todos", id: :serial, force: :cascade do |t| + t.datetime "created_at", precision: nil + t.integer "creator_id", null: false + t.boolean "ignore", default: false, null: false t.integer "item_id", null: false + t.datetime "updated_at", precision: nil + t.integer "updater_id", null: false t.integer "user_id", null: false t.string "workflow_state", limit: 255, null: false - t.boolean "ignore", default: false, null: false - t.integer "creator_id", null: false - t.integer "updater_id", null: false - t.datetime "created_at", precision: nil - t.datetime "updated_at", precision: nil t.index ["creator_id"], name: "fk__course_lesson_plan_todos_creator_id" t.index ["item_id", "user_id"], name: "index_course_lesson_plan_todos_on_item_id_and_user_id", unique: true t.index ["item_id"], name: "fk__course_lesson_plan_todos_item_id" @@ -1202,27 +1202,27 @@ create_table "course_levels", id: :serial, force: :cascade do |t| t.integer "course_id", null: false - t.integer "experience_points_threshold", null: false t.datetime "created_at", precision: nil, null: false + t.integer "experience_points_threshold", null: false t.datetime "updated_at", precision: nil, null: false t.index ["course_id", "experience_points_threshold"], name: "index_experience_points_threshold_on_course_id", unique: true t.index ["course_id"], name: "fk__course_levels_course_id" end create_table "course_material_folders", id: :serial, force: :cascade do |t| - t.integer "parent_id" + t.boolean "can_student_upload", default: false, null: false t.integer "course_id", null: false + t.datetime "created_at", precision: nil, null: false + t.integer "creator_id", null: false + t.text "description" + t.datetime "end_at", precision: nil + t.string "name", limit: 255, null: false t.integer "owner_id" t.string "owner_type", limit: 255 - t.string "name", limit: 255, null: false - t.text "description" - t.boolean "can_student_upload", default: false, null: false + t.integer "parent_id" t.datetime "start_at", precision: nil, null: false - t.datetime "end_at", precision: nil - t.integer "creator_id", null: false - t.integer "updater_id", null: false - t.datetime "created_at", precision: nil, null: false t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false t.index "parent_id, lower((name)::text)", name: "index_course_material_folders_on_parent_id_and_name", unique: true t.index ["course_id"], name: "fk__course_material_folders_course_id" t.index ["creator_id"], name: "fk__course_material_folders_creator_id" @@ -1234,10 +1234,10 @@ create_table "course_material_text_chunk_references", id: :uuid, default: -> { "uuid_generate_v4()" }, force: :cascade do |t| t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false + t.bigint "creator_id", null: false t.bigint "material_id", null: false t.bigint "text_chunk_id", null: false - t.bigint "creator_id", null: false + t.datetime "updated_at", precision: nil, null: false t.bigint "updater_id", null: false t.index ["creator_id"], name: "fk__course_material_text_chunk_references_creator_id" t.index ["material_id"], name: "fk__course_material_text_chunk_references_material_id" @@ -1247,9 +1247,9 @@ create_table "course_material_text_chunkings", id: :serial, force: :cascade do |t| t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.bigint "material_id", null: false t.uuid "job_id" + t.bigint "material_id", null: false + t.datetime "updated_at", null: false t.index ["job_id"], name: "fk__course_material_text_chunkings_job_id" t.index ["material_id"], name: "fk__course_material_text_chunkings_material_id", unique: true end @@ -1263,13 +1263,13 @@ end create_table "course_materials", id: :serial, force: :cascade do |t| + t.datetime "created_at", precision: nil, null: false + t.integer "creator_id", null: false + t.text "description" t.integer "folder_id", null: false t.string "name", limit: 255, null: false - t.text "description" - t.integer "creator_id", null: false - t.integer "updater_id", null: false - t.datetime "created_at", precision: nil, null: false t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false t.string "workflow_state", limit: 255, default: "not_chunked", null: false t.index "folder_id, lower((name)::text)", name: "index_course_materials_on_folder_id_and_name", unique: true t.index ["creator_id"], name: "fk__course_materials_creator_id" @@ -1279,39 +1279,39 @@ end create_table "course_monitoring_heartbeats", force: :cascade do |t| - t.bigint "session_id", null: false - t.string "user_agent", null: false - t.string "ip_address" + t.datetime "created_at", null: false t.datetime "generated_at", precision: nil, null: false + t.string "ip_address" + t.jsonb "seb_payload" + t.bigint "session_id", null: false t.boolean "stale", default: false, null: false - t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.jsonb "seb_payload" + t.string "user_agent", null: false t.index ["generated_at"], name: "index_course_monitoring_heartbeats_on_generated_at" t.index ["session_id"], name: "index_course_monitoring_heartbeats_on_session_id" end create_table "course_monitoring_monitors", force: :cascade do |t| - t.boolean "enabled", default: false, null: false - t.string "secret" - t.integer "min_interval_ms", null: false - t.integer "max_interval_ms", null: false - t.integer "offset_ms", default: 0, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false t.boolean "blocks", default: false, null: false t.boolean "browser_authorization", default: true, null: false t.integer "browser_authorization_method", default: 0, null: false + t.datetime "created_at", null: false + t.boolean "enabled", default: false, null: false + t.integer "max_interval_ms", null: false + t.integer "min_interval_ms", null: false + t.integer "offset_ms", default: 0, null: false t.string "seb_config_key" + t.string "secret" + t.datetime "updated_at", null: false end create_table "course_monitoring_sessions", force: :cascade do |t| + t.datetime "created_at", null: false + t.bigint "creator_id", null: false + t.integer "misses", default: 0, null: false t.bigint "monitor_id", null: false t.integer "status", default: 0, null: false - t.bigint "creator_id", null: false - t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.integer "misses", default: 0, null: false t.index ["creator_id"], name: "fk__course_monitoring_sessions_creator_id" t.index ["monitor_id"], name: "index_course_monitoring_sessions_on_monitor_id" end @@ -1319,27 +1319,27 @@ create_table "course_notifications", id: :serial, force: :cascade do |t| t.integer "activity_id", null: false t.integer "course_id", null: false - t.integer "notification_type", default: 0, null: false t.datetime "created_at", precision: nil, null: false + t.integer "notification_type", default: 0, null: false t.datetime "updated_at", precision: nil, null: false t.index ["activity_id"], name: "index_course_notifications_on_activity_id" t.index ["course_id"], name: "index_course_notifications_on_course_id" end create_table "course_personal_times", force: :cascade do |t| - t.bigint "course_user_id", null: false - t.bigint "lesson_plan_item_id", null: false - t.datetime "start_at", precision: nil, null: false t.datetime "bonus_end_at", precision: nil + t.bigint "course_user_id", null: false t.datetime "end_at", precision: nil t.boolean "fixed", default: false, null: false - t.index ["course_user_id"], name: "index_course_personal_times_on_course_user_id" + t.bigint "lesson_plan_item_id", null: false + t.datetime "start_at", precision: nil, null: false + t.index ["course_user_id", "lesson_plan_item_id"], name: "index_course_personal_times_on_user_and_item", unique: true t.index ["lesson_plan_item_id"], name: "index_course_personal_times_on_lesson_plan_item_id" end create_table "course_question_assessments", id: :serial, force: :cascade do |t| - t.integer "question_id", null: false t.integer "assessment_id", null: false + t.integer "question_id", null: false t.integer "weight", null: false t.index ["assessment_id"], name: "index_course_question_assessments_on_assessment_id" t.index ["question_id", "assessment_id"], name: "index_question_assessments_on_question_id_and_assessment_id", unique: true @@ -1348,21 +1348,21 @@ create_table "course_reference_timelines", force: :cascade do |t| t.bigint "course_id", null: false - t.boolean "default", default: false, null: false t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false + t.boolean "default", default: false, null: false t.string "title" + t.datetime "updated_at", precision: nil, null: false t.integer "weight" t.index ["course_id"], name: "index_course_reference_timelines_on_course_id" end create_table "course_reference_times", force: :cascade do |t| - t.bigint "reference_timeline_id", null: false - t.bigint "lesson_plan_item_id", null: false - t.datetime "start_at", precision: nil, null: false t.datetime "bonus_end_at", precision: nil - t.datetime "end_at", precision: nil t.datetime "created_at", precision: nil, null: false + t.datetime "end_at", precision: nil + t.bigint "lesson_plan_item_id", null: false + t.bigint "reference_timeline_id", null: false + t.datetime "start_at", precision: nil, null: false t.datetime "updated_at", precision: nil, null: false t.index ["lesson_plan_item_id"], name: "index_course_reference_times_on_lesson_plan_item_id" t.index ["reference_timeline_id"], name: "index_course_reference_times_on_reference_timeline_id" @@ -1370,14 +1370,14 @@ create_table "course_rubric_answer_evaluation_ratings", force: :cascade do |t| t.bigint "answer_evaluation_id", null: false + t.datetime "created_at", null: false + t.bigint "creator_id", null: false + t.text "edited_feedback" + t.text "original_feedback", null: false t.bigint "post_id" t.integer "rating" - t.text "original_feedback", null: false - t.text "edited_feedback" - t.bigint "creator_id", null: false - t.bigint "updater_id", null: false - t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.bigint "updater_id", null: false t.index ["answer_evaluation_id"], name: "fk__craer_answer_evaluation_id" t.index ["creator_id"], name: "fk__craer_creator_id" t.index ["post_id"], name: "index_craer_on_post_id_unique_active", unique: true, where: "(post_id IS NOT NULL)" @@ -1395,11 +1395,11 @@ create_table "course_rubric_answer_evaluations", force: :cascade do |t| t.bigint "answer_id", null: false - t.bigint "rubric_id" - t.uuid "job_id" - t.text "feedback" t.string "evaluation_type", default: "playground", null: false - t.index ["answer_id", "rubric_id"], name: "index_course_rubric_playground_evaluation_on_answer_rubric", unique: true, where: "((evaluation_type)::text = ANY ((ARRAY['playground'::character varying, 'playground_hidden'::character varying])::text[]))" + t.text "feedback" + t.uuid "job_id" + t.bigint "rubric_id" + t.index ["answer_id", "rubric_id"], name: "index_course_rubric_playground_evaluation_on_answer_rubric", unique: true, where: "((evaluation_type)::text = ANY (ARRAY[('playground'::character varying)::text, ('playground_hidden'::character varying)::text]))" t.index ["answer_id"], name: "index_course_rubric_answer_evaluations_on_answer_id" t.index ["answer_id"], name: "index_course_rubric_grading_evaluation_on_answer", unique: true, where: "((evaluation_type)::text = 'grading'::text)" t.index ["job_id"], name: "index_course_rubric_answer_evaluations_on_job_id", unique: true @@ -1407,72 +1407,72 @@ end create_table "course_rubric_categories", force: :cascade do |t| - t.bigint "rubric_id", null: false - t.text "name", null: false t.boolean "is_bonus_category", default: false, null: false + t.text "name", null: false + t.bigint "rubric_id", null: false t.integer "weight", default: 0, null: false t.index ["rubric_id"], name: "index_course_rubric_categories_on_rubric_id" end create_table "course_rubric_category_criterions", force: :cascade do |t| t.bigint "category_id", null: false - t.integer "grade", default: 0, null: false t.text "explanation", null: false + t.integer "grade", default: 0, null: false t.index ["category_id"], name: "index_course_rubric_category_criterions_on_category_id" end create_table "course_rubric_mock_answer_evaluation_selections", force: :cascade do |t| - t.bigint "mock_answer_evaluation_id", null: false t.bigint "category_id", null: false t.bigint "criterion_id" + t.bigint "mock_answer_evaluation_id", null: false t.index ["category_id"], name: "idx_on_category_id_e30923d044" t.index ["criterion_id"], name: "idx_on_criterion_id_aced8a6ee9" t.index ["mock_answer_evaluation_id"], name: "idx_on_mock_answer_evaluation_id_3aae8a490b" end create_table "course_rubric_mock_answer_evaluations", force: :cascade do |t| + t.text "feedback" + t.uuid "job_id" t.bigint "mock_answer_id", null: false t.bigint "rubric_id", null: false - t.uuid "job_id" - t.text "feedback" t.index ["job_id"], name: "index_course_rubric_mock_answer_evaluations_on_job_id", unique: true t.index ["mock_answer_id"], name: "index_course_rubric_mock_answer_evaluations_on_mock_answer_id" t.index ["rubric_id"], name: "index_course_rubric_mock_answer_evaluations_on_rubric_id" end create_table "course_rubrics", force: :cascade do |t| + t.string "content_hash", default: "", null: false t.bigint "course_id", null: false t.datetime "created_at", null: false t.text "grading_prompt", default: "", null: false t.text "model_answer", default: "", null: false - t.string "content_hash", default: "", null: false t.index ["course_id"], name: "index_course_rubrics_on_course_id" end create_table "course_scholaistic_assessments", force: :cascade do |t| - t.string "upstream_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "upstream_id", null: false end create_table "course_scholaistic_submissions", force: :cascade do |t| - t.string "upstream_id", null: false t.bigint "assessment_id", null: false - t.bigint "creator_id", null: false t.datetime "created_at", null: false + t.bigint "creator_id", null: false t.datetime "updated_at", null: false + t.string "upstream_id", null: false t.index ["assessment_id", "creator_id"], name: "idx_on_assessment_id_creator_id_ac62df4c1b", unique: true t.index ["assessment_id"], name: "index_course_scholaistic_submissions_on_assessment_id" t.index ["creator_id"], name: "fk__course_scholaistic_submissions_creator_id" end create_table "course_settings_emails", force: :cascade do |t| - t.bigint "course_id", null: false t.integer "component", null: false t.bigint "course_assessment_category_id" - t.integer "setting", null: false + t.bigint "course_id", null: false t.boolean "phantom", default: true, null: false t.boolean "regular", default: true, null: false + t.integer "setting", null: false t.index ["course_assessment_category_id"], name: "index_course_settings_emails_on_course_assessment_category_id" t.index ["course_id", "component", "course_assessment_category_id", "setting"], name: "index_course_settings_emails_composite", unique: true t.index ["course_id"], name: "index_course_settings_emails_on_course_id" @@ -1486,13 +1486,13 @@ end create_table "course_survey_answers", id: :serial, force: :cascade do |t| + t.datetime "created_at", precision: nil, null: false + t.integer "creator_id", null: false t.integer "question_id", null: false t.integer "response_id", null: false - t.integer "creator_id", null: false - t.integer "updater_id", null: false - t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false t.text "text_response" + t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false t.index ["creator_id"], name: "fk__course_survey_answers_creator_id" t.index ["question_id"], name: "fk__course_survey_answers_question_id" t.index ["response_id"], name: "fk__course_survey_answers_response_id" @@ -1500,37 +1500,37 @@ end create_table "course_survey_question_options", id: :serial, force: :cascade do |t| - t.integer "question_id", null: false t.text "option" + t.integer "question_id", null: false t.integer "weight", null: false t.index ["question_id"], name: "fk__course_survey_question_options_question_id" end create_table "course_survey_questions", id: :serial, force: :cascade do |t| - t.text "description", null: false - t.integer "creator_id", null: false - t.integer "updater_id", null: false t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false - t.boolean "required", default: false, null: false - t.integer "question_type", default: 0, null: false - t.integer "weight", null: false - t.integer "max_options" - t.integer "min_options" + t.integer "creator_id", null: false + t.text "description", null: false t.boolean "grid_view", default: false, null: false + t.integer "max_options" + t.integer "min_options" + t.integer "question_type", default: 0, null: false + t.boolean "required", default: false, null: false t.integer "section_id", null: false + t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false + t.integer "weight", null: false t.index ["creator_id"], name: "fk__course_survey_questions_creator_id" t.index ["section_id"], name: "index_course_survey_questions_on_section_id" t.index ["updater_id"], name: "fk__course_survey_questions_updater_id" end create_table "course_survey_responses", id: :serial, force: :cascade do |t| - t.integer "survey_id", null: false - t.datetime "submitted_at", precision: nil - t.integer "creator_id", null: false - t.integer "updater_id", null: false t.datetime "created_at", precision: nil, null: false + t.integer "creator_id", null: false + t.datetime "submitted_at", precision: nil + t.integer "survey_id", null: false t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false t.index ["creator_id"], name: "fk__course_survey_responses_creator_id" t.index ["survey_id", "creator_id"], name: "index_course_survey_responses_on_survey_id_and_creator_id", unique: true t.index ["survey_id"], name: "fk__course_survey_responses_survey_id" @@ -1538,32 +1538,32 @@ end create_table "course_survey_sections", id: :serial, force: :cascade do |t| + t.text "description" t.integer "survey_id", null: false t.string "title", limit: 255, null: false - t.text "description" t.integer "weight", null: false t.index ["survey_id"], name: "fk__course_survey_sections_survey_id" end create_table "course_surveys", id: :serial, force: :cascade do |t| - t.integer "creator_id", null: false - t.integer "updater_id", null: false - t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false - t.boolean "anonymous", default: false, null: false t.boolean "allow_modify_after_submit", default: false, null: false - t.datetime "closing_reminded_at", precision: nil t.boolean "allow_response_after_end", default: false, null: false + t.boolean "anonymous", default: false, null: false + t.datetime "closing_reminded_at", precision: nil + t.datetime "created_at", precision: nil, null: false + t.integer "creator_id", null: false t.integer "satisfiability_type", default: 0 + t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false t.index ["creator_id"], name: "fk__course_surveys_creator_id" t.index ["updater_id"], name: "fk__course_surveys_updater_id" end create_table "course_user_achievements", id: :serial, force: :cascade do |t| - t.integer "course_user_id" t.integer "achievement_id" - t.datetime "obtained_at", precision: nil, null: false + t.integer "course_user_id" t.datetime "created_at", precision: nil, null: false + t.datetime "obtained_at", precision: nil, null: false t.datetime "updated_at", precision: nil, null: false t.index ["achievement_id"], name: "fk__course_user_achievements_achievement_id" t.index ["course_user_id", "achievement_id"], name: "index_user_achievements_on_course_user_id_and_achievement_id", unique: true @@ -1571,30 +1571,30 @@ end create_table "course_user_email_unsubscriptions", force: :cascade do |t| - t.bigint "course_user_id", null: false t.bigint "course_settings_email_id", null: false + t.bigint "course_user_id", null: false t.index ["course_settings_email_id"], name: "index_email_unsubscriptions_on_course_settings_email_id" t.index ["course_user_id", "course_settings_email_id"], name: "index_course_user_email_unsubscriptions_composite", unique: true t.index ["course_user_id"], name: "index_email_unsubscriptions_on_course_user_id" end create_table "course_user_invitations", id: :serial, force: :cascade do |t| - t.string "invitation_key", limit: 32, null: false - t.integer "creator_id", null: false - t.integer "updater_id", null: false - t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false - t.datetime "sent_at", precision: nil - t.integer "course_id", null: false - t.string "name", limit: 255, null: false - t.string "email", limit: 255, null: false t.datetime "confirmed_at", precision: nil t.integer "confirmer_id" - t.integer "role", default: 0, null: false + t.integer "course_id", null: false + t.datetime "created_at", precision: nil, null: false + t.integer "creator_id", null: false + t.string "email", limit: 255, null: false + t.string "external_id" + t.string "invitation_key", limit: 32, null: false + t.boolean "is_retryable", default: true, null: false + t.string "name", limit: 255, null: false t.boolean "phantom", default: false, null: false + t.integer "role", default: 0, null: false + t.datetime "sent_at", precision: nil t.integer "timeline_algorithm" - t.boolean "is_retryable", default: true, null: false - t.string "external_id" + t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false t.index "lower((email)::text)", name: "index_course_user_invitations_on_email" t.index ["confirmer_id"], name: "fk__course_user_invitations_confirmer_id" t.index ["course_id", "email"], name: "index_course_user_invitations_on_course_id_and_email", unique: true @@ -1607,20 +1607,20 @@ create_table "course_users", id: :serial, force: :cascade do |t| t.integer "course_id", null: false - t.integer "user_id", null: false - t.integer "role", default: 0, null: false - t.string "name", limit: 255, null: false - t.boolean "phantom", default: false, null: false - t.datetime "last_active_at", precision: nil t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false t.integer "creator_id", null: false - t.integer "updater_id", null: false - t.bigint "reference_timeline_id" - t.integer "timeline_algorithm", default: 0, null: false t.datetime "deleted_at" - t.boolean "is_suspended", default: false, null: false t.string "external_id" + t.boolean "is_suspended", default: false, null: false + t.datetime "last_active_at", precision: nil + t.string "name", limit: 255, null: false + t.boolean "phantom", default: false, null: false + t.bigint "reference_timeline_id" + t.integer "role", default: 0, null: false + t.integer "timeline_algorithm", default: 0, null: false + t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false + t.integer "user_id", null: false t.index ["course_id", "external_id"], name: "index_course_users_on_course_id_and_external_id", unique: true, where: "(external_id IS NOT NULL)" t.index ["course_id", "user_id"], name: "index_course_users_on_course_id_and_user_id", unique: true t.index ["course_id"], name: "fk__course_users_course_id" @@ -1631,54 +1631,54 @@ end create_table "course_video_events", force: :cascade do |t| - t.integer "session_id", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "event_time", precision: nil, null: false t.integer "event_type", null: false + t.float "playback_rate" t.integer "sequence_num", null: false - t.integer "video_time", null: false - t.datetime "event_time", precision: nil, null: false - t.datetime "created_at", precision: nil, null: false + t.integer "session_id", null: false t.datetime "updated_at", precision: nil, null: false - t.float "playback_rate" + t.integer "video_time", null: false t.index ["session_id", "sequence_num"], name: "index_course_video_events_on_session_id_and_sequence_num", unique: true t.index ["session_id"], name: "index_course_video_events_on_session_id" end create_table "course_video_sessions", force: :cascade do |t| - t.integer "submission_id", null: false - t.datetime "session_start", precision: nil, null: false - t.datetime "session_end", precision: nil, null: false t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false t.integer "creator_id" - t.integer "updater_id" t.integer "last_video_time" + t.datetime "session_end", precision: nil, null: false + t.datetime "session_start", precision: nil, null: false + t.integer "submission_id", null: false + t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id" t.index ["creator_id"], name: "index_course_video_sessions_on_creator_id" t.index ["submission_id"], name: "index_course_video_sessions_on_submission_id" t.index ["updater_id"], name: "index_course_video_sessions_on_updater_id" end create_table "course_video_statistics", force: :cascade do |t| + t.boolean "cached", default: false, null: false + t.integer "percent_watched", default: 0, null: false t.integer "video_id", null: false t.integer "watch_freq", default: [], array: true - t.integer "percent_watched", default: 0, null: false - t.boolean "cached", default: false, null: false t.index ["video_id"], name: "index_course_video_statistics_on_video_id" end create_table "course_video_submission_statistics", force: :cascade do |t| + t.boolean "cached", default: false, null: false + t.integer "percent_watched", default: 0, null: false t.integer "submission_id", null: false t.integer "watch_freq", default: [], array: true - t.integer "percent_watched", default: 0, null: false - t.boolean "cached", default: false, null: false t.index ["submission_id"], name: "index_course_video_submission_statistics_on_submission_id" end create_table "course_video_submissions", id: :serial, force: :cascade do |t| - t.integer "video_id", null: false - t.integer "creator_id", null: false - t.integer "updater_id", null: false t.datetime "created_at", precision: nil, null: false + t.integer "creator_id", null: false t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false + t.integer "video_id", null: false t.index ["creator_id"], name: "fk__course_video_submissions_creator_id" t.index ["updater_id"], name: "fk__course_video_submissions_updater_id" t.index ["video_id", "creator_id"], name: "index_course_video_submissions_on_video_id_and_creator_id", unique: true @@ -1687,68 +1687,68 @@ create_table "course_video_tabs", force: :cascade do |t| t.integer "course_id", null: false - t.string "title", limit: 255, null: false - t.integer "weight", null: false t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false t.integer "creator_id", null: false + t.string "title", limit: 255, null: false + t.datetime "updated_at", precision: nil, null: false t.integer "updater_id", null: false + t.integer "weight", null: false t.index ["course_id"], name: "index_course_video_tabs_on_course_id" t.index ["creator_id"], name: "index_course_video_tabs_on_creator_id" t.index ["updater_id"], name: "index_course_video_tabs_on_updater_id" end create_table "course_video_topics", id: :serial, force: :cascade do |t| - t.integer "video_id", null: false - t.integer "timestamp", null: false t.integer "creator_id", null: false + t.integer "timestamp", null: false t.integer "updater_id", null: false + t.integer "video_id", null: false t.index ["creator_id"], name: "index_course_video_topics_on_creator_id" t.index ["updater_id"], name: "index_course_video_topics_on_updater_id" t.index ["video_id"], name: "fk__course_video_topics_video_id" end create_table "course_videos", id: :serial, force: :cascade do |t| - t.string "url", limit: 255, null: false - t.integer "creator_id", null: false - t.integer "updater_id", null: false t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false - t.integer "tab_id", null: false + t.integer "creator_id", null: false t.integer "duration", default: 0, null: false t.integer "satisfiability_type", default: 0 + t.integer "tab_id", null: false + t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false + t.string "url", limit: 255, null: false t.index ["creator_id"], name: "fk__course_videos_creator_id" t.index ["tab_id"], name: "index_course_videos_on_tab_id" t.index ["updater_id"], name: "fk__course_videos_updater_id" end create_table "courses", id: :serial, force: :cascade do |t| - t.integer "instance_id", null: false - t.string "title", limit: 255, null: false + t.datetime "conditional_satisfiability_evaluation_time", precision: nil, default: "2021-11-09 00:08:09" + t.text "course_suspension_message" + t.datetime "created_at", precision: nil, null: false + t.integer "creator_id", null: false + t.integer "default_timeline_algorithm", default: 0, null: false t.text "description" - t.text "logo" - t.string "registration_key", limit: 16 - t.text "settings" - t.datetime "start_at", precision: nil, null: false t.datetime "end_at", precision: nil, null: false - t.integer "creator_id", null: false - t.integer "updater_id", null: false - t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false + t.boolean "enrol_auto_approve", default: false, null: false + t.boolean "enrollable", default: false, null: false t.boolean "gamified", default: true, null: false + t.integer "instance_id", null: false + t.boolean "is_suspended", default: false, null: false + t.string "koditsu_workspace_id" + t.text "logo" + t.boolean "preview", default: false, null: false t.boolean "published", default: false, null: false - t.boolean "enrollable", default: false, null: false - t.string "time_zone", limit: 255 + t.string "registration_key", limit: 16 + t.text "settings" t.boolean "show_personalized_timeline_features", default: false, null: false - t.datetime "conditional_satisfiability_evaluation_time", precision: nil, default: "2021-11-09 00:08:09" - t.integer "default_timeline_algorithm", default: 0, null: false - t.string "koditsu_workspace_id" t.uuid "ssid_folder_id" - t.boolean "enrol_auto_approve", default: false, null: false + t.datetime "start_at", precision: nil, null: false + t.string "time_zone", limit: 255 + t.string "title", limit: 255, null: false + t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false t.text "user_suspension_message" - t.boolean "is_suspended", default: false, null: false - t.text "course_suspension_message" - t.boolean "preview", default: false, null: false t.index ["creator_id"], name: "fk__courses_creator_id" t.index ["instance_id"], name: "fk__courses_instance_id" t.index ["instance_id"], name: "index_courses_on_instance_id_one_preview", unique: true, where: "preview" @@ -1768,48 +1768,48 @@ end create_table "duplication_traceables", force: :cascade do |t| - t.string "actable_type" t.bigint "actable_id" - t.integer "source_id" - t.bigint "creator_id", null: false - t.bigint "updater_id", null: false + t.string "actable_type" t.datetime "created_at", null: false + t.bigint "creator_id", null: false + t.integer "source_id" t.datetime "updated_at", null: false + t.bigint "updater_id", null: false t.index ["actable_type", "actable_id"], name: "index_duplication_traceables_actable", unique: true t.index ["creator_id"], name: "fk__duplication_traceables_creator_id" t.index ["updater_id"], name: "fk__duplication_traceables_updater_id" end create_table "generic_announcements", id: :serial, force: :cascade do |t| - t.string "type", limit: 255, null: false - t.integer "instance_id" - t.string "title", limit: 255, null: false t.text "content" - t.datetime "start_at", precision: nil, null: false - t.datetime "end_at", precision: nil, null: false - t.integer "creator_id", null: false - t.integer "updater_id", null: false t.datetime "created_at", precision: nil, null: false + t.integer "creator_id", null: false + t.datetime "end_at", precision: nil, null: false + t.integer "instance_id" + t.datetime "start_at", precision: nil, null: false + t.string "title", limit: 255, null: false + t.string "type", limit: 255, null: false t.datetime "updated_at", precision: nil, null: false + t.integer "updater_id", null: false t.index ["creator_id"], name: "fk__generic_announcements_creator_id" t.index ["instance_id"], name: "fk__generic_announcements_instance_id" t.index ["updater_id"], name: "fk__generic_announcements_updater_id" end create_table "instance_user_invitations", force: :cascade do |t| + t.datetime "confirmed_at", precision: nil + t.integer "confirmer_id" + t.datetime "created_at", precision: nil, null: false + t.integer "creator_id", null: false + t.string "email", limit: 255, null: false t.integer "instance_id", null: false + t.string "invitation_key", limit: 32, null: false + t.boolean "is_retryable", default: true, null: false t.string "name", limit: 255, null: false - t.string "email", limit: 255, null: false t.integer "role", default: 0, null: false - t.string "invitation_key", limit: 32, null: false t.datetime "sent_at", precision: nil - t.datetime "confirmed_at", precision: nil - t.integer "confirmer_id" - t.integer "creator_id", null: false - t.integer "updater_id", null: false - t.datetime "created_at", precision: nil, null: false t.datetime "updated_at", precision: nil, null: false - t.boolean "is_retryable", default: true, null: false + t.integer "updater_id", null: false t.index "lower((email)::text)", name: "index_instance_user_invitations_on_lower_email_text" t.index ["instance_id", "email"], name: "index_instance_user_invitations_on_instance_id_and_email", unique: true t.index ["instance_id"], name: "index_instance_user_invitations_on_instance_id" @@ -1817,20 +1817,20 @@ end create_table "instance_user_role_requests", id: :serial, force: :cascade do |t| + t.datetime "confirmed_at", precision: nil + t.bigint "confirmer_id" + t.datetime "created_at", precision: nil, null: false + t.bigint "creator_id", null: false + t.string "designation", limit: 255 t.integer "instance_id", null: false - t.integer "user_id", null: false - t.integer "role", null: false t.string "organization", limit: 255 - t.string "designation", limit: 255 t.text "reason" - t.datetime "created_at", precision: nil, null: false + t.text "rejection_message" + t.integer "role", null: false t.datetime "updated_at", precision: nil, null: false - t.bigint "creator_id", null: false t.bigint "updater_id", null: false + t.integer "user_id", null: false t.string "workflow_state", null: false - t.datetime "confirmed_at", precision: nil - t.bigint "confirmer_id" - t.text "rejection_message" t.index ["confirmer_id"], name: "index_instance_user_role_requests_on_confirmer_id" t.index ["creator_id"], name: "index_instance_user_role_requests_on_creator_id" t.index ["instance_id"], name: "fk__instance_user_role_requests_instance_id" @@ -1839,39 +1839,39 @@ end create_table "instance_users", id: :serial, force: :cascade do |t| + t.datetime "created_at", precision: nil, null: false t.integer "instance_id", null: false - t.integer "user_id", null: false + t.datetime "last_active_at", precision: nil t.integer "role", default: 0, null: false - t.datetime "created_at", precision: nil, null: false t.datetime "updated_at", precision: nil, null: false - t.datetime "last_active_at", precision: nil + t.integer "user_id", null: false t.index ["instance_id", "user_id"], name: "index_instance_users_on_instance_id_and_user_id", unique: true t.index ["instance_id"], name: "fk__instance_users_instance_id" end create_table "instances", id: :serial, force: :cascade do |t| - t.string "name", limit: 255, null: false t.string "host", limit: 255, null: false + t.string "name", limit: 255, null: false t.text "settings" t.index "lower((host)::text)", name: "index_instances_on_host", unique: true end create_table "jobs", id: :uuid, default: nil, force: :cascade do |t| - t.integer "status", default: 0, null: false - t.text "redirect_to" - t.json "error" t.datetime "created_at", precision: nil + t.json "error" + t.text "redirect_to" + t.integer "status", default: 0, null: false t.datetime "updated_at", precision: nil end create_table "live_feedback_files", force: :cascade do |t| - t.string "filename", null: false t.text "content", null: false + t.string "filename", null: false end create_table "live_feedback_message_files", force: :cascade do |t| - t.bigint "message_id", null: false t.bigint "file_id", null: false + t.bigint "message_id", null: false t.index ["file_id"], name: "index_live_feedback_message_files_on_file_id" t.index ["message_id"], name: "index_live_feedback_message_files_on_message_id" end @@ -1884,56 +1884,56 @@ end create_table "live_feedback_messages", force: :cascade do |t| - t.bigint "thread_id", null: false - t.bigint "option_id" - t.bigint "creator_id" - t.boolean "is_error", default: false, null: false t.string "content", null: false t.datetime "created_at", null: false + t.bigint "creator_id" + t.boolean "is_error", default: false, null: false + t.bigint "option_id" + t.bigint "thread_id", null: false t.index ["creator_id"], name: "index_live_feedback_messages_on_creator_id" t.index ["option_id"], name: "index_live_feedback_messages_on_option_id" t.index ["thread_id"], name: "index_live_feedback_messages_on_thread_id" end create_table "live_feedback_options", force: :cascade do |t| - t.integer "option_type", null: false t.boolean "is_enabled", default: false, null: false + t.integer "option_type", null: false end create_table "live_feedback_threads", force: :cascade do |t| - t.bigint "submission_question_id", null: false - t.bigint "submission_creator_id", null: false t.string "codaveri_thread_id", null: false - t.boolean "is_active", default: true, null: false t.datetime "created_at", null: false + t.boolean "is_active", default: true, null: false + t.bigint "submission_creator_id", null: false + t.bigint "submission_question_id", null: false t.index ["submission_creator_id"], name: "index_live_feedback_threads_on_submission_creator_id" t.index ["submission_question_id"], name: "index_live_feedback_threads_on_submission_question_id" end create_table "oauth_access_grants", force: :cascade do |t| - t.bigint "resource_owner_id", null: false t.bigint "application_id", null: false - t.string "token", null: false + t.datetime "created_at", precision: nil, null: false t.integer "expires_in", null: false t.text "redirect_uri", null: false - t.string "scopes", default: "", null: false - t.datetime "created_at", precision: nil, null: false + t.bigint "resource_owner_id", null: false t.datetime "revoked_at", precision: nil + t.string "scopes", default: "", null: false + t.string "token", null: false t.index ["application_id"], name: "index_oauth_access_grants_on_application_id" t.index ["resource_owner_id"], name: "index_oauth_access_grants_on_resource_owner_id" t.index ["token"], name: "index_oauth_access_grants_on_token", unique: true end create_table "oauth_access_tokens", force: :cascade do |t| - t.bigint "resource_owner_id" t.bigint "application_id", null: false - t.string "token", null: false - t.string "refresh_token" - t.integer "expires_in" - t.string "scopes" t.datetime "created_at", precision: nil, null: false - t.datetime "revoked_at", precision: nil + t.integer "expires_in" t.string "previous_refresh_token", default: "", null: false + t.string "refresh_token" + t.bigint "resource_owner_id" + t.datetime "revoked_at", precision: nil + t.string "scopes" + t.string "token", null: false t.index ["application_id"], name: "index_oauth_access_tokens_on_application_id" t.index ["refresh_token"], name: "index_oauth_access_tokens_on_refresh_token", unique: true t.index ["resource_owner_id"], name: "index_oauth_access_tokens_on_resource_owner_id" @@ -1941,27 +1941,27 @@ end create_table "oauth_applications", force: :cascade do |t| + t.boolean "confidential", default: true, null: false + t.datetime "created_at", null: false t.string "name", null: false - t.string "uid", null: false - t.string "secret", null: false t.text "redirect_uri", null: false t.string "scopes", default: "", null: false - t.boolean "confidential", default: true, null: false - t.datetime "created_at", null: false + t.string "secret", null: false + t.string "uid", null: false t.datetime "updated_at", null: false t.index ["uid"], name: "index_oauth_applications_on_uid", unique: true end create_table "polyglot_languages", id: :serial, force: :cascade do |t| - t.string "type", limit: 255, null: false + t.boolean "codaveri_evaluator_whitelisted", default: false, null: false + t.boolean "default_evaluator_whitelisted", default: true, null: false + t.boolean "enabled", default: true, null: false + t.boolean "koditsu_whitelisted", default: false, null: false t.string "name", limit: 255, null: false t.integer "parent_id" - t.serial "weight", null: false - t.boolean "enabled", default: true, null: false - t.boolean "default_evaluator_whitelisted", default: true, null: false - t.boolean "codaveri_evaluator_whitelisted", default: false, null: false t.boolean "question_generation_whitelisted", default: false, null: false - t.boolean "koditsu_whitelisted", default: false, null: false + t.string "type", limit: 255, null: false + t.serial "weight" t.index "lower((name)::text)", name: "index_polyglot_languages_on_name", unique: true t.index ["parent_id"], name: "fk__polyglot_languages_parent_id" end @@ -1970,63 +1970,63 @@ t.integer "readable_id" t.string "readable_type", limit: 255, null: false t.integer "reader_id", null: false - t.datetime "timestamp", precision: nil t.string "reader_type", limit: 255 + t.datetime "timestamp", precision: nil t.index ["reader_id", "reader_type", "readable_type", "readable_id"], name: "read_marks_reader_readable_index", unique: true t.index ["reader_id"], name: "fk__read_marks_user_id" end create_table "user_emails", id: :serial, force: :cascade do |t| - t.boolean "primary", default: false, null: false - t.integer "user_id" - t.string "email", limit: 255, null: false + t.datetime "confirmation_sent_at", precision: nil t.string "confirmation_token", limit: 255 t.datetime "confirmed_at", precision: nil - t.datetime "confirmation_sent_at", precision: nil + t.string "email", limit: 255, null: false + t.boolean "primary", default: false, null: false t.string "unconfirmed_email", limit: 255 + t.integer "user_id" t.index "lower((email)::text)", name: "index_user_emails_on_email", unique: true t.index ["confirmation_token"], name: "index_user_emails_on_confirmation_token", unique: true t.index ["user_id", "primary"], name: "index_user_emails_on_user_id_and_primary", unique: true, where: "(\"primary\" <> false)" end create_table "user_identities", id: :serial, force: :cascade do |t| - t.integer "user_id", null: false + t.datetime "created_at", precision: nil, null: false t.string "provider", limit: 255, null: false t.string "uid", limit: 255, null: false - t.datetime "created_at", precision: nil, null: false t.datetime "updated_at", precision: nil, null: false + t.integer "user_id", null: false t.index ["provider", "uid"], name: "index_user_identities_on_provider_and_uid", unique: true t.index ["user_id"], name: "fk__user_identities_user_id" end create_table "user_notifications", id: :serial, force: :cascade do |t| t.integer "activity_id", null: false - t.integer "user_id", null: false - t.integer "notification_type", default: 0, null: false t.datetime "created_at", precision: nil, null: false + t.integer "notification_type", default: 0, null: false t.datetime "updated_at", precision: nil, null: false + t.integer "user_id", null: false t.index ["activity_id"], name: "index_user_notifications_on_activity_id" t.index ["user_id"], name: "index_user_notifications_on_user_id" end create_table "users", id: :serial, force: :cascade do |t| - t.string "name", limit: 255, null: false - t.integer "role", default: 0, null: false - t.string "time_zone", limit: 255 - t.text "profile_photo" - t.string "encrypted_password", limit: 255, default: "", null: false - t.string "reset_password_token", limit: 255 - t.datetime "reset_password_sent_at", precision: nil - t.datetime "remember_created_at", precision: nil - t.integer "sign_in_count", default: 0, null: false + t.datetime "created_at", precision: nil, null: false t.datetime "current_sign_in_at", precision: nil - t.datetime "last_sign_in_at", precision: nil t.inet "current_sign_in_ip" + t.string "encrypted_password", limit: 255, default: "", null: false + t.datetime "last_sign_in_at", precision: nil t.inet "last_sign_in_ip" - t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false t.string "locale", default: "en", null: false + t.string "name", limit: 255, null: false + t.text "profile_photo" + t.datetime "remember_created_at", precision: nil + t.datetime "reset_password_sent_at", precision: nil + t.string "reset_password_token", limit: 255 + t.integer "role", default: 0, null: false t.string "session_id" + t.integer "sign_in_count", default: 0, null: false + t.string "time_zone", limit: 255 + t.datetime "updated_at", precision: nil, null: false t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true end From 21a3fa72aa13cae88913acacbf59c8f5a3e0b77b Mon Sep 17 00:00:00 2001 From: adi-herwana-nus Date: Fri, 28 Aug 2026 17:20:11 +0800 Subject: [PATCH 2/2] style(rubocop): adjust metrics limits, remove redundant cop disable directives - completely disable Style/OneClassPerFile - disable Lint/EmptyBlock in spec directory --- .rubocop.yml | 33 +- .rubocop_todo.yml | 290 +----------------- .../application_user_time_zone_concern.rb | 2 +- .../answer/update_answer_concern.rb | 2 +- .../question/koditsu_question_concern.rb | 2 - .../submission/monitoring_concern.rb | 2 +- .../lesson_plan/learning_rate_concern.rb | 4 +- .../base_personalization_strategy.rb | 2 +- .../fomo_personalization_strategy.rb | 2 +- .../otot_personalization_strategy.rb | 2 +- .../stragglers_personalization_strategy.rb | 2 +- .../concerns/course/unread_counts_concern.rb | 2 +- .../admin/component_settings_controller.rb | 2 +- .../forum_post_responses_controller.rb | 2 +- .../rubric_based_responses_controller.rb | 2 +- .../question/scribing_controller.rb | 2 +- .../course/assessment/rubrics_controller.rb | 2 +- .../submission/submissions_controller.rb | 4 +- app/controllers/course/courses_controller.rb | 4 +- .../course/gradebook_controller.rb | 2 +- .../course/learning_map_controller.rb | 4 +- .../course/statistics/aggregate_controller.rb | 2 +- .../statistics/assessments_controller.rb | 2 +- .../admin/instance/courses_controller.rb | 2 +- .../application_html_formatters_helper.rb | 2 - .../course/discussion/topics_helper.rb | 2 +- .../course/course_user_type_concern.rb | 2 - app/models/course/assessment.rb | 2 +- app/models/course/assessment/answer.rb | 2 +- app/models/course/assessment/question.rb | 2 +- .../course/assessment/question/programming.rb | 2 +- app/models/course/gradebook/level_config.rb | 2 +- app/models/course/learning_rate_record.rb | 2 +- app/models/course/rubric.rb | 2 +- app/models/course/story.rb | 2 +- ...ramming_codaveri_async_feedback_service.rb | 4 +- ...ogramming_codaveri_auto_grading_service.rb | 2 +- .../marketplace/apply_version_service.rb | 2 - ...programming_codaveri_evaluation_service.rb | 4 +- .../codaveri_problem_generation_service.rb | 4 +- .../c_sharp/c_sharp_package_service.rb | 2 +- .../programming/cpp/cpp_package_service.rb | 2 +- .../programming/go/go_package_service.rb | 2 +- .../programming/java/java_package_service.rb | 2 +- .../java_script_package_service.rb | 2 +- .../programming/language_package_service.rb | 4 +- .../programming_package_service.rb | 2 +- .../python/python_package_service.rb | 2 +- .../programming/r/r_package_service.rb | 2 +- .../programming/rust/rust_package_service.rb | 2 +- .../type_script_package_service.rb | 2 +- .../c_sharp/c_sharp_package_service.rb | 4 +- .../go/go_package_service.rb | 4 +- .../java_script_package_service.rb | 4 +- .../r/r_package_service.rb | 4 +- .../rust/rust_package_service.rb | 4 +- .../type_script_package_service.rb | 4 +- .../submission/csv_download_service.rb | 2 +- .../submission/ssid_plagiarism_service.rb | 2 +- .../assessment/submission/update_service.rb | 2 +- .../course/survey/reminder_service.rb | 2 - app/services/course/video/reminder_service.rb | 2 - .../programming_test_case_report_builder.rb | 2 - lib/autoload/duplicator.rb | 2 +- .../attachable/active_record/base.rb | 4 +- .../materials/active_record/base.rb | 2 +- lib/tasks/db/add_missing_email_settings.rake | 2 +- .../assessment_marketplace_component_spec.rb | 2 +- .../course/forum/forums_controller_spec.rb | 2 +- ...rse_assessment_question_voice_responses.rb | 2 - spec/support/devise.rb | 2 +- spec/support/reference_timelines_helper.rb | 2 - .../stubs/codaveri/evaluate_api_stubs.rb | 2 - spec/support/stubs/langchain/llm_stubs.rb | 2 +- spec/support/stubs/ssid/api_stubs.rb | 2 +- 75 files changed, 116 insertions(+), 383 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index ed6b7fccf9..f3915b387a 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -35,15 +35,41 @@ Lint/AmbiguousBlockAssociation: Lint/ConstantDefinitionInBlock: Enabled: false +Lint/EmptyBlock: + Exclude: + - 'spec/**/*' + +# The Metrics limits below are deliberately more permissive than RuboCop's defaults. +# They were calibrated against the existing code base so that the cops flag genuine outliers. Metrics/AbcSize: - Max: 20 + Max: 35 + # Rails code reads the same attribute repeatedly (`current_course`, `submission.assessment`); + # counting each read separately inflates the score without indicating real complexity. + CountRepeatedAttributes: false Metrics/BlockLength: Enabled: false -Metrics/MethodLength: +Metrics/ClassLength: + Max: 200 + CountAsOne: ['array', 'hash', 'heredoc'] + CountComments: false + +Metrics/CyclomaticComplexity: Max: 15 + +Metrics/MethodLength: + Max: 30 CountAsOne: ['array', 'hash', 'heredoc'] + CountComments: false + +Metrics/ModuleLength: + Max: 200 + CountAsOne: ['array', 'hash', 'heredoc'] + CountComments: false + +Metrics/PerceivedComplexity: + Max: 15 Style/Alias: EnforcedStyle: prefer_alias_method @@ -78,6 +104,9 @@ Style/LambdaCall: Style/NumericPredicate: EnforcedStyle: comparison +Style/OneClassPerFile: + Enabled: false + Style/ParallelAssignment: Enabled: false diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 2b159e8c96..e0ae1382d5 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -14,28 +14,6 @@ Lint/DuplicateBranch: - 'app/models/course/settings/lesson_plan_items.rb' - 'spec/support/i18n.rb' -# Offense count: 19 -# Configuration parameters: AllowComments, AllowEmptyLambdas. -Lint/EmptyBlock: - Exclude: - - 'spec/components/course/controller_component_host_spec.rb' - - 'spec/controllers/course/assessment/assessments_component_spec.rb' - - 'spec/controllers/course/assessment/condition/achievements_controller_spec.rb' - - 'spec/controllers/course/assessment/condition/assessments_controller_spec.rb' - - 'spec/controllers/course/assessment/condition/levels_controller_spec.rb' - - 'spec/controllers/course/assessment/condition/surveys_controller_spec.rb' - - 'spec/controllers/course/conditions_controller_spec.rb' - - 'spec/controllers/user_login_spec.rb' - - 'spec/factories/course_assessment_question_scribings.rb' - - 'spec/factories/course_condition_assessments.rb' - - 'spec/factories/course_survey_questions.rb' - - 'spec/factories/system_announcements.rb' - - 'spec/helpers/course/assessment/answer/programming_test_case_helper.rb' - - 'spec/helpers/course/assessment/submissions_helper_spec.rb' - - 'spec/jobs/application_job_spec.rb' - - 'spec/libraries/has_many_inverse_through_spec.rb' - - 'spec/models/instance/announcement_spec.rb' - # Offense count: 8 # Configuration parameters: AllowComments. Lint/EmptyClass: @@ -67,31 +45,6 @@ Lint/NonAtomicFileOperation: Exclude: - 'config/initializers/send_file.rb' -# Offense count: 16 -# This cop supports safe autocorrection (--autocorrect). -Lint/RedundantCopDisableDirective: - Exclude: - - 'app/controllers/concerns/application_user_time_zone_concern.rb' - - 'app/controllers/concerns/course/lesson_plan/strategies/base_personalization_strategy.rb' - - 'app/controllers/concerns/course/lesson_plan/strategies/otot_personalization_strategy.rb' - - 'app/controllers/course/assessment/submission/submissions_controller.rb' - - 'app/controllers/course/courses_controller.rb' - - 'app/controllers/system/admin/instance/courses_controller.rb' - - 'app/models/course/story.rb' - - 'app/services/course/assessment/answer/programming_codaveri_auto_grading_service.rb' - - 'app/services/course/assessment/question/programming/cpp/cpp_package_service.rb' - - 'app/services/course/assessment/question/programming/java/java_package_service.rb' - - 'app/services/course/assessment/question/programming/language_package_service.rb' - - 'app/services/course/assessment/question/programming/python/python_package_service.rb' - - 'app/services/course/assessment/submission/ssid_plagiarism_service.rb' - - 'app/services/course/survey/reminder_service.rb' - - 'lib/extensions/attachable/active_record/base.rb' - - 'lib/extensions/materials/active_record/base.rb' - - 'spec/controllers/course/forum/forums_controller_spec.rb' - - 'spec/support/devise.rb' - - 'spec/support/reference_timelines_helper.rb' - - 'spec/support/stubs/ssid/api_stubs.rb' - # Offense count: 2 Lint/ReturnInVoidContext: Exclude: @@ -143,238 +96,55 @@ Lint/UselessConstantScoping: - 'lib/autoload/coursemology_docker_container.rb' - 'lib/extensions/attachable/active_record/base.rb' -# Offense count: 99 +# Offense count: 11 # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max. Metrics/AbcSize: Exclude: - - 'app/channels/course/monitoring/live_monitoring_channel.rb' - - 'app/controllers/concerns/application_user_concern.rb' - 'app/controllers/concerns/course/assessment/question_bundle_assignment_concern.rb' - 'app/controllers/concerns/course/scholaistic/concern.rb' - - 'app/controllers/concerns/course/statistics/counts_concern.rb' - - 'app/controllers/course/assessment/assessments_controller.rb' - - 'app/controllers/course/assessment/question_bundle_assignments_controller.rb' - - 'app/controllers/course/assessment/submission/submissions_controller.rb' - - 'app/controllers/course/assessment/submission_question/comments_controller.rb' - - 'app/controllers/course/controller.rb' - - 'app/controllers/course/courses_controller.rb' - - 'app/controllers/course/discussion/posts_controller.rb' - - 'app/controllers/course/forum/posts_controller.rb' - - 'app/controllers/course/group/group_categories_controller.rb' - - 'app/controllers/course/lesson_plan/items_controller.rb' - - 'app/controllers/course/material/materials_controller.rb' - - 'app/controllers/course/object_duplications_controller.rb' - - 'app/controllers/course/plagiarism/assessments_controller.rb' - - 'app/controllers/course/scholaistic/scholaistic_assessments_controller.rb' - - 'app/controllers/course/scholaistic/submissions_controller.rb' - - 'app/controllers/course/statistics/assessments_controller.rb' - - 'app/controllers/course/user_invitations_controller.rb' - - 'app/controllers/course/users_controller.rb' - - 'app/controllers/course/video/submission/sessions_controller.rb' - - 'app/controllers/system/admin/instance/users_controller.rb' - - 'app/controllers/system/admin/users_controller.rb' - - 'app/controllers/user/registrations_controller.rb' - - 'app/controllers/users_controller.rb' - - 'app/jobs/course/assessment/answer/programming_codaveri_feedback_job.rb' - - 'app/jobs/video_statistic_update_job.rb' - - 'app/mailers/course/mailer.rb' - - 'app/models/components/course/conditions_ability_component.rb' - - 'app/models/components/course/course_ability_component.rb' - - 'app/models/components/course/materials_ability_component.rb' - - 'app/models/components/course/scholaistic_ability_component.rb' - - 'app/models/concerns/course/duplication_concern.rb' - - 'app/models/concerns/course/video/watch_statistics_concern.rb' - - 'app/models/course/assessment/answer.rb' - - 'app/models/course/assessment/answer/forum_post_response.rb' - - 'app/models/course/assessment/answer/text_response.rb' - - 'app/models/course/assessment/category.rb' - - 'app/models/course/assessment/question/programming.rb' - - 'app/models/course/assessment/tab.rb' - 'app/models/course/lesson_plan/item.rb' - - 'app/models/course/material.rb' - - 'app/models/course/material/folder.rb' - - 'app/models/user/email.rb' - - 'app/notifiers/course/announcement_notifier.rb' - 'app/notifiers/course/assessment/answer/comment_notifier.rb' - 'app/notifiers/course/assessment/submission_question/comment_notifier.rb' - 'app/notifiers/course/assessment_notifier.rb' - - 'app/notifiers/course/forum/post_notifier.rb' - - 'app/notifiers/course/forum/topic_notifier.rb' - - 'app/services/concerns/course/user_invitation_service/parse_invitation_concern.rb' - - 'app/services/concerns/course/user_invitation_service/process_invitation_concern.rb' - - 'app/services/course/assessment/answer/programming_auto_grading_service.rb' - - 'app/services/course/assessment/answer/text_response_auto_grading_service.rb' - - 'app/services/course/assessment/answer/text_response_comprehension_auto_grading_service.rb' - - 'app/services/course/assessment/programming_codaveri_evaluation_service.rb' - 'app/services/course/assessment/question/programming/cpp/cpp_package_service.rb' - 'app/services/course/assessment/question/programming/java/java_package_service.rb' - 'app/services/course/assessment/question/programming/python/python_package_service.rb' - 'app/services/course/assessment/question/programming_codaveri/java/java_package_service.rb' - 'app/services/course/assessment/question/programming_codaveri/python/python_package_service.rb' - - 'app/services/course/assessment/reminder_service.rb' - - 'app/services/course/assessment/submission/ssid_zip_download_service.rb' - - 'app/services/course/duplication/course_duplication_service.rb' - - 'app/services/course/experience_points_download_service.rb' - - 'app/services/course/skills_mastery_preload_service.rb' - - 'app/services/course/survey/reminder_service.rb' - - 'lib/autoload/send_file.rb' - - 'lib/tasks/db/migrate_email_settings.rake' - -# Offense count: 44 + +# Offense count: 5 # Configuration parameters: CountComments, Max, CountAsOne. Metrics/ClassLength: Exclude: - - 'app/channels/course/monitoring/heartbeat_channel.rb' - - 'app/channels/course/monitoring/live_monitoring_channel.rb' - - 'app/controllers/concerns/course/assessment/question_bundle_assignment_concern.rb' - - 'app/controllers/course/assessment/question/multiple_responses_controller.rb' - - 'app/controllers/course/assessment/question/programming_controller.rb' - - 'app/controllers/course/forum/forums_controller.rb' - - 'app/controllers/course/forum/posts_controller.rb' - - 'app/controllers/course/group/group_categories_controller.rb' - - 'app/controllers/course/learning_map_controller.rb' - - 'app/controllers/course/plagiarism/assessments_controller.rb' - - 'app/controllers/course/statistics/aggregate_controller.rb' - 'app/controllers/course/user_invitations_controller.rb' - - 'app/mailers/course/mailer.rb' - 'app/models/course/assessment.rb' - - 'app/models/course/assessment/answer.rb' - - 'app/models/course/assessment/answer/forum_post_response.rb' - - 'app/models/course/assessment/answer/programming.rb' - - 'app/models/course/assessment/question/text_response.rb' - 'app/models/course/assessment/submission.rb' - - 'app/models/course/discussion/post.rb' - - 'app/models/course/experience_points/forum_disbursement.rb' - - 'app/models/course/forum/topic.rb' - - 'app/models/course/lesson_plan/item.rb' - - 'app/models/course/material.rb' - - 'app/models/course/material/folder.rb' - - 'app/models/course/video.rb' - - 'app/models/course_user.rb' - - 'app/models/user.rb' - - 'app/services/course/assessment/answer/programming_auto_grading_service.rb' - - 'app/services/course/assessment/answer/text_response_auto_grading_service.rb' - 'app/services/course/assessment/answer/text_response_comprehension_auto_grading_service.rb' - - 'app/services/course/assessment/question/koditsu_question_service.rb' - - 'app/services/course/assessment/question/programming/cpp/cpp_package_service.rb' - 'app/services/course/assessment/question/programming/java/java_package_service.rb' - - 'app/services/course/assessment/question/programming/python/python_package_service.rb' - - 'app/services/course/assessment/question/programming_codaveri/java/java_package_service.rb' - - 'app/services/course/assessment/question/programming_codaveri/python/python_package_service.rb' - - 'app/services/course/assessment/submission/ssid_zip_download_service.rb' - - 'app/services/course/assessment/submission/statistics_download_service.rb' - - 'app/services/scholaistic_api_service.rb' - - 'lib/autoload/active_job/queue_adapters/background_thread_adapter.rb' - - 'lib/autoload/course/assessment/programming_package.rb' - - 'lib/autoload/coursemology_docker_container.rb' - - 'spec/support/stubs/langchain/llm_stubs.rb' -# Offense count: 43 +# Offense count: 3 # Configuration parameters: AllowedMethods, AllowedPatterns, Max. Metrics/CyclomaticComplexity: Exclude: - - 'app/controllers/concerns/course/assessment/question_bundle_assignment_concern.rb' - 'app/controllers/concerns/course/scholaistic/concern.rb' - - 'app/controllers/course/assessment/assessments_controller.rb' - - 'app/controllers/course/assessment/submission/submissions_controller.rb' - - 'app/controllers/course/assessment/submission_question/comments_controller.rb' - - 'app/controllers/course/courses_controller.rb' - - 'app/controllers/course/discussion/posts_controller.rb' - - 'app/controllers/course/forum/posts_controller.rb' - - 'app/controllers/course/scholaistic/scholaistic_assessments_controller.rb' - - 'app/controllers/course/statistics/assessments_controller.rb' - - 'app/controllers/course/user_invitations_controller.rb' - - 'app/controllers/course/video/submission/sessions_controller.rb' - - 'app/controllers/user/registrations_controller.rb' - - 'app/mailers/course/mailer.rb' - - 'app/models/components/course/course_ability_component.rb' - - 'app/models/components/course/duplication_ability_component.rb' - - 'app/models/components/course/experience_points_records_ability_component.rb' - - 'app/models/concerns/course/assessment/submission/todo_concern.rb' - - 'app/models/course/assessment/question/programming.rb' - 'app/models/course/lesson_plan/item.rb' - - 'app/models/course/settings/lesson_plan_items.rb' - - 'app/notifiers/course/assessment/answer/comment_notifier.rb' - - 'app/notifiers/course/assessment/submission_question/comment_notifier.rb' - - 'app/notifiers/course/assessment_notifier.rb' - - 'app/notifiers/course/forum/post_notifier.rb' - - 'app/notifiers/course/forum/topic_notifier.rb' - - 'app/services/concerns/course/user_invitation_service/parse_invitation_concern.rb' - - 'app/services/concerns/course/user_invitation_service/process_invitation_concern.rb' - - 'app/services/course/assessment/answer/text_response_comprehension_auto_grading_service.rb' - - 'app/services/course/assessment/question/mrq_generation_service.rb' - - 'app/services/course/assessment/question/programming/java/java_package_service.rb' - 'app/services/course/assessment/question/programming_codaveri/java/java_package_service.rb' - - 'app/services/course/assessment/question/programming_codaveri/programming_codaveri_package_service.rb' - - 'app/services/course/assessment/question/programming_codaveri/python/python_package_service.rb' - - 'app/services/course/assessment/reminder_service.rb' - - 'app/services/course/assessment/submission/statistics_download_service.rb' - - 'app/services/instance/user_invitation_service.rb' -# Offense count: 59 +# Offense count: 5 # Configuration parameters: CountComments, Max, CountAsOne, AllowedMethods, AllowedPatterns. Metrics/MethodLength: Exclude: - - 'app/controllers/concerns/course/assessment/question_bundle_assignment_concern.rb' - - 'app/controllers/concerns/course/lesson_plan/personalization_concern.rb' - 'app/controllers/concerns/course/scholaistic/concern.rb' - - 'app/controllers/concerns/course/statistics/counts_concern.rb' - - 'app/controllers/concerns/course/statistics/grades_concern.rb' - - 'app/controllers/course/assessment/assessments_controller.rb' - - 'app/controllers/course/assessment/question/multiple_responses_controller.rb' - - 'app/controllers/course/assessment/submission/submissions_controller.rb' - - 'app/controllers/course/courses_controller.rb' - - 'app/controllers/course/plagiarism/assessments_controller.rb' - - 'app/controllers/course/scholaistic/scholaistic_assessments_controller.rb' - - 'app/controllers/course/scholaistic/submissions_controller.rb' - - 'app/controllers/course/user_invitations_controller.rb' - - 'app/controllers/course/users_controller.rb' - - 'app/controllers/course/video/submission/sessions_controller.rb' - - 'app/controllers/user/registrations_controller.rb' - - 'app/controllers/users_controller.rb' - - 'app/jobs/course/assessment/answer/programming_codaveri_feedback_job.rb' - - 'app/mailers/course/mailer.rb' - - 'app/models/components/course/course_ability_component.rb' - - 'app/models/concerns/course/assessment/new_submission_concern.rb' - 'app/models/course/lesson_plan/item.rb' - - 'app/notifiers/course/assessment/answer/comment_notifier.rb' - - 'app/notifiers/course/assessment/submission_question/comment_notifier.rb' - - 'app/notifiers/course/assessment_notifier.rb' - - 'app/notifiers/course/forum/post_notifier.rb' - - 'app/notifiers/course/forum/topic_notifier.rb' - - 'app/services/concerns/course/user_invitation_service/parse_invitation_concern.rb' - - 'app/services/course/assessment/answer/programming_codaveri_async_feedback_service.rb' - - 'app/services/course/assessment/answer/text_response_comprehension_auto_grading_service.rb' - 'app/services/course/assessment/question/programming/cpp/cpp_package_service.rb' - 'app/services/course/assessment/question/programming/java/java_package_service.rb' - 'app/services/course/assessment/question/programming/python/python_package_service.rb' - - 'app/services/course/assessment/question/programming_codaveri/java/java_package_service.rb' - - 'app/services/course/assessment/question/programming_codaveri/programming_codaveri_package_service.rb' - - 'app/services/course/assessment/question/programming_codaveri/python/python_package_service.rb' - - 'app/services/course/assessment/question/programming_codaveri_service.rb' - - 'app/services/course/assessment/reminder_service.rb' - - 'app/services/course/duplication/course_duplication_service.rb' - - 'app/services/course/survey/reminder_service.rb' - - 'app/services/instance/user_invitation_service.rb' - - 'app/services/rag_wise/chunking_service.rb' - - 'app/uploaders/image_uploader.rb' - - 'lib/autoload/duplicator.rb' - - 'lib/extensions/attachable/active_record/base.rb' - - 'lib/tasks/db/migrate_email_settings.rake' - - 'spec/services/course/user_invitation_service_spec.rb' -# Offense count: 8 +# Offense count: 1 # Configuration parameters: CountComments, Max, CountAsOne. Metrics/ModuleLength: Exclude: - - 'app/controllers/concerns/course/statistics/submissions_concern.rb' - - 'app/controllers/concerns/course/users_controller_management_concern.rb' - - 'app/models/components/course/surveys_ability_component.rb' - - 'app/models/concerns/course/assessment/submission/workflow_event_concern.rb' - 'app/models/course/assessment/assessment_ability.rb' - - 'app/services/concerns/course/user_invitation_service/parse_invitation_concern.rb' - - 'app/services/concerns/course/user_invitation_service/process_invitation_concern.rb' - - 'lib/extensions/attachable/active_record/base.rb' # Offense count: 4 # Configuration parameters: Max, CountKeywordArgs, MaxOptionalParameters. @@ -384,41 +154,12 @@ Metrics/ParameterLists: - 'app/models/ability.rb' - 'app/services/course/assessment/programming_evaluation_service.rb' -# Offense count: 37 +# Offense count: 2 # Configuration parameters: AllowedMethods, AllowedPatterns, Max. Metrics/PerceivedComplexity: Exclude: - - 'app/controllers/concerns/course/assessment/question_bundle_assignment_concern.rb' - - 'app/controllers/concerns/course/assessment/submission/monitoring_concern.rb' - 'app/controllers/concerns/course/scholaistic/concern.rb' - - 'app/controllers/course/assessment/assessments_controller.rb' - - 'app/controllers/course/assessment/submission_question/comments_controller.rb' - - 'app/controllers/course/courses_controller.rb' - - 'app/controllers/course/discussion/posts_controller.rb' - - 'app/controllers/course/forum/posts_controller.rb' - - 'app/controllers/course/scholaistic/scholaistic_assessments_controller.rb' - - 'app/controllers/course/user_invitations_controller.rb' - - 'app/controllers/course/video/submission/sessions_controller.rb' - - 'app/controllers/user/registrations_controller.rb' - - 'app/mailers/course/mailer.rb' - - 'app/models/components/course/course_ability_component.rb' - - 'app/models/concerns/course/assessment/submission/todo_concern.rb' - - 'app/models/course/assessment/answer.rb' - - 'app/models/course/assessment/question/programming.rb' - 'app/models/course/lesson_plan/item.rb' - - 'app/notifiers/course/assessment/answer/comment_notifier.rb' - - 'app/notifiers/course/assessment/submission_question/comment_notifier.rb' - - 'app/notifiers/course/assessment_notifier.rb' - - 'app/notifiers/course/forum/post_notifier.rb' - - 'app/notifiers/course/forum/topic_notifier.rb' - - 'app/services/concerns/course/user_invitation_service/parse_invitation_concern.rb' - - 'app/services/concerns/course/user_invitation_service/process_invitation_concern.rb' - - 'app/services/course/assessment/answer/text_response_comprehension_auto_grading_service.rb' - - 'app/services/course/assessment/question/programming/java/java_package_service.rb' - - 'app/services/course/assessment/question/programming_codaveri/java/java_package_service.rb' - - 'app/services/course/assessment/question/programming_codaveri/python/python_package_service.rb' - - 'app/services/course/assessment/reminder_service.rb' - - 'app/services/course/assessment/submission/statistics_download_service.rb' # Offense count: 24 # This cop supports safe autocorrection (--autocorrect). @@ -796,23 +537,6 @@ Style/MultipleComparison: - 'app/services/course/assessment/koditsu_assessment_invitation_service.rb' - 'app/services/course/assessment/question/programming/language_package_service.rb' -# Offense count: 11 -# Configuration parameters: AllowedClasses. -Style/OneClassPerFile: - Exclude: - - 'spec/**/*' - - 'test/**/*' - - 'app/models/course/settings/codaveri_component.rb' - - 'app/services/concerns/course/user_invitation_service/email_invitation_concern.rb' - - 'app/services/concerns/course/user_invitation_service/parse_invitation_concern.rb' - - 'app/services/concerns/course/user_invitation_service/process_invitation_concern.rb' - - 'app/services/concerns/instance/user_invitation_service/email_invitation_concern.rb' - - 'app/services/concerns/instance/user_invitation_service/parse_invitation_concern.rb' - - 'app/services/concerns/instance/user_invitation_service/process_invitation_concern.rb' - - 'config/initializers/action_cable_acts_as_tenant.rb' - - 'lib/extensions/deferred_workflow_state_persistence/workflow.rb' - - 'lib/extensions/polyglot_with_database/coursemology/polyglot/language.rb' - # Offense count: 26 Style/OpenStructUse: Exclude: diff --git a/app/controllers/concerns/application_user_time_zone_concern.rb b/app/controllers/concerns/application_user_time_zone_concern.rb index 581aceaf05..d485501697 100644 --- a/app/controllers/concerns/application_user_time_zone_concern.rb +++ b/app/controllers/concerns/application_user_time_zone_concern.rb @@ -9,7 +9,7 @@ module ApplicationUserTimeZoneConcern protected # Set the time_zone for current request. - def set_time_zone(&block) # rubocop:disable Naming/AccessorMethodName + def set_time_zone(&block) Time.use_zone(current_user.time_zone, &block) end end diff --git a/app/controllers/concerns/course/assessment/answer/update_answer_concern.rb b/app/controllers/concerns/course/assessment/answer/update_answer_concern.rb index ab26b2ab16..be53d85d6c 100644 --- a/app/controllers/concerns/course/assessment/answer/update_answer_concern.rb +++ b/app/controllers/concerns/course/assessment/answer/update_answer_concern.rb @@ -31,7 +31,7 @@ def additional_answer_params(answer) end end - def update_specific_answer_type_params(answer) # rubocop:disable Metrics/MethodLength,Metrics/CyclomaticComplexity + def update_specific_answer_type_params(answer) answer_actable_class = answer.actable.class.name scalar_params = [] array_params = {} diff --git a/app/controllers/concerns/course/assessment/question/koditsu_question_concern.rb b/app/controllers/concerns/course/assessment/question/koditsu_question_concern.rb index 3fda352e3a..07d9555d78 100644 --- a/app/controllers/concerns/course/assessment/question/koditsu_question_concern.rb +++ b/app/controllers/concerns/course/assessment/question/koditsu_question_concern.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -# rubocop:disable Metrics/ModuleLength module Course::Assessment::Question::KoditsuQuestionConcern extend ActiveSupport::Concern include Course::Assessment::KoditsuAssessmentConcern @@ -146,4 +145,3 @@ def koditsu_programming_language_map } end end -# rubocop:enable Metrics/ModuleLength diff --git a/app/controllers/concerns/course/assessment/submission/monitoring_concern.rb b/app/controllers/concerns/course/assessment/submission/monitoring_concern.rb index 7692acbc24..5988ca6f41 100644 --- a/app/controllers/concerns/course/assessment/submission/monitoring_concern.rb +++ b/app/controllers/concerns/course/assessment/submission/monitoring_concern.rb @@ -8,7 +8,7 @@ module Course::Assessment::Submission::MonitoringConcern after_action :stop_monitoring_session_if_submitted, only: [:update] end - def should_monitor? # rubocop:disable Metrics/CyclomaticComplexity + def should_monitor? monitoring_component_enabled? && current_user.id == @submission.creator_id && current_course_user&.student? && diff --git a/app/controllers/concerns/course/lesson_plan/learning_rate_concern.rb b/app/controllers/concerns/course/lesson_plan/learning_rate_concern.rb index 6a4144d8e4..7fa27fb09c 100644 --- a/app/controllers/concerns/course/lesson_plan/learning_rate_concern.rb +++ b/app/controllers/concerns/course/lesson_plan/learning_rate_concern.rb @@ -28,7 +28,7 @@ def lesson_plan_items_submission_time_hash(course_user) # their submitted time, if relevant/available. # @param [Float] alpha Alpha value used in exponential moving average computation. # @return [Float|nil] Learning rate exponential moving average, if computable. - def compute_learning_rate_ema(course_user, items_affecting_personal_times, submitted_items, alpha = 0.4) # rubocop:disable Metrics/AbcSize + def compute_learning_rate_ema(course_user, items_affecting_personal_times, submitted_items, alpha = 0.4) submitted_items_affecting_personal_times = items_affecting_personal_times. select { |i| i.id.in? submitted_items.keys }. select { |i| i.time_for(course_user).end_at.present? } @@ -67,7 +67,7 @@ def compute_learning_rate_ema(course_user, items_affecting_personal_times, submi # @param [Float] min_learning_rate The minimum overall learning rate. # @param [Float] max_learning_rate The maximum overall learning rate. # @return [Array] An array pair containing [min learning rate, max learning rate]. - def compute_learning_rate_effective_limits(course_user, items, submitted_items, min_learning_rate, max_learning_rate) # rubocop:disable Metrics/AbcSize + def compute_learning_rate_effective_limits(course_user, items, submitted_items, min_learning_rate, max_learning_rate) course_start = items.first.start_at course_end = items.last.start_at last_submitted_item = items.reverse_each.lazy. diff --git a/app/controllers/concerns/course/lesson_plan/strategies/base_personalization_strategy.rb b/app/controllers/concerns/course/lesson_plan/strategies/base_personalization_strategy.rb index 858eae7d1d..85cba7048b 100644 --- a/app/controllers/concerns/course/lesson_plan/strategies/base_personalization_strategy.rb +++ b/app/controllers/concerns/course/lesson_plan/strategies/base_personalization_strategy.rb @@ -28,7 +28,7 @@ class Course::LessonPlan::Strategies::BasePersonalizationStrategy # # @param [CourseUser] course_user The course user to compute data for. # @return [Hash] Precomputed data to aid execution. - def precompute_data(course_user) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength + def precompute_data(course_user) submitted_items = lesson_plan_items_submission_time_hash(course_user) items = lesson_plan_items_with_sorted_times_for(course_user) items_affecting_personal_times = items.select(&:affects_personal_times?) diff --git a/app/controllers/concerns/course/lesson_plan/strategies/fomo_personalization_strategy.rb b/app/controllers/concerns/course/lesson_plan/strategies/fomo_personalization_strategy.rb index 7175a96a36..e6e5ec30a0 100644 --- a/app/controllers/concerns/course/lesson_plan/strategies/fomo_personalization_strategy.rb +++ b/app/controllers/concerns/course/lesson_plan/strategies/fomo_personalization_strategy.rb @@ -15,7 +15,7 @@ class Course::LessonPlan::Strategies::FomoPersonalizationStrategy < # @param [Hash] precomputed_data The default data precomputed by precompute_data. # @param [Set|nil] items_to_shift Set of item ids to shift. If provided, only items with ids in this set will # be shifted. - def execute(course_user, precomputed_data, items_to_shift = nil) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength + def execute(course_user, precomputed_data, items_to_shift = nil) return if precomputed_data[:learning_rate_ema].nil? @course_tz = course_user.course.time_zone diff --git a/app/controllers/concerns/course/lesson_plan/strategies/otot_personalization_strategy.rb b/app/controllers/concerns/course/lesson_plan/strategies/otot_personalization_strategy.rb index 0874712c47..8a361efd76 100644 --- a/app/controllers/concerns/course/lesson_plan/strategies/otot_personalization_strategy.rb +++ b/app/controllers/concerns/course/lesson_plan/strategies/otot_personalization_strategy.rb @@ -7,7 +7,7 @@ class Course::LessonPlan::Strategies::OtotPersonalizationStrategy < # # @param [CourseUser] course_user The course user to compute data for. # @return [Hash] Precomputed data to aid execution. - def precompute_data(course_user) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength + def precompute_data(course_user) submitted_items = lesson_plan_items_submission_time_hash(course_user) items = lesson_plan_items_with_sorted_times_for(course_user) items_affecting_personal_times = items.select(&:affects_personal_times?) diff --git a/app/controllers/concerns/course/lesson_plan/strategies/stragglers_personalization_strategy.rb b/app/controllers/concerns/course/lesson_plan/strategies/stragglers_personalization_strategy.rb index 0ca6c82b5c..2dbd46004e 100644 --- a/app/controllers/concerns/course/lesson_plan/strategies/stragglers_personalization_strategy.rb +++ b/app/controllers/concerns/course/lesson_plan/strategies/stragglers_personalization_strategy.rb @@ -16,7 +16,7 @@ class Course::LessonPlan::Strategies::StragglersPersonalizationStrategy < # @param [Hash] precomputed_data The default data precomputed by precompute_data. # @param [Set|nil] items_to_shift Set of item ids to shift. If provided, only items with ids in this set will # be shifted. - def execute(course_user, precomputed_data, items_to_shift = nil) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength + def execute(course_user, precomputed_data, items_to_shift = nil) return if precomputed_data[:learning_rate_ema].nil? @course_tz = course_user.course.time_zone diff --git a/app/controllers/concerns/course/unread_counts_concern.rb b/app/controllers/concerns/course/unread_counts_concern.rb index b41a3c9c1c..3c1b243353 100644 --- a/app/controllers/concerns/course/unread_counts_concern.rb +++ b/app/controllers/concerns/course/unread_counts_concern.rb @@ -44,7 +44,7 @@ def pending_assessment_submissions_count end end - def unread_comments_count # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity + def unread_comments_count self.class.include Course::Discussion::TopicsHelper is_staff_with_students = current_course_user&.staff? && !current_course_user.my_students.empty? diff --git a/app/controllers/course/admin/component_settings_controller.rb b/app/controllers/course/admin/component_settings_controller.rb index 6bc9a8f11d..fb78d92e25 100644 --- a/app/controllers/course/admin/component_settings_controller.rb +++ b/app/controllers/course/admin/component_settings_controller.rb @@ -11,7 +11,7 @@ def edit end end - def update # rubocop:disable Metrics/AbcSize + def update if @settings.update(settings_components_params) && current_course.save is_koditsu_enabled = settings_components_params['enabled_component_ids']. include?('course_koditsu_platform_component') diff --git a/app/controllers/course/assessment/question/forum_post_responses_controller.rb b/app/controllers/course/assessment/question/forum_post_responses_controller.rb index 733dd89a77..4ca5739c52 100644 --- a/app/controllers/course/assessment/question/forum_post_responses_controller.rb +++ b/app/controllers/course/assessment/question/forum_post_responses_controller.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Course::Assessment::Question::ForumPostResponsesController < Course::Assessment::Question::Controller # rubocop:disable Metrics/ClassLength +class Course::Assessment::Question::ForumPostResponsesController < Course::Assessment::Question::Controller include Course::Assessment::Question::GradingContextParamsConcern build_and_authorize_new_question :forum_post_response_question, diff --git a/app/controllers/course/assessment/question/rubric_based_responses_controller.rb b/app/controllers/course/assessment/question/rubric_based_responses_controller.rb index 4d98dd36dd..fde1342e28 100644 --- a/app/controllers/course/assessment/question/rubric_based_responses_controller.rb +++ b/app/controllers/course/assessment/question/rubric_based_responses_controller.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Course::Assessment::Question::RubricBasedResponsesController < Course::Assessment::Question::Controller # rubocop:disable Metrics/ClassLength +class Course::Assessment::Question::RubricBasedResponsesController < Course::Assessment::Question::Controller include Course::Assessment::Question::RubricBasedResponseControllerConcern include Course::Assessment::Question::GradingContextParamsConcern diff --git a/app/controllers/course/assessment/question/scribing_controller.rb b/app/controllers/course/assessment/question/scribing_controller.rb index 18e67d6f87..120560c27d 100644 --- a/app/controllers/course/assessment/question/scribing_controller.rb +++ b/app/controllers/course/assessment/question/scribing_controller.rb @@ -19,7 +19,7 @@ def show end end - def create # rubocop:disable Metrics/MethodLength + def create if file_is_pdf? respond_to do |format| if pdf_import_service.save diff --git a/app/controllers/course/assessment/rubrics_controller.rb b/app/controllers/course/assessment/rubrics_controller.rb index 94b5752e29..016da4fa57 100644 --- a/app/controllers/course/assessment/rubrics_controller.rb +++ b/app/controllers/course/assessment/rubrics_controller.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Course::Assessment::RubricsController < Course::Assessment::QuestionsController # rubocop:disable Metrics/ClassLength +class Course::Assessment::RubricsController < Course::Assessment::QuestionsController load_resource :rubric, class: 'Course::Rubric', through: :question, except: [:index, :rubric_answers, :grading_contexts, :answer_grading_contexts] diff --git a/app/controllers/course/assessment/submission/submissions_controller.rb b/app/controllers/course/assessment/submission/submissions_controller.rb index 9f6c0d4a4d..42d584eef2 100644 --- a/app/controllers/course/assessment/submission/submissions_controller.rb +++ b/app/controllers/course/assessment/submission/submissions_controller.rb @@ -40,7 +40,7 @@ def index @course_users = current_course.course_users.order_phantom_user.order_alphabetically end - def create # rubocop:disable Metrics/AbcSize + def create authorize! :access, @assessment existing_submission = @assessment.submissions.find_by(creator: current_user) @@ -419,7 +419,7 @@ def download_job # Check for zombie jobs, create new grading jobs if there's any zombie jobs. # TODO: Remove this method after found the cause of the dead jobs. - def check_zombie_jobs # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity + def check_zombie_jobs return unless @submission.attempting? || @submission.submitted? submitted_answers = @submission.answers.where(workflow_state: 'submitted') diff --git a/app/controllers/course/courses_controller.rb b/app/controllers/course/courses_controller.rb index 60e3a51c08..54da086eab 100644 --- a/app/controllers/course/courses_controller.rb +++ b/app/controllers/course/courses_controller.rb @@ -61,7 +61,7 @@ def course_params permit(:title, :description, :status, :start_at, :end_at, :logo) end - def load_todos # rubocop:disable Metrics/AbcSize + def load_todos return unless current_course_user&.student? todos = Course::LessonPlan::Todo.pending_for(current_course_user). @@ -89,7 +89,7 @@ def load_todos # rubocop:disable Metrics/AbcSize to_h { |survey| [survey.survey_id, survey] } end - def load_items_with_timeline # rubocop:disable Metrics/CyclomaticComplexity + def load_items_with_timeline return unless current_course_user&.student? item_ids = [*@video_todos&.map { |todo| todo.item.id }, diff --git a/app/controllers/course/gradebook_controller.rb b/app/controllers/course/gradebook_controller.rb index 80d26367d3..19f8c7789c 100644 --- a/app/controllers/course/gradebook_controller.rb +++ b/app/controllers/course/gradebook_controller.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Course::GradebookController < Course::ComponentController # rubocop:disable Metrics/ClassLength +class Course::GradebookController < Course::ComponentController include Course::Gradebook::WeightParsingConcern before_action :authorize_read_gradebook! diff --git a/app/controllers/course/learning_map_controller.rb b/app/controllers/course/learning_map_controller.rb index 3e9dbad11b..881199e223 100644 --- a/app/controllers/course/learning_map_controller.rb +++ b/app/controllers/course/learning_map_controller.rb @@ -91,7 +91,7 @@ def map_conditionals_to_nodes generate_node_depths(nodes) end - def generate_all_node_relations # rubocop:disable Metrics/AbcSize, Metrics/MethodLength + def generate_all_node_relations relations = init_all_node_relations node_ids_to_children = relations[:node_ids_to_children] node_ids_to_parents = relations[:node_ids_to_parents] @@ -131,7 +131,7 @@ def map_condition_to_parent(condition) { id: id, is_satisfied: typed_condition.satisfied_by?(current_course_user) } end - def generate_nodes_from_conditionals(all_node_relations) # rubocop:disable Metrics/AbcSize + def generate_nodes_from_conditionals(all_node_relations) node_ids_to_children = all_node_relations[:node_ids_to_children] node_ids_to_parents = all_node_relations[:node_ids_to_parents] node_ids_to_unlock_level = all_node_relations[:node_ids_to_unlock_level] diff --git a/app/controllers/course/statistics/aggregate_controller.rb b/app/controllers/course/statistics/aggregate_controller.rb index 266a384497..4dd765e223 100644 --- a/app/controllers/course/statistics/aggregate_controller.rb +++ b/app/controllers/course/statistics/aggregate_controller.rb @@ -109,7 +109,7 @@ def assessment_info_array :start_at, :end_at) end - def user_submission_array # rubocop:disable Metrics/AbcSize + def user_submission_array submission_data_arr = Course::Assessment::Submission.joins(creator: :course_users). where(assessment_id: assessment_info_array.map { |i| i[0] }, course_users: { course_id: current_course.id, role: :student }). diff --git a/app/controllers/course/statistics/assessments_controller.rb b/app/controllers/course/statistics/assessments_controller.rb index 1b55243ba4..947387520c 100644 --- a/app/controllers/course/statistics/assessments_controller.rb +++ b/app/controllers/course/statistics/assessments_controller.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Course::Statistics::AssessmentsController < Course::Statistics::Controller # rubocop:disable Metrics/ClassLength +class Course::Statistics::AssessmentsController < Course::Statistics::Controller include Course::UsersHelper include Course::Statistics::SubmissionsConcern include Course::Statistics::UsersConcern diff --git a/app/controllers/system/admin/instance/courses_controller.rb b/app/controllers/system/admin/instance/courses_controller.rb index 7483866a00..0b423d3483 100644 --- a/app/controllers/system/admin/instance/courses_controller.rb +++ b/app/controllers/system/admin/instance/courses_controller.rb @@ -24,7 +24,7 @@ def search_param params.permit(:search)[:search] end - def preload_courses # rubocop:disable Metrics/AbcSize + def preload_courses @courses = @instance.courses.search(search_param).calculated(:active_user_count, :user_count) @courses = @courses.active_in_past_7_days if ActiveRecord::Type::Boolean.new.cast(params[:active]) diff --git a/app/helpers/application_html_formatters_helper.rb b/app/helpers/application_html_formatters_helper.rb index be900d3a31..0cd72f2545 100644 --- a/app/helpers/application_html_formatters_helper.rb +++ b/app/helpers/application_html_formatters_helper.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -# rubocop:disable Metrics/ModuleLength module ApplicationHtmlFormattersHelper # Constants that defines the size/lines limit of the code MAX_CODE_SIZE = 50 * 1024 # 50 KB @@ -285,4 +284,3 @@ def remove_internal_adjacent_code_tags(text) end end end -# rubocop:enable Metrics/ModuleLength diff --git a/app/helpers/course/discussion/topics_helper.rb b/app/helpers/course/discussion/topics_helper.rb index 289b37111d..ccd99d3b6f 100644 --- a/app/helpers/course/discussion/topics_helper.rb +++ b/app/helpers/course/discussion/topics_helper.rb @@ -56,7 +56,7 @@ def my_students_unread_count # This replaces what the `from_user` scopes in the specific models were doing when getting # my_students_unread_count, for better performance. - def from_user(topic, my_student_ids) # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity + def from_user(topic, my_student_ids) case topic.actable_type when 'Course::Assessment::SubmissionQuestion' my_student_ids.include?(topic&.actable&.submission&.creator_id) diff --git a/app/models/concerns/course/course_user_type_concern.rb b/app/models/concerns/course/course_user_type_concern.rb index d7bfaea7af..61096c02a2 100644 --- a/app/models/concerns/course/course_user_type_concern.rb +++ b/app/models/concerns/course/course_user_type_concern.rb @@ -17,7 +17,6 @@ def valid_course_user_type?(type) end end - # rubocop:disable Metrics/CyclomaticComplexity def course_users_by_type(type, user) case type when COURSE_USER_TYPES[:my_students] @@ -34,5 +33,4 @@ def course_users_by_type(type, user) students.without_phantom_users # :students is the default type end end - # rubocop:enable Metrics/CyclomaticComplexity end diff --git a/app/models/course/assessment.rb b/app/models/course/assessment.rb index 4153327695..810fd3c941 100644 --- a/app/models/course/assessment.rb +++ b/app/models/course/assessment.rb @@ -364,7 +364,7 @@ def record_marketplace_adoption(duplicate, destination_course, current_user) ) end - def initialize_duplicate(duplicator, other) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength + def initialize_duplicate(duplicator, other) # rubocop:disable Metrics/AbcSize copy_attributes(other, duplicator) target_tab = initialize_duplicate_tab(duplicator, other) self.folder = duplicator.duplicate(other.folder) diff --git a/app/models/course/assessment/answer.rb b/app/models/course/assessment/answer.rb index bcfb54dd26..c1cd5b4348 100644 --- a/app/models/course/assessment/answer.rb +++ b/app/models/course/assessment/answer.rb @@ -178,7 +178,7 @@ def publish private - def validate_session_and_client_version # rubocop:disable Metrics/CyclomaticComplexity + def validate_session_and_client_version return if last_session_id.nil? || client_version.nil? return if last_session_id_changed? || !client_version_changed? return if client_version_change[0].nil? diff --git a/app/models/course/assessment/question.rb b/app/models/course/assessment/question.rb index 24502a77fa..00af0759c3 100644 --- a/app/models/course/assessment/question.rb +++ b/app/models/course/assessment/question.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Course::Assessment::Question < ApplicationRecord # rubocop:disable Metrics/ClassLength +class Course::Assessment::Question < ApplicationRecord include Course::SanitizeDescriptionConcern actable optional: true diff --git a/app/models/course/assessment/question/programming.rb b/app/models/course/assessment/question/programming.rb index c9a0f23ec1..e99765c0b4 100644 --- a/app/models/course/assessment/question/programming.rb +++ b/app/models/course/assessment/question/programming.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Course::Assessment::Question::Programming < ApplicationRecord # rubocop:disable Metrics/ClassLength +class Course::Assessment::Question::Programming < ApplicationRecord enum :package_type, { zip_upload: 0, online_editor: 1 } # The table name for this model is singular. diff --git a/app/models/course/gradebook/level_config.rb b/app/models/course/gradebook/level_config.rb index 51e719e66b..146c931ad7 100644 --- a/app/models/course/gradebook/level_config.rb +++ b/app/models/course/gradebook/level_config.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Course::Gradebook::LevelConfig < ApplicationRecord # rubocop:disable Metrics/ClassLength +class Course::Gradebook::LevelConfig < ApplicationRecord belongs_to :course, inverse_of: :gradebook_level_config validates :weight, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 100 } diff --git a/app/models/course/learning_rate_record.rb b/app/models/course/learning_rate_record.rb index 5c4756285a..9575964b54 100644 --- a/app/models/course/learning_rate_record.rb +++ b/app/models/course/learning_rate_record.rb @@ -13,7 +13,7 @@ class Course::LearningRateRecord < ApplicationRecord default_scope { order(created_at: :desc) } # Implicitly asserts that effective_min <= effective_max as well - def learning_rate_between_effective_min_and_max # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity + def learning_rate_between_effective_min_and_max # We return if any of the three attributes is nil, since that will be handled by the presence check return if learning_rate.nil? || effective_min.nil? || effective_max.nil? return if effective_min <= learning_rate && learning_rate <= effective_max diff --git a/app/models/course/rubric.rb b/app/models/course/rubric.rb index 9eacccb90e..c634420044 100644 --- a/app/models/course/rubric.rb +++ b/app/models/course/rubric.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Course::Rubric < ApplicationRecord # rubocop:disable Metrics/ClassLength +class Course::Rubric < ApplicationRecord include DuplicationStateTrackingConcern include Course::Rubric::CopyOnWriteConcern diff --git a/app/models/course/story.rb b/app/models/course/story.rb index 8a72fbb04e..2eba9f34e0 100644 --- a/app/models/course/story.rb +++ b/app/models/course/story.rb @@ -64,7 +64,7 @@ def find_or_create_personal_time_for(_course_user) PersonalTime.new(@course_user, @id, reference_time.start_at) end - def has_personal_times? # rubocop:disable Naming/PredicateName + def has_personal_times? true end diff --git a/app/services/course/assessment/answer/programming_codaveri_async_feedback_service.rb b/app/services/course/assessment/answer/programming_codaveri_async_feedback_service.rb index c11d2c74c0..f65fcb26af 100644 --- a/app/services/course/assessment/answer/programming_codaveri_async_feedback_service.rb +++ b/app/services/course/assessment/answer/programming_codaveri_async_feedback_service.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Course::Assessment::Answer::ProgrammingCodaveriAsyncFeedbackService # rubocop:disable Metrics/ClassLength +class Course::Assessment::Answer::ProgrammingCodaveriAsyncFeedbackService CODAVERI_LANGUAGE_MAPPING = { en: 'english', zh: 'chinese' @@ -116,7 +116,7 @@ def process_codaveri_feedback end end - def save_annotation(file, feedback_line) # rubocop:disable Metrics/AbcSize + def save_annotation(file, feedback_line) feedback_id = feedback_line['id'] linenum = feedback_line['linenum'].to_i feedback = feedback_line['feedback'] diff --git a/app/services/course/assessment/answer/programming_codaveri_auto_grading_service.rb b/app/services/course/assessment/answer/programming_codaveri_auto_grading_service.rb index 4e2f6e9904..d5016dca3f 100644 --- a/app/services/course/assessment/answer/programming_codaveri_auto_grading_service.rb +++ b/app/services/course/assessment/answer/programming_codaveri_auto_grading_service.rb @@ -121,7 +121,7 @@ def build_test_case_records(question, auto_grading, evaluation_results) # grading result to store the test results in. # @param [Array] evaluation_results The evaluation results from Codaveri API Response. # @return [Array] - def build_test_case_records_from_test_results(question, auto_grading, evaluation_results) # rubocop:disable Metrics/AbcSize + def build_test_case_records_from_test_results(question, auto_grading, evaluation_results) test_cases = question.test_cases.to_h { |test_case| [test_case.id, test_case] } evaluation_results.map do |result| test_case = find_test_case(test_cases, result.index) diff --git a/app/services/course/assessment/marketplace/apply_version_service.rb b/app/services/course/assessment/marketplace/apply_version_service.rb index e88b4df7ca..72100ba70e 100644 --- a/app/services/course/assessment/marketplace/apply_version_service.rb +++ b/app/services/course/assessment/marketplace/apply_version_service.rb @@ -125,7 +125,6 @@ def adopt_content!(temp) # hide an assessment, nor move it out from under the manager who filed it. Unlock conditions and # link-tree membership are untouched for a stronger reason — they reference this course's objects, # so the snapshot's would be meaningless. - # rubocop:disable Metrics/AbcSize def copy_attributes!(temp, version) @assessment.title = resolved_title(temp.title, version) @assessment.description = temp.description @@ -143,7 +142,6 @@ def copy_attributes!(temp, version) @assessment.affects_personal_times = temp.affects_personal_times @assessment.save! end - # rubocop:enable Metrics/AbcSize # Collision rule excluding this assessment itself. Its own old title is exactly what it # is replacing, so it must not count as a collision. diff --git a/app/services/course/assessment/programming_codaveri_evaluation_service.rb b/app/services/course/assessment/programming_codaveri_evaluation_service.rb index 016bf29e37..b41e53ded4 100644 --- a/app/services/course/assessment/programming_codaveri_evaluation_service.rb +++ b/app/services/course/assessment/programming_codaveri_evaluation_service.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true # Sets up a programming evaluation, queues it for execution by codaveri evaluators, then returns the results. -class Course::Assessment::ProgrammingCodaveriEvaluationService # rubocop:disable Metrics/ClassLength +class Course::Assessment::ProgrammingCodaveriEvaluationService include Course::Assessment::Question::CodaveriQuestionConcern # The default timeout for the job to finish. @@ -292,7 +292,7 @@ def build_expr_test_case_result(result) ) end - def build_evaluation_result # rubocop:disable Metrics/CyclomaticComplexity + def build_evaluation_result stdout = @codaveri_evaluation_results.map(&:stdout).reject(&:empty?).join("\n") stderr = @codaveri_evaluation_results.map(&:stderr).reject(&:empty?).join("\n") exit_code = (@codaveri_evaluation_results.map(&:success).all? { |n| n == 1 }) ? 0 : 2 diff --git a/app/services/course/assessment/question/codaveri_problem_generation_service.rb b/app/services/course/assessment/question/codaveri_problem_generation_service.rb index fe4dcd59e6..6c22f38628 100644 --- a/app/services/course/assessment/question/codaveri_problem_generation_service.rb +++ b/app/services/course/assessment/question/codaveri_problem_generation_service.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Course::Assessment::Question::CodaveriProblemGenerationService # rubocop:disable Metrics/ClassLength +class Course::Assessment::Question::CodaveriProblemGenerationService POLL_INTERVAL_SECONDS = 2 MAX_POLL_RETRIES = 1000 @@ -42,7 +42,7 @@ def codaveri_generate_problem private - def initialize(assessment, params, language, version) # rubocop:disable Metrics/AbcSize + def initialize(assessment, params, language, version) custom_prompt = params[:custom_prompt].to_s @payload = { userId: assessment.creator_id.to_s, diff --git a/app/services/course/assessment/question/programming/c_sharp/c_sharp_package_service.rb b/app/services/course/assessment/question/programming/c_sharp/c_sharp_package_service.rb index 339ba24d50..893ef09579 100644 --- a/app/services/course/assessment/question/programming/c_sharp/c_sharp_package_service.rb +++ b/app/services/course/assessment/question/programming/c_sharp/c_sharp_package_service.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Course::Assessment::Question::Programming::CSharp::CSharpPackageService < # rubocop:disable Metrics/ClassLength +class Course::Assessment::Question::Programming::CSharp::CSharpPackageService < Course::Assessment::Question::Programming::LanguagePackageService def submission_templates [ diff --git a/app/services/course/assessment/question/programming/cpp/cpp_package_service.rb b/app/services/course/assessment/question/programming/cpp/cpp_package_service.rb index c9a3d0a76a..a2d15ad3a3 100644 --- a/app/services/course/assessment/question/programming/cpp/cpp_package_service.rb +++ b/app/services/course/assessment/question/programming/cpp/cpp_package_service.rb @@ -166,7 +166,7 @@ def get_file_path(filename) File.join(__dir__, filename).freeze end - def zip_test_files(test_type, zip) # rubocop:disable Metrics/AbcSize + def zip_test_files(test_type, zip) tests = @test_params[:test_cases] tests[test_type]&.each&.with_index(1) do |test, index| # String types should be displayed with quotes, other types will be converted to string diff --git a/app/services/course/assessment/question/programming/go/go_package_service.rb b/app/services/course/assessment/question/programming/go/go_package_service.rb index ce7e9e28ab..3f81d9c21d 100644 --- a/app/services/course/assessment/question/programming/go/go_package_service.rb +++ b/app/services/course/assessment/question/programming/go/go_package_service.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Course::Assessment::Question::Programming::Go::GoPackageService < # rubocop:disable Metrics/ClassLength +class Course::Assessment::Question::Programming::Go::GoPackageService < Course::Assessment::Question::Programming::LanguagePackageService def submission_templates [ diff --git a/app/services/course/assessment/question/programming/java/java_package_service.rb b/app/services/course/assessment/question/programming/java/java_package_service.rb index fde8184cf9..81c45858ab 100644 --- a/app/services/course/assessment/question/programming/java/java_package_service.rb +++ b/app/services/course/assessment/question/programming/java/java_package_service.rb @@ -235,7 +235,7 @@ def generate_standard_submission_solution_files(zip, submission_files_to_keep, s end end - def zip_test_files(test_type, zip) # rubocop:disable Metrics/AbcSize + def zip_test_files(test_type, zip) tests = @test_params[:test_cases] tests[test_type]&.each&.with_index(1) do |test, index| # String types should be displayed with quotes, other types will be converted to string diff --git a/app/services/course/assessment/question/programming/java_script/java_script_package_service.rb b/app/services/course/assessment/question/programming/java_script/java_script_package_service.rb index c332e10133..18d9674189 100644 --- a/app/services/course/assessment/question/programming/java_script/java_script_package_service.rb +++ b/app/services/course/assessment/question/programming/java_script/java_script_package_service.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Course::Assessment::Question::Programming::JavaScript::JavaScriptPackageService < # rubocop:disable Metrics/ClassLength +class Course::Assessment::Question::Programming::JavaScript::JavaScriptPackageService < Course::Assessment::Question::Programming::LanguagePackageService def submission_templates [ diff --git a/app/services/course/assessment/question/programming/language_package_service.rb b/app/services/course/assessment/question/programming/language_package_service.rb index 3954bfa887..19d118d91e 100644 --- a/app/services/course/assessment/question/programming/language_package_service.rb +++ b/app/services/course/assessment/question/programming/language_package_service.rb @@ -38,7 +38,7 @@ def submission_templates # # @param [AttachmentReference] Previous package, may contain files that the new package uses. # @return [Tempfile] - def generate_package(old_attachment) # rubocop:disable Lint/UnusedMethodArgument + def generate_package(old_attachment) raise NotImplementedError, 'You must implement this' end @@ -64,7 +64,7 @@ def default_meta # @param [Array] An Array of template # files used to generate meta for non-autograded questions. # @return [Hash] - def extract_meta(attachment, template_files) # rubocop:disable Lint/UnusedMethodArgument + def extract_meta(attachment, template_files) raise NotImplementedError, 'You must implement this' end diff --git a/app/services/course/assessment/question/programming/programming_package_service.rb b/app/services/course/assessment/question/programming/programming_package_service.rb index 859f4d018c..7248895a10 100644 --- a/app/services/course/assessment/question/programming/programming_package_service.rb +++ b/app/services/course/assessment/question/programming/programming_package_service.rb @@ -39,7 +39,7 @@ def extract_meta private - def init_language_package_service(params) # rubocop:disable Metrics/MethodLength,Metrics/CyclomaticComplexity + def init_language_package_service(params) @language_package_service = case @language when Coursemology::Polyglot::Language::Python diff --git a/app/services/course/assessment/question/programming/python/python_package_service.rb b/app/services/course/assessment/question/programming/python/python_package_service.rb index 22d6ac8193..964edfd787 100644 --- a/app/services/course/assessment/question/programming/python/python_package_service.rb +++ b/app/services/course/assessment/question/programming/python/python_package_service.rb @@ -160,7 +160,7 @@ def get_file_path(filename) File.join(__dir__, filename).freeze end - def zip_test_files(test_type, zip) # rubocop:disable Metrics/AbcSize + def zip_test_files(test_type, zip) # Print test class preamble test_class_name = "#{test_type}_tests_grader".camelize class_definition = <<~PYTHON diff --git a/app/services/course/assessment/question/programming/r/r_package_service.rb b/app/services/course/assessment/question/programming/r/r_package_service.rb index 14069bf162..a4e11bbe51 100644 --- a/app/services/course/assessment/question/programming/r/r_package_service.rb +++ b/app/services/course/assessment/question/programming/r/r_package_service.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Course::Assessment::Question::Programming::R::RPackageService < # rubocop:disable Metrics/ClassLength +class Course::Assessment::Question::Programming::R::RPackageService < Course::Assessment::Question::Programming::LanguagePackageService def submission_templates [ diff --git a/app/services/course/assessment/question/programming/rust/rust_package_service.rb b/app/services/course/assessment/question/programming/rust/rust_package_service.rb index 3df1a2d000..3f070f9735 100644 --- a/app/services/course/assessment/question/programming/rust/rust_package_service.rb +++ b/app/services/course/assessment/question/programming/rust/rust_package_service.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Course::Assessment::Question::Programming::Rust::RustPackageService < # rubocop:disable Metrics/ClassLength +class Course::Assessment::Question::Programming::Rust::RustPackageService < Course::Assessment::Question::Programming::LanguagePackageService def submission_templates [ diff --git a/app/services/course/assessment/question/programming/type_script/type_script_package_service.rb b/app/services/course/assessment/question/programming/type_script/type_script_package_service.rb index 853c46b5c1..7a6c9ad967 100644 --- a/app/services/course/assessment/question/programming/type_script/type_script_package_service.rb +++ b/app/services/course/assessment/question/programming/type_script/type_script_package_service.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Course::Assessment::Question::Programming::TypeScript::TypeScriptPackageService < # rubocop:disable Metrics/ClassLength +class Course::Assessment::Question::Programming::TypeScript::TypeScriptPackageService < Course::Assessment::Question::Programming::LanguagePackageService def submission_templates [ diff --git a/app/services/course/assessment/question/programming_codaveri/c_sharp/c_sharp_package_service.rb b/app/services/course/assessment/question/programming_codaveri/c_sharp/c_sharp_package_service.rb index 2360882dbe..1c7f3bc99d 100644 --- a/app/services/course/assessment/question/programming_codaveri/c_sharp/c_sharp_package_service.rb +++ b/app/services/course/assessment/question/programming_codaveri/c_sharp/c_sharp_package_service.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Course::Assessment::Question::ProgrammingCodaveri::CSharp::CSharpPackageService < # rubocop:disable Metrics/ClassLength +class Course::Assessment::Question::ProgrammingCodaveri::CSharp::CSharpPackageService < Course::Assessment::Question::ProgrammingCodaveri::LanguagePackageService def process_solutions extract_main_solution @@ -99,7 +99,7 @@ def extract_supporting_solution_files # Extracts test cases from the built dummy reports and append all the test cases to the # [:IOTestcases] array for the problem management API request body. - def extract_test_cases # rubocop:disable Metrics/AbcSize + def extract_test_cases test_cases_with_id = preload_question_test_cases @package.test_reports.each do |test_type, test_report| Course::Assessment::ProgrammingTestCaseReport.new(test_report).test_cases.each do |test_case| diff --git a/app/services/course/assessment/question/programming_codaveri/go/go_package_service.rb b/app/services/course/assessment/question/programming_codaveri/go/go_package_service.rb index aadc11cf9e..475e2124ef 100644 --- a/app/services/course/assessment/question/programming_codaveri/go/go_package_service.rb +++ b/app/services/course/assessment/question/programming_codaveri/go/go_package_service.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Course::Assessment::Question::ProgrammingCodaveri::Go::GoPackageService < # rubocop:disable Metrics/ClassLength +class Course::Assessment::Question::ProgrammingCodaveri::Go::GoPackageService < Course::Assessment::Question::ProgrammingCodaveri::LanguagePackageService def process_solutions extract_main_solution @@ -99,7 +99,7 @@ def extract_supporting_solution_files # Extracts test cases from the built dummy reports and append all the test cases to the # [:IOTestcases] array for the problem management API request body. - def extract_test_cases # rubocop:disable Metrics/AbcSize + def extract_test_cases test_cases_with_id = preload_question_test_cases @package.test_reports.each do |test_type, test_report| Course::Assessment::ProgrammingTestCaseReport.new(test_report).test_cases.each do |test_case| diff --git a/app/services/course/assessment/question/programming_codaveri/java_script/java_script_package_service.rb b/app/services/course/assessment/question/programming_codaveri/java_script/java_script_package_service.rb index 1293ead181..9fab80471e 100644 --- a/app/services/course/assessment/question/programming_codaveri/java_script/java_script_package_service.rb +++ b/app/services/course/assessment/question/programming_codaveri/java_script/java_script_package_service.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Course::Assessment::Question::ProgrammingCodaveri::JavaScript::JavaScriptPackageService < # rubocop:disable Metrics/ClassLength +class Course::Assessment::Question::ProgrammingCodaveri::JavaScript::JavaScriptPackageService < Course::Assessment::Question::ProgrammingCodaveri::LanguagePackageService def process_solutions extract_main_solution @@ -99,7 +99,7 @@ def extract_supporting_solution_files # Extracts test cases from the built dummy reports and append all the test cases to the # [:IOTestcases] array for the problem management API request body. - def extract_test_cases # rubocop:disable Metrics/AbcSize + def extract_test_cases test_cases_with_id = preload_question_test_cases @package.test_reports.each do |test_type, test_report| Course::Assessment::ProgrammingTestCaseReport.new(test_report).test_cases.each do |test_case| diff --git a/app/services/course/assessment/question/programming_codaveri/r/r_package_service.rb b/app/services/course/assessment/question/programming_codaveri/r/r_package_service.rb index fc41378b9d..1880ac480a 100644 --- a/app/services/course/assessment/question/programming_codaveri/r/r_package_service.rb +++ b/app/services/course/assessment/question/programming_codaveri/r/r_package_service.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Course::Assessment::Question::ProgrammingCodaveri::R::RPackageService < # rubocop:disable Metrics/ClassLength +class Course::Assessment::Question::ProgrammingCodaveri::R::RPackageService < Course::Assessment::Question::ProgrammingCodaveri::LanguagePackageService def process_solutions extract_main_solution @@ -99,7 +99,7 @@ def extract_supporting_solution_files # Extracts test cases from the built dummy reports and append all the test cases to the # [:IOTestcases] array for the problem management API request body. - def extract_test_cases # rubocop:disable Metrics/AbcSize + def extract_test_cases test_cases_with_id = preload_question_test_cases @package.test_reports.each do |test_type, test_report| Course::Assessment::ProgrammingTestCaseReport.new(test_report).test_cases.each do |test_case| diff --git a/app/services/course/assessment/question/programming_codaveri/rust/rust_package_service.rb b/app/services/course/assessment/question/programming_codaveri/rust/rust_package_service.rb index eae0a8cf35..7e4f1ae77b 100644 --- a/app/services/course/assessment/question/programming_codaveri/rust/rust_package_service.rb +++ b/app/services/course/assessment/question/programming_codaveri/rust/rust_package_service.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Course::Assessment::Question::ProgrammingCodaveri::Rust::RustPackageService < # rubocop:disable Metrics/ClassLength +class Course::Assessment::Question::ProgrammingCodaveri::Rust::RustPackageService < Course::Assessment::Question::ProgrammingCodaveri::LanguagePackageService def process_solutions extract_main_solution @@ -99,7 +99,7 @@ def extract_supporting_solution_files # Extracts test cases from the built dummy reports and append all the test cases to the # [:IOTestcases] array for the problem management API request body. - def extract_test_cases # rubocop:disable Metrics/AbcSize + def extract_test_cases test_cases_with_id = preload_question_test_cases @package.test_reports.each do |test_type, test_report| Course::Assessment::ProgrammingTestCaseReport.new(test_report).test_cases.each do |test_case| diff --git a/app/services/course/assessment/question/programming_codaveri/type_script/type_script_package_service.rb b/app/services/course/assessment/question/programming_codaveri/type_script/type_script_package_service.rb index 0a54601c22..62e265ffa9 100644 --- a/app/services/course/assessment/question/programming_codaveri/type_script/type_script_package_service.rb +++ b/app/services/course/assessment/question/programming_codaveri/type_script/type_script_package_service.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Course::Assessment::Question::ProgrammingCodaveri::TypeScript::TypeScriptPackageService < # rubocop:disable Metrics/ClassLength +class Course::Assessment::Question::ProgrammingCodaveri::TypeScript::TypeScriptPackageService < Course::Assessment::Question::ProgrammingCodaveri::LanguagePackageService def process_solutions extract_main_solution @@ -99,7 +99,7 @@ def extract_supporting_solution_files # Extracts test cases from the built dummy reports and append all the test cases to the # [:IOTestcases] array for the problem management API request body. - def extract_test_cases # rubocop:disable Metrics/AbcSize + def extract_test_cases test_cases_with_id = preload_question_test_cases @package.test_reports.each do |test_type, test_report| Course::Assessment::ProgrammingTestCaseReport.new(test_report).test_cases.each do |test_case| diff --git a/app/services/course/assessment/submission/csv_download_service.rb b/app/services/course/assessment/submission/csv_download_service.rb index 3407367e33..d2bb3e964d 100644 --- a/app/services/course/assessment/submission/csv_download_service.rb +++ b/app/services/course/assessment/submission/csv_download_service.rb @@ -75,7 +75,7 @@ def submissions_csv_header(csv) I18n.t('csv.assessment_submissions.headers.status')] end - def submissions_csv_row(csv, submission, course_user) # rubocop:disable Metrics/AbcSize + def submissions_csv_row(csv, submission, course_user) row_array = [course_user.name, course_user.user.email, course_user.role, diff --git a/app/services/course/assessment/submission/ssid_plagiarism_service.rb b/app/services/course/assessment/submission/ssid_plagiarism_service.rb index 7b3a3f2ee5..93f12009b7 100644 --- a/app/services/course/assessment/submission/ssid_plagiarism_service.rb +++ b/app/services/course/assessment/submission/ssid_plagiarism_service.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Course::Assessment::Submission::SsidPlagiarismService # rubocop:disable Metrics/ClassLength +class Course::Assessment::Submission::SsidPlagiarismService include Course::SsidFolderConcern POLL_INTERVAL_SECONDS = 2 diff --git a/app/services/course/assessment/submission/update_service.rb b/app/services/course/assessment/submission/update_service.rb index 7db382b251..1e3fd06d32 100644 --- a/app/services/course/assessment/submission/update_service.rb +++ b/app/services/course/assessment/submission/update_service.rb @@ -98,7 +98,7 @@ def questions_to_attempt @questions_to_attempt ||= @submission.questions end - def update_submission # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity, Metrics/MethodLength + def update_submission @submission.class.transaction do unless unsubmit? || unmark? update_answers_params&.each do |answer_params| diff --git a/app/services/course/survey/reminder_service.rb b/app/services/course/survey/reminder_service.rb index d91cc66713..600a72ed00 100644 --- a/app/services/course/survey/reminder_service.rb +++ b/app/services/course/survey/reminder_service.rb @@ -59,7 +59,6 @@ def closing_reminder_staff(survey, students) # If empty, all students will be selected. # @param [Boolean] include_unsubscribed Whether to include unsubscribed students in the reminder (forced reminder). # @return [Set] Set of CourseUsers who have not finished the survey. - # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity def uncompleted_subscribed_students(survey, course_user_ids, include_unsubscribed) course_users = survey.course.course_users course_users = course_users.where(id: course_user_ids) unless course_user_ids.empty? @@ -82,5 +81,4 @@ def uncompleted_subscribed_students(survey, course_user_ids, include_unsubscribe where('course_user_email_unsubscriptions.course_settings_email_id = ?', email_enabled.id) Set.new(students) - Set.new(unsubscribed) - Set.new(submitted) end - # rubocop:enable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity end diff --git a/app/services/course/video/reminder_service.rb b/app/services/course/video/reminder_service.rb index e77e693f38..7b75b2dd81 100644 --- a/app/services/course/video/reminder_service.rb +++ b/app/services/course/video/reminder_service.rb @@ -16,7 +16,6 @@ def closing_reminder(video, token) private - # rubocop:disable Metrics/AbcSize def unattempted_subscribed_students(video, email_enabled) course_users = video.course.course_users students = if email_enabled.regular && email_enabled.phantom @@ -34,5 +33,4 @@ def unattempted_subscribed_students(video, email_enabled) Set.new(students) - Set.new(submitted) - Set.new(unsubscribed) end - # rubocop:enable Metrics/AbcSize end diff --git a/lib/autoload/course/assessment/programming_test_case_report_builder.rb b/lib/autoload/course/assessment/programming_test_case_report_builder.rb index 6538d5c09c..2d9f91e548 100644 --- a/lib/autoload/course/assessment/programming_test_case_report_builder.rb +++ b/lib/autoload/course/assessment/programming_test_case_report_builder.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -# rubocop:disable Metrics/AbcSize class Course::Assessment::ProgrammingTestCaseReportBuilder def self.build_dummy_report(test_type, test_cases, file_type) builder = Nokogiri::XML::Builder.new do |xml| @@ -33,4 +32,3 @@ def self.build_dummy_report(test_type, test_cases, file_type) builder.to_xml end end -# rubocop:enable Metrics/AbcSize diff --git a/lib/autoload/duplicator.rb b/lib/autoload/duplicator.rb index 8b49bb39e5..632af816bc 100644 --- a/lib/autoload/duplicator.rb +++ b/lib/autoload/duplicator.rb @@ -89,7 +89,7 @@ def map_item_or_collection(item_or_collection, &block) # # @param [#initialize_duplicate] source_object The object to be duplicated. # @return duplicated_object A reference to the duplicated object. - def duplicate_object(source_object) # rubocop:disable Metrics/AbcSize + def duplicate_object(source_object) return nil unless source_object @duplicated_objects.fetch(source_object) do |key| diff --git a/lib/extensions/attachable/active_record/base.rb b/lib/extensions/attachable/active_record/base.rb index 395c1eb9b5..0cf35869b1 100644 --- a/lib/extensions/attachable/active_record/base.rb +++ b/lib/extensions/attachable/active_record/base.rb @@ -51,7 +51,7 @@ module ClassMethods # associated with the attachments. Updating description will result in attachments changing. # # To change the provided logic, you can override `description_attachment_references_changes`. - def has_many_attachments(options = {}) # rubocop:disable Naming/PredicateName + def has_many_attachments(options = {}) include HasManyAttachments return unless options[:on] @@ -62,7 +62,7 @@ def has_many_attachments(options = {}) # rubocop:disable Naming/PredicateName HasManyAttachments.define_attachment_references_readers(attachable_columns) end - def has_one_attachment # rubocop:disable Naming/PredicateName + def has_one_attachment include HasOneAttachment end end diff --git a/lib/extensions/materials/active_record/base.rb b/lib/extensions/materials/active_record/base.rb index 7cc494ef4a..44d72d2dd4 100644 --- a/lib/extensions/materials/active_record/base.rb +++ b/lib/extensions/materials/active_record/base.rb @@ -2,7 +2,7 @@ module Extensions::Materials::ActiveRecord::Base module ClassMethods # Declare this to allow models to support materials uploads. - def has_one_folder # rubocop:disable Naming/PredicateName + def has_one_folder after_initialize :build_new_record_folder, if: :new_record? has_one :folder, as: :owner, class_name: 'Course::Material::Folder', diff --git a/lib/tasks/db/add_missing_email_settings.rake b/lib/tasks/db/add_missing_email_settings.rake index f6bc3876fa..d68a3699a1 100644 --- a/lib/tasks/db/add_missing_email_settings.rake +++ b/lib/tasks/db/add_missing_email_settings.rake @@ -24,7 +24,7 @@ namespace :db do end # Non-assessment - def create_default_email_settings # rubocop:disable Metrics/MethodLength + def create_default_email_settings course_with_email_settings = Course.includes(:setting_emails). joins("LEFT JOIN course_settings_emails \ ON course_settings_emails.course_id = courses.id \ diff --git a/spec/controllers/course/assessment_marketplace_component_spec.rb b/spec/controllers/course/assessment_marketplace_component_spec.rb index 78cd6db53f..14d7ff0696 100644 --- a/spec/controllers/course/assessment_marketplace_component_spec.rb +++ b/spec/controllers/course/assessment_marketplace_component_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' RSpec.describe Course::AssessmentMarketplaceComponent do - controller(Course::Controller) {} # rubocop:disable Lint/EmptyBlock + controller(Course::Controller) {} let!(:instance) { Instance.default } with_tenant(:instance) do diff --git a/spec/controllers/course/forum/forums_controller_spec.rb b/spec/controllers/course/forum/forums_controller_spec.rb index b7e82a9f6b..38400d22fb 100644 --- a/spec/controllers/course/forum/forums_controller_spec.rb +++ b/spec/controllers/course/forum/forums_controller_spec.rb @@ -128,7 +128,7 @@ def check_forum(received_forum_post_pack, expected_forum) end # Helper method to check that post pack content is expected - def check_post_pack(received_post_pack, expected_forum, expected_topic, expected_post, expected_parent = nil) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize + def check_post_pack(received_post_pack, expected_forum, expected_topic, expected_post, expected_parent = nil) expect(received_post_pack['corePost']['id']).to eq(expected_post.id) expect(received_post_pack['corePost']['text']).to eq(expected_post.text) expect(received_post_pack['corePost']['creatorId']).to eq(expected_post.creator.id) diff --git a/spec/factories/course_assessment_question_voice_responses.rb b/spec/factories/course_assessment_question_voice_responses.rb index bb8f22719c..e83e036e6c 100644 --- a/spec/factories/course_assessment_question_voice_responses.rb +++ b/spec/factories/course_assessment_question_voice_responses.rb @@ -1,9 +1,7 @@ # frozen_string_literal: true -# rubocop:disable Lint/EmptyBlock FactoryBot.define do factory :course_assessment_question_voice_response, class: Course::Assessment::Question::VoiceResponse, parent: :course_assessment_question do end end -# rubocop:enable Lint/EmptyBlock diff --git a/spec/support/devise.rb b/spec/support/devise.rb index 454605c8d4..16b8e6ccc3 100644 --- a/spec/support/devise.rb +++ b/spec/support/devise.rb @@ -4,7 +4,7 @@ module DeviseControllerMacros # # @param [nil] as if there should not be a user to be logged in. # @param [Symbol] as if there is a user that should be created by the factory with this name. - def requires_login(as: nil) # rubocop:disable Naming/MethodParameterName + def requires_login(as: nil) before do @request.env['devise.mapping'] = Devise.mappings[:user] sign_in FactoryBot.create(as) if as diff --git a/spec/support/reference_timelines_helper.rb b/spec/support/reference_timelines_helper.rb index 1286fd1575..8a966b4b8b 100644 --- a/spec/support/reference_timelines_helper.rb +++ b/spec/support/reference_timelines_helper.rb @@ -13,7 +13,6 @@ module ReferenceTimelinesTestHelper # @param time_shift [ActiveSupport::Duration] number of days expected to be between the times in both timelines # @return [Boolean] `true` if both timelines are similar to each other # - # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity def similar_timelines?(timeline1, timeline2, time_shift = 0.day) return false unless timeline1.title == timeline2.title @@ -32,7 +31,6 @@ def similar_timelines?(timeline1, timeline2, time_shift = 0.day) true end - # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity private diff --git a/spec/support/stubs/codaveri/evaluate_api_stubs.rb b/spec/support/stubs/codaveri/evaluate_api_stubs.rb index 345a4a1315..716a1f2643 100644 --- a/spec/support/stubs/codaveri/evaluate_api_stubs.rb +++ b/spec/support/stubs/codaveri/evaluate_api_stubs.rb @@ -1,4 +1,3 @@ -# rubocop: disable Metrics/ModuleLength # frozen_string_literal: true module Codaveri::EvaluateApiStubs def evaluate_success_final_result @@ -391,4 +390,3 @@ def test_cases_id_from_factory :evaluate_wrong_answer_final_result, :test_cases_id_from_factory end -# rubocop: enable Metrics/ModuleLength diff --git a/spec/support/stubs/langchain/llm_stubs.rb b/spec/support/stubs/langchain/llm_stubs.rb index 18e92991cc..5a914ca047 100644 --- a/spec/support/stubs/langchain/llm_stubs.rb +++ b/spec/support/stubs/langchain/llm_stubs.rb @@ -9,7 +9,7 @@ def initialize(completion) end class OpenAiStub < Langchain::LLM::Base - def chat(messages: [], **_kwargs) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity + def chat(messages: [], **_kwargs) system_message = messages.find { |msg| msg[:role] == 'system' }&.dig(:content) || '' user_message = messages.find { |msg| msg[:role] == 'user' }&.dig(:content) || '' diff --git a/spec/support/stubs/ssid/api_stubs.rb b/spec/support/stubs/ssid/api_stubs.rb index 89f48c9ea8..49032c6258 100644 --- a/spec/support/stubs/ssid/api_stubs.rb +++ b/spec/support/stubs/ssid/api_stubs.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -module Ssid::ApiStubs # rubocop:disable Metrics/ModuleLength +module Ssid::ApiStubs CREATE_FOLDER_SUCCESS = { status: 200, body: {