Rails 3 di chuyển: Thêm cột tham chiếu?


162

Nếu tôi tạo một đường ray mới 3 di chuyển với (ví dụ)

rails g migration tester title:tester user:references

, mọi thứ đều hoạt động tốt ... tuy nhiên nếu tôi thêm một cột có nội dung:

rails g migration add_user_to_tester user:references

trường tham chiếu không được công nhận. Nói tóm lại, câu hỏi là: làm thế nào để tôi thêm một cột tham chiếu vào di chuyển đường ray từ dòng lệnh?

Câu trả lời:


205

Nếu bạn đang sử dụng Rails 4.x, bây giờ bạn có thể tạo chuyển đổi với các tham chiếu, như thế này:

rails generate migration AddUserRefToProducts user:references

như bạn có thể thấy trên đường ray



2
Làm thế nào để bạn chỉ định một tên cột cho khóa ngoại thay vì tên được tạo tự động?
j sẽ

@jwill bạn có thể sử dụng đa hình: người dùng: tài liệu tham khảo {đa hình}.
Paulo Fidalgo

@PauloFidalgo Bạn có thể giải thích một chút về cách làm điều đó không? có thể là một số hướng dẫn của các liên kết? (nói về đa hình)
Anwar


186

EDIT : Đây là một câu trả lời lỗi thời và không nên áp dụng cho Rails 4.x +

Bạn không cần thêm tài liệu tham khảo khi bạn có thể sử dụng id số nguyên cho lớp được tham chiếu của mình.

Tôi muốn nói rằng lợi thế của việc sử dụng các tham chiếu thay vì một số nguyên đơn giản là mô hình sẽ được xác định trước với poss_to và vì mô hình đã được tạo và sẽ không bị ảnh hưởng khi bạn di chuyển một cái gì đó hiện có, mục đích bị mất.

Vì vậy, tôi sẽ làm như thế này thay thế:

rails g migration add_user_id_to_tester user_id:integer

Và sau đó thêm thủ công thuộc sở hữu: người dùng trong mô hình Tester


9
Nhưng điều đó sẽ không tạo ra các ràng buộc khóa ngoại thích hợp trên các cơ sở dữ liệu hỗ trợ nó, phải không?
abahgat

19
Không, afaik Rails không bao giờ tạo các hạn chế khóa ngoại trên cơ sở dữ liệu trừ khi bạn thêm các plugin để làm điều đó cho bạn.
DanneManne

chỉ cần nghiên cứu bài đăng này, làm thế nào để tôi thêm tài liệu tham khảo sau tất cả
El nino

13
nhớ thêm chỉ mục với người dùng: số nguyên: chỉ mục
rickypai

3
Câu trả lời là ngày, xem câu trả lời của @ Paulo cho đường ray hiện đại.
OneHoopyFrood 30/03/2015

102

Xin lưu ý rằng rất có thể bạn cũng sẽ cần một chỉ mục trên cột đó.

class AddUserReferenceToTester < ActiveRecord::Migration
  def change
    add_column :testers, :user_id, :integer
    add_index  :testers, :user_id
  end
end

1
Tại sao? Điều này có đúng với hầu hết các mối quan hệ thuộc về?
ahnbizcad

Nó thực sự là vì lý do hiệu suất và có ích nếu bạn có has_many / has_one ở phía bên kia của mối quan hệ thuộc về đó. Nếu bạn hoàn toàn chắc chắn rằng bạn sẽ không trải qua, user.testersbạn có thể bỏ qua chỉ mục.
Eugene

1
Việc rails g migration ...tạo ra add_reference :installs, :device, index: truecũng tạo ra chỉ mục.
B Bảy

49

Với hai bước trước đã nêu ở trên, bạn vẫn còn thiếu ràng buộc khóa ngoại. Điều này sẽ làm việc:

  class AddUserReferenceToTester < ActiveRecord::Migration
      def change
          add_column :testers, :user_id, :integer, references: :users
      end
  end

Đây là câu trả lời thực tế duy nhất ở đây. Khóa ngoại là phần quan trọng nhất ở đây
user2490003

đây nên được đánh dấu là câu trả lời đúng vì các câu hỏi yêu cầu đường ray 3
Carlos Roque

35

Bạn có thể sử dụng tài liệu tham khảo trong một di chuyển thay đổi. Đây là mã Rails 3.2.13 hợp lệ:

class AddUserToTester < ActiveRecord::Migration
  def change
    change_table :testers do |t|
      t.references :user, index: true 
    end
  end
  def down
    change_table :testers do |t|
      t.remove :user_id
    end
  end
end

cf: http://apidock.com/rails/ActiveRecord/ConnectionAd Chap / SchemaStatements / exchange_table


1
thay đổi và phương pháp xuống? không phải là phương pháp lên và xuống thay vào đó?
MaicolBen

@MomsolBen có, và bạn cũng có thể bỏ phương thức xuống.
Hut8

@MomsolBen Không có downphương pháp, tôi đã nhận được ActiveRecord::IrreversibleMigrationkhi quay lại sử dụng Rails 3.2. Tôi cũng phải đổi changesang up.
Andrew Grimm

27

Chạy rails g migration AddUserRefToSponsors user:referencessẽ tạo ra di chuyển sau:

def change
  add_reference :sponsors, :user, index: true
end

Phiên bản này của Rails là gì?
Andrew Grimm

8

Khi thêm một cột, bạn cần làm cho cột đó thành một số nguyên và nếu có thể, hãy gắn với các quy ước đường ray. Vì vậy, đối với trường hợp của bạn, tôi giả sử bạn đã có các mô hình Người kiểm tra và Người dùng, và người kiểm tra và bảng người dùng.

Để thêm khóa ngoại, bạn cần tạo một cột số nguyên với tên user_id (quy ước):

add_column :tester, :user_id, :integer

Sau đó thêm một thuộc tính_to vào mô hình thử nghiệm:

class Tester < ActiveRecord::Base
  belongs_to :user
end

Và bạn cũng có thể muốn thêm một chỉ mục cho khóa ngoại (đây là điều mà các tài liệu tham khảo đã làm cho bạn):

add_index :tester, :user_id

8

Điều đó sẽ làm các thủ thuật:

rails g migration add_user_to_tester user_id:integer:index

Tôi thích điều này cũng thêm chỉ số mà bạn rất có thể sẽ muốn.
bheeshmar

3

Bạn có thể thêm các tham chiếu đến mô hình của mình thông qua dòng lệnh theo cách sau:

rails g migration add_column_to_tester user_id:integer

Điều này sẽ tạo ra một tệp di chuyển như:

class AddColumnToTesters < ActiveRecord::Migration
  def change
    add_column :testers, :user_id, :integer
  end
end

Điều này hoạt động tốt mỗi khi tôi sử dụng nó ..


3

Đối với đường ray 4

Trình tạo chấp nhận loại cột làm tài liệu tham khảo (cũng có sẵn như belongs_to).

Di chuyển này sẽ tạo ra một user_idcột và chỉ mục thích hợp:

$ rails g migration AddUserRefToProducts user:references 

tạo ra:

class AddUserRefToProducts < ActiveRecord::Migration
  def change
    add_reference :products, :user, index: true
  end
end

http://guides.rubyonrails.org/active_record_migations.html#creating-a-standalone-migration

Đối với đường ray 3

Người trợ giúp được gọi là tài liệu tham khảo (cũng có sẵn như belongs_to).

Di chuyển này sẽ tạo ra một category_idcột của loại thích hợp. Lưu ý rằng bạn chuyển tên mô hình, không phải tên cột. Active Record bổ sung _idcho bạn.

change_table :products do |t|
  t.references :category
end

Nếu bạn có các belongs_toliên kết đa hình thì các tham chiếu sẽ thêm cả hai cột cần thiết:

change_table :products do |t|
  t.references :attachment, :polymorphic => {:default => 'Photo'}
end

Sẽ thêm một cột tệp đính kèm và attachment_typecột chuỗi có giá trị mặc định là Photo.

http://guides.rubyonrails.org/v3.2.21/migations.html#creating-a-standalone-migration

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.