Di chuyển đường ray cho bảng tham gia has_and_belongs_to_many


Câu trả lời:


228

Ở đâu:

class Teacher < ActiveRecord::Base
  has_and_belongs_to_many :students
end

class Student < ActiveRecord::Base
  has_and_belongs_to_many :teachers
end

cho đường ray 4:

rails generate migration CreateJoinTableStudentTeacher student teacher

cho đường ray 3:

rails generate migration students_teachers student_id:integer teacher_id:integer

cho đường ray <3

script/generate migration students_teachers student_id:integer teacher_id:integer

(lưu ý tên bảng liệt kê cả hai bảng tham gia theo thứ tự bảng chữ cái)

và sau đó chỉ dành cho đường ray 3 trở xuống, bạn cần chỉnh sửa di chuyển đã tạo để trường id không được tạo:

create_table :students_teachers, :id => false do |t|

16
Đây là câu trả lời duy nhất thực sự trả lời câu hỏi.
pingu

8
@pingu: ngoại trừ việc nó không hoạt động, ít nhất là trong Rails 3.2. Tệp di chuyển được tạo trống.
hoffmanc

7
Hoạt động cho Rails 4.
Felipe Zavan

2
@hoffmanc Nó sẽ tạo một tệp di chuyển trống nếu bạn không chỉ định bất kỳ trường nào. Bạn phải chỉ định các trường nếu bạn muốn Rails tự động thêm chúng vào tệp di chuyển.
Andrew

1
xin chào, tôi đang cố gắng rails generate migration CreateJoinTableTeacherStudent teacher studentthay vì rails generate migration CreateJoinTableStudentTeacher student teachernhư vậy? S (tudent) có cần trước T (mỗi người) không?
zx1986

138

Một has_and_belongs_to_manybảng phải phù hợp với định dạng này. Tôi giả sử hai mô hình được tham gia has_and_belongs_to_manyđã có trong DB: applesoranges:

create_table :apples_oranges, :id => false do |t|
  t.references :apple, :null => false
  t.references :orange, :null => false
end

# Adding the index can massively speed up join tables. Don't use the
# unique if you allow duplicates.
add_index(:apples_oranges, [:apple_id, :orange_id], :unique => true)

Nếu bạn sử dụng :unique => truechỉ mục trên, thì bạn nên (trong rails3) chuyển :uniq => trueđến has_and_belongs_to_many.

Thêm thông tin: Tài liệu Rails

CẬP NHẬT 2010-12-13 Tôi đã cập nhật nó để xóa id và dấu thời gian ... Về cơ bản MattDiPasqualenunopoloniachính xác: Không được có id và không được có dấu thời gian hoặc đường ray sẽ không cho phép has_and_belongs_to_manyhoạt động.


6
Trên thực tế, một bảng tham gia chỉ nên có hai cột tham chiếu và không có cột id hoặc dấu thời gian. Dưới đây là một ví dụ tốt hơn về di chuyển has_and_belongs_to_many từ liên kết bạn đã đưa ra. Tôi đang tìm cách để thực hiện nó từ dòng lệnh với script/generate migration...
ma11hew28

Chà, nó không cần phải có dấu thời gian; Tôi đã đánh dấu nó tùy chọn trong ví dụ của tôi. Tôi sẽ khuyên bạn nên thêm id, mặc dù. Có những trường hợp ID hoặc dấu thời gian có thể hữu ích. Nhưng tôi thực sự khuyên bạn nên ID.
docwhat

Đồng ý. Trường hợp ID sẽ hữu ích là gì?
ma11hew28

Một ví dụ là nếu mối quan hệ đủ quan trọng để có quan điểm. Nó cũng có thể được sử dụng để tăng tốc độ truy cập các cơ sở dữ liệu bằng cách chuyển qua mối quan hệ. Thay vì tìm kiếm nó nhiều lần. Nó cũng làm cho việc xử lý sự cố cơ sở dữ liệu dễ dàng hơn. Đặc biệt là nếu id của các cột khác thực sự cao. Việc nhớ id dễ dàng hơn: 12345 thay vì id: 54321-id: 67890 - Nhưng có thể nói, nếu bảng thực sự lớn thì bạn có thể muốn tiết kiệm dung lượng bằng cách không phân bổ id khác cho mỗi mối quan hệ.
docwhat

2
Tôi không nghĩ rằng chỉ số nhiều màu là giải pháp phù hợp cho việc này. Nó sẽ hoạt động cho các truy vấn cho các quả táo cụ thể để tìm các quả cam có liên quan nhưng không phải là cách khác. Hai chỉ mục cột đơn sẽ cho phép cả hai hướng được truy vấn một cách hiệu quả có thể ở một tổn thất nhỏ đối với kiểm tra sự tồn tại của một kết hợp táo, cam cụ thể).
Joseph Lord

14

Bạn nên đặt tên cho bảng là tên của 2 mô hình bạn muốn kết nối theo thứ tự bảng chữ cái và đặt hai id của mô hình vào bảng. Sau đó kết nối từng mô hình với nhau tạo ra các liên kết trong mô hình.

Đây là một ví dụ:

# in migration
def self.up
  create_table 'categories_products', :id => false do |t|
    t.column :category_id, :integer
    t.column :product_id, :integer
  end
end

# models/product.rb
has_and_belongs_to_many :categories

# models/category.rb
has_and_belongs_to_many :products

Nhưng điều này không linh hoạt lắm và bạn nên nghĩ về việc sử dụng has_many: thông qua


6

Câu trả lời trên cùng cho thấy một chỉ số tổng hợp mà tôi không tin sẽ được sử dụng để tra cứu táo từ cam.

create_table :apples_oranges, :id => false do |t|
  t.references :apple, :null => false
  t.references :orange, :null => false
end

# Adding the index can massively speed up join tables.
# This enforces uniqueness and speeds up apple->oranges lookups.
add_index(:apples_oranges, [:apple_id, :orange_id], :unique => true)
# This speeds up orange->apple lookups
add_index(:apples_oranges, :orange_id)

Tôi đã tìm thấy câu trả lời này dựa trên 'The Doctor What' hữu ích và cuộc thảo luận chắc chắn cũng vậy.


4

Trong rails 4, bạn có thể sử dụng đơn giản

created_join_table: table1s ,: table2s

nó là tất cả

Chú ý: bạn phải tắt bảng1, bảng2 bằng chữ và số.


đây là một giải pháp cập nhật tốt Lưu ý, bảng tham gia không thể truy cập dưới dạng mô hình, nhưng thông qua quan hệ has_and_belongs_to_many được thiết lập trên cả hai bảng đã tham gia.
Trang web Taylored

1

Tôi thích làm:

rails g migration CreateJoinedTable model1:references model2:references. Bằng cách đó tôi có được một di chuyển trông như thế này:

class CreateJoinedTable < ActiveRecord::Migration
  def change
    create_table :joined_tables do |t|
      t.references :trip, index: true
      t.references :category, index: true
    end
    add_foreign_key :joined_tables, :trips
    add_foreign_key :joined_tables, :categories
  end
end

Tôi thích có chỉ mục trên các cột này vì tôi thường thực hiện tra cứu bằng các cột này.


add_foreign_keysẽ thất bại nếu được đặt trong cùng di chuyển với di chuyển đã tạo các bảng.
Adib Saad
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.