Search code examples
ruby-on-railsrubyactiverecordruby-on-rails-7

Rails Exception No Such Table Exists


I used rails generate to scaffold a ProjectType table and a ProjectGroup table that references project type. I created a project type successfully through the browser, but when trying to create the project group I get an error: Input: Name: asdf Projecttype: 1 Raises: ActiveRecord::StatementInvalid in ProjectGroupsController#create SQLite3::SQLException: no such table: main.ProjectTypes

However when I check the irb after getting that error I have:

irb(main):001> ProjectType.all   
ProjectType Load (0.1ms)  SELECT "project_types".* FROM "project_types" /* loading for pp */ LIMIT ?  [["LIMIT", 11]] 
=> [#<ProjectType:0x000000011f7977f8 id: 1, name: "1", created_at: Sat, 01 Jun 2024 02:51:48.921453000 UTC +00:00, updated_at: Sat, 01 Jun 2024 02:51:48.921453000 UTC +00:00>]

This would indicate to me that there is in-fact the table there.

If I try to create a project group with Projecttype: 2 in the browser I just get a form error saying: 1 error prohibited this project_group from being saved: Projecttype must exist

But it doesn't break the page.

I would appreciate any direction on solving this. Its also affecting my fixtures on data load I'm getting errors on my PRAGMA foreign_key_check for project groups and project types.

my schema:

create_table "project_groups", force: :cascade do |t|
t.string "name"
t.integer "ProjectType_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["ProjectType_id"], name: "index_project_groups_on_ProjectType_id"
end
create_table "project_types", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false 
t.datetime "updated_at", null: false
end
add_foreign_key "project_groups", "ProjectTypes"

trying to create in IRB:

irb(main):008> ProjectGroup.new(name:"something", ProjectType_id:1)
=> #<ProjectGroup:0x000000012d995150 id: nil, name: "something", ProjectType_id: 1, created_at: nil, updated_at: nil>
irb(main):009> ProjectGroup.create(name:"something", Project_Type_id:1)
(irb):9:in `<main>': unknown attribute 'Project_Type_id' for ProjectGroup. (ActiveModel::UnknownAttributeError)

          raise UnknownAttributeError.new(self, k.to_s)
          ^^^^^
irb(main):010> ProjectGroup.create(name:"something", ProjectType_id:1)
  TRANSACTION (0.2ms)  begin transaction
  ProjectType Load (0.7ms)  SELECT "project_types".* FROM "project_types" WHERE "project_types"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  ProjectGroup Create (0.4ms)  INSERT INTO "project_groups" ("name", "ProjectType_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) RETURNING "id"  [["name", "something"], ["ProjectType_id", 1], ["created_at", "2024-06-01 03:03:05.944403"], ["updated_at", "2024-06-01 03:03:05.944403"]]
  TRANSACTION (0.1ms)  rollback transaction
(irb):10:in `<main>': SQLite3::SQLException: no such table: main.ProjectTypes (ActiveRecord::StatementInvalid)

Solution

  • The reason you're getting an error is that the table is named project_types not ProjectTypes. On the schema side of things in Rails everything should be lower case.

    To add a foreign key column to a table use the add_reference method:

    class AddProjectTypeToProjectGroups < ActiveRecord::Migration[7.1]
      def change
        add_reference :project_groups, :project_type, 
          null: false, 
          foreign_key: true
      end
    end
    

    Or in the block form with ActiveRecord::ConnectionAdapters::TableDefinition:

    class AddProjectTypeToProjectGroups < ActiveRecord::Migration[7.1]
      def change
        change_table :project_groups do |t|
          t.references :project_type, 
            null: false, 
            foreign_key: true
        end
      end
    end
    

    The second argument should be the snaked cased singular version of the model name. This will name the foreign key column according to rails conventions:

    These fields should be named following the pattern singularized_table_name_id (e.g., item_id, order_id). These are the fields that Active Record will look for when you create associations between your models.

    In this case the column should be named project_type_id.

    In general with Rails you'll have a lot more fun and less anguish if you pay attention to it's naming conventions.