【问题标题】:Rails string as a foreign keyRails 字符串作为外键
【发布时间】:2016-04-10 00:40:27
【问题描述】:

我在UserCourse 之间有关系(典型的注册数据)。 Userhas_manyCourse 反之亦然(典型的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,因为我想使用Userg_number(字符串)属性作为外键。 注意:我不关心intvarchar/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.coursesCourse.users。但是现在我想将连接表中user_id 列的类型更改为string,以便我可以存储g_numberUser 上的字符串属性)并加入 that 而不是User 的串行id 列。

当我尝试在迁移中将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.usersUser.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。我需要做什么才能将Enrollment 模型/表中的user_id 列更改为string 类型,并且仍然能够执行诸如User.coursesCourse.users 之类的Active Record 查询?

【问题讨论】:

    标签: ruby-on-rails activerecord database-migration


    【解决方案1】:

    尝试在注册模型中指定外键和主键,像这样

    belongs_to :user foreign_key: :user_id, primary_key: :g_number
    

    【讨论】:

    • 你是一个救生员。我已经为此工作了大约 6 个小时,试图找出它们之间的正确关系!为了使反向查询正常工作 (Course.users),我还需要在 User 模型中添加 has_many :enrollment, foreign_key: :user_id, primary_key: :g_number
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-04
    • 2012-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-16
    • 1970-01-01
    相关资源
    最近更新 更多