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)
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.