Di chuyển đường ray: t.references với tên thay thế?


121

Vì vậy, tôi có một create_table như thế này cho các Khóa học tại một trường học:

create_table :courses do |t|
  t.string :name
  t.references :course
  t.timestamps
end

nhưng tôi muốn nó tham chiếu đến hai khóa học khác như:

has_many :transferrable_as # A Course
has_many :same_as          # Another Course

Tôi có thể nói như sau không?

t.references :transferrable_as, :as=> :course

Câu trả lời:


161

Bạn có thể thực hiện tất cả điều này trong định nghĩa cột / di chuyển ban đầu (ít nhất là hiện tại trong Rails 5):

t.references :transferable_as, index: true, foreign_key: {to_table: :courses}
t.references :same_as, index: true, foreign_key: {to_table: :courses}

10
Điều này hoạt động trên Rails 5.1 và không có đề xuất nào khác làm được. Nó sạch hơn nhiều và cảm thấy đúng.
stephenmurdoch

2
Tôi sử dụng Rails 5.1.4 nhưng nó không hoạt động. Khi tôi chỉ định một foreign_keytùy chọn trong việc tạo bảng như thế này, nó gây ra lỗi nói rằng chính bảng tôi đang tạo không tồn tại ... Vì vậy, tôi nghi ngờ nó không thực sự được API chính thức hỗ trợ.
Quv

3
Tôi cũng đọc rằng indexnó đã được thêm vào khóa ngoại kể từ Rails stackoverflow.com/questions/39769981/…
Jonathan Reyes,

98

Bạn có thể làm theo cách này:

create_table :courses do |t|
  t.string :name
  t.references :transferrable_as
  t.references :same_as
  t.timestamps
end

hoặc sử dụng t.belongs_to làm bí danh chot.references

Bạn không thể thêm foreign_key: truevào hai dòng tham chiếu đó. Nếu bạn muốn đánh dấu chúng là khóa ngoại ở cấp cơ sở dữ liệu, bạn cần phải di chuyển với điều này:

add_foreign_key :courses, :courses, column: :transferrable_as_id
add_foreign_key :courses, :courses, column: :same_as_id

Cập nhật

Trong Rails 5.1 trở lên, bạn có thể thêm khóa ngoại khi di chuyển trong create_tablekhối như sau:

create_table :courses do |t|
  t.string :name
  t.references :transferrable_as, foreign_key: { to_table: 'courses' }
  t.references :same_as, foreign_key: { to_table: 'courses' }
  t.timestamps
end

5
Phần về việc không thể thêm foreign_key: truevào các dòng tham chiếu là điều đã khiến tôi vấp phải. Thêm add_foreign_keyvà chỉ định tên cột cho những người đã thực hiện thủ thuật.
Matthew Clark

Điều này có hoạt động ngoài hộp trong Rails không? Theo stackoverflow.com/a/22384289/239657 , điều này yêu cầu schema_plusđá quý. Các tài liệu add_reference của Rails không đề cập đến các tùy chọn: reference.
Beni Cherniavsky-Paskin

1
Tôi không theo dõi references:tùy chọn này để làm gì (trái ngược với điều t.referencesđó sẽ không chỉ phù hợp ở cấp độ mô hình, với các cân nhắc về Foreign_key đang được quan tâm add_foreign_key?
MCB

1
@MCB t.referencesnói "thêm một trường vào bảng này là khóa chính của bảng khác". Các references:tùy chọn cho nó mà bảng đó là một khóa chính của (cần thiết nếu nó không được rõ ràng bởi tên của trường). Các add_foreign_keychức năng bảo cơ sở dữ liệu để thực thi toàn vẹn tham chiếu ở đây.
Toby 1 Kenobi

2
@MCB sau ngần ấy thời gian, tôi nhận ra rằng bạn đã đúng. Nhận xét đầu tiên của bạn ở trên là hoàn toàn đúng - các add_foreign_keydòng lưu ý đến việc thông báo cho cơ sở dữ liệu khóa ngoại của cái gì. Các references:tham số được làm gì cả.
Toby 1 Kenobi

13

Tôi nghĩ chủ đề này có một cách Rails-ish khác: Scaffolding ActiveRecord: hai cột có cùng kiểu dữ liệu

Trong quá trình di chuyển:

t.belongs_to: transferrable_as

t.belongs_to: same_as


1
nhưng làm thế nào để db biết khóa ngoại nào để liên kết bảng? Tôi đang thử điều này với cơ sở dữ liệu Postgres và nó cho tôi một lỗi PG::UndefinedTable: ERRORlà đang cố thêm ràng buộc khóa ngoại vào một bảng không tồn tại.
Toby 1 Kenobi

Trong trường hợp bất cứ ai đang tự hỏi, belongs_tochỉ là một bí danh để referencesvà do đó, có các chức năng chính xác tương tự.
Jason Swett

11

Như một câu trả lời bổ sung cho câu hỏi này - Mô hình phải có dòng sau để hoàn thành liên kết:

    belongs_to :transferrable_as, class_name: "Course"
    belongs_to :same_as, class_name: "Course"

3

Tôi không nghĩ là referenceschấp nhận :astùy chọn, nhưng bạn có thể tạo các cột của mình theo cách thủ công ...

create_table :courses do |t| 
  t.string  :name 
  t.integer :course1_id
  t.integer :course2_id 
  t.timestamps 
end 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.