我有User
和Course
之间的关系(典型的注册数据)。 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
设为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
类型,并且仍然可以执行{{1}等活动记录查询}和User.courses
?
答案 0 :(得分:6)
尝试在注册模型中指定外键和主键,例如
belongs_to :user foreign_key: :user_id, primary_key: :g_number