У меня есть связь между User
и Course
(типичные данные о зачислении). A User
has_many
Course
и наоборот (типичный сценарий JOIN
таблицы).
Я пытаюсь перенести свои предыдущие отношения has_and_belongs_to_many
между этими двумя моделями на отношения has_many :through
. Мои файлы сейчас выглядят так:
class User < ActiveRecord::Base
has_and_belongs_to_many :courses
end
а также
class Course < ActiveRecord::Base
has_and_belongs_to_many :users
end
а имя таблицы, объединяющей две модели, - courses_users
.
Теперь мне нужно перенести это отношение на ассоциацию has_many :through
, а также сделать тип столбца user_id
a string
, поскольку я хочу использовать атрибут g_number
(строка) User
в качестве внешнего ключа. Примечание. Меня не волнует разница в производительности между int
и varchar/string
.
Краткая и простая проблема заключается в том, что мне нужно users.g_number
ссылаться на enrollments.user_id
как на внешний ключ, и оба являются строками.
Моя попытка миграции и доработки модели такова:
class User < ActiveRecord::Base
has_many :enrollment
has_many :courses, :through => :enrollment
end
а также
class Course < ActiveRecord::Base
has_many :enrollment
has_many :users, :through => :enrollment
end
наконец
class Enrollment < ActiveRecord::Base
belongs_to :course
belongs_to :user
end
затем миграция
class ChangeUserIdJoin < ActiveRecord::Migration
def self.up
rename_table :courses_users, :enrollments
end
def self.down
rename_table :enrollments, :courses_users
end
end
Здесь все работает нормально. Я могу выполнять такие запросы, как User.courses
и Course.users
. Но теперь я хочу изменить тип столбца user_id
в таблице соединений на string
, чтобы я мог сохранить g_number
(строковый атрибут на User
) и присоединиться к этому вместо последовательного столбца id
в User
.
Когда я пытаюсь изменить тип столбца user_id
на string
в миграции:
class ChangeUserIdJoin < ActiveRecord::Migration
def self.up
change_column :courses_users, :user_id, :string
rename_table :courses_users, :enrollments
end
def self.down
rename_table :enrollments, :courses_users
change_column :courses_users, :user_id, :integer
end
end
запросы Course.users
и User.courses
начинают терпеть неудачу (ниже из консоли Rails). User.courses
возвращает пустой массив (тогда как раньше было несколько объектов Course
), а Course.users
выдает исключение из-за несовпадения типов столбцов (что, очевидно, имеет смысл):
u = User.take
User Load (0.9ms) SELECT "users".* FROM "users" LIMIT 1
=> #<User id: 1, username: "director", g_number: "g00000000", password_digest: "$2a$10$dvcOd3rHfbcR1Rn/D6VhsOokj4XiIkQbHxXLYjy5s4f...", created_at: "2016-01-06 01:36:00", updated_at: "2016-01-06 01:36:00", first_name: "Director", last_name: "", role: 0, registered: true>
2.1.5 :002 > u.courses
Course Load (0.9ms) SELECT "courses".* FROM "courses" INNER JOIN "enrollments ON "courses"."id" = "enrollments"."course_id" WHERE "enrollments"."user_id" = $1 [["user_id", 1]]
=> #<ActiveRecord::Associations::CollectionProxy []>
2.1.5 :003 > c = Course.take
Course Load (0.7ms) SELECT "courses".* FROM "courses" LIMIT 1
=> #<Course id: 12754, year: 2015, semester: 0, department: 7, course: 101, section: 1, name: "SPA 101 01 - Elementary Spanish I">
2.1.5 :004 > c.users
PG::UndefinedFunction: ERROR: operator does not exist: integer = character varying
LINE 1: ... "users" INNER JOIN "enrollments" ON "users"."id" = "enrollm...
Мне нужно присоединиться к enrollments.user_id = users.g_number
. Что мне нужно сделать, чтобы изменить столбец user_id
на тип string
в модели / таблице Enrollment
и по-прежнему иметь возможность выполнять запросы Active Record, такие как User.courses
и Course.users
?