Thêm một cột vào một bảng hiện có trong di chuyển Rails


340

Tôi có một mô hình Người dùng cần một :emailcột (Tôi quên thêm cột đó trong giàn giáo ban đầu).

Tôi đã mở tệp di chuyển và thêm t.string :email, đã làm rake db:migratevà có một NoMethodError. Sau đó tôi thêm dòng

add_column :users, :email, :string

một lần nữa rake db:migrate, một lần nữa NoMethodError. Tôi có thiếu một bước ở đây không?

Chỉnh sửa: đây là tập tin di chuyển.

class CreateUsers < ActiveRecord::Migration  
  def self.up  
    add_column :users, :email, :string  
    create_table :users do |t|  
      t.string :username  
      t.string :email  
      t.string :crypted_password  
      t.string :password_salt  
      t.string :persistence_token  

      t.timestamps  
    end  
  end  

  def self.down  
    drop_table :users  
  end  
end

Câu trả lời:


573

Nếu bạn đã chạy di chuyển ban đầu của mình (trước khi chỉnh sửa nó), thì bạn cần tạo một di chuyển mới ( rails generate migration add_email_to_users email:stringsẽ thực hiện thủ thuật). Nó sẽ tạo một tệp di chuyển chứa dòng: add_column :users, email, string Sau đó thực hiện rake db:migratevà nó sẽ chạy di chuyển mới, tạo cột mới.

Nếu bạn chưa chạy di chuyển ban đầu, bạn có thể chỉnh sửa nó, giống như bạn đang cố gắng thực hiện. Mã di chuyển của bạn gần như hoàn hảo: bạn chỉ cần xóa add_columnhoàn toàn dòng (mã đó đang cố thêm cột vào bảng, trước khi bảng được tạo và mã tạo bảng của bạn đã được cập nhật để bao gồm cả t.string :emaildù sao).


6
Chỉ cần rõ ràng, chúng ta sử dụng số nhiều? Vì vậy, nó add_email_to_usersvà KHÔNG add_email_to_user?
Purplejquet 16/12/13

9
Chính xác. Tên bảng trong Rails luôn ở dạng số nhiều (để khớp với các quy ước DB).
camdez

2
Bạn cũng có thể sử dụng rails db:migratecho bước cuối cùng.
Dylan Vander Berg

Có thể tạo một cột mới trên một vị trí cụ thể trong một bảng. Ví dụ: nếu tôi muốn tạo trường "trạng thái" mới ngay sau trường "email" hiện tại?
neeraj

2
@neeraj bây giờ bạn có thể có câu trả lời nhưng đối với những người tìm kiếm khác, vâng, bạn có thể như trong ví dụ t.string :column_x, limit: 10, after: :column_y(đối với Rails 4 ít nhất)
244an

123

Sử dụng lệnh này tại bảng điều khiển rails

rails generate migration add_fieldname_to_tablename fieldname:string

rake db:migrate

để chạy di chuyển này


57

Đôi khi rails generate migration add_email_to_users email:stringtạo ra một di chuyển như thế này

class AddEmailToUsers < ActiveRecord::Migration[5.0]
  def change
  end
end

Trong trường hợp đó bạn phải tự một add_columnđến change:

class AddEmailToUsers < ActiveRecord::Migration[5.0]
  def change
    add_column :users, :email, :string
  end
end

Và sau đó chạy rake db:migrate


1) rails generate migration add_email_to_users email:stringĐiều này nên được chạy sau bundle exec rails choặc chỉ trong thiết bị đầu cuối? 2) Tệp được tạo được đặt ở đâu khi chúng tôi thực hiện truy vấn?
sofs1

28

Bạn cũng có thể làm

rake db:rollback

nếu bạn chưa thêm bất kỳ dữ liệu nào vào các bảng. Sau đó chỉnh sửa tệp di chuyển bằng cách thêm cột email vào đó và sau đó gọi

rake db:migrate

Điều này sẽ hoạt động nếu bạn có đường ray 3.1 trở đi được cài đặt trong hệ thống của bạn.

Cách đơn giản hơn nhiều là thay đổi, hãy để thay đổi trong tệp di chuyển. sử dụng

$rake db:migrate:redo

Điều này sẽ quay trở lại lần di chuyển cuối cùng và di chuyển lại.


21

Để thêm một cột tôi chỉ cần làm theo các bước sau:

  1. rails generate migration add_fieldname_to_tablename fieldname:string

    Thay thế

    rails generate migration addFieldnameToTablename

    Khi di chuyển được tạo, sau đó chỉnh sửa di chuyển và xác định tất cả các thuộc tính bạn muốn cột đó được thêm vào.

    Lưu ý : Tên bảng trong Rails luôn ở dạng số nhiều (để khớp với các quy ước DB). Ví dụ sử dụng một trong các bước được đề cập trước đây-

    rails generate migration addEmailToUsers

  2. rake db:migrate

Hoặc là

  1. Bạn có thể thay đổi lược đồ từ db/schema.rb, Thêm các cột bạn muốn trong truy vấn SQL.
  2. Chạy lệnh này: rake db:schema:load

    Cảnh báo / Lưu ý

    Hãy nhớ rằng, chạy rake db:schema:loadtự động xóa sạch tất cả dữ liệu trong bảng của bạn.


Tôi đã làm điều này, nhưng nó đã không làm lại "giàn giáo" và thêm cột mới. Làm thế nào tôi có thể làm điều đó "tự động"?
John Wooten

@ John Wooten, bạn có thể muốn xóa Giàn giáo và đi qua nó một lần nữa. Thả di chuyển tương ứng quá.
Afolabi Olaoluwa Akinwumi

để thêm ghi chú: thay đổi lược đồ mà không thay đổi di chuyển có thể tạo ra sự cố với các nhà phát triển khác đang duy trì ứng dụng.
BKSpurgeon

3

Khi tôi đã thực hiện điều này, thay vì thay đổi di chuyển ban đầu, tôi tạo một cái mới chỉ với cột thêm trong phần lên và cột thả trong phần xuống.

Bạn có thể thay đổi bản gốc và chạy lại nó nếu bạn di chuyển xuống giữa, nhưng trong trường hợp này tôi nghĩ rằng điều đó đã tạo ra một di chuyển không hoạt động đúng.

Như hiện được đăng, bạn đang thêm cột và sau đó tạo bảng.

Nếu bạn thay đổi thứ tự nó có thể hoạt động. Hoặc, khi bạn đang sửa đổi một di chuyển hiện có, chỉ cần thêm nó vào bảng tạo thay vì thực hiện một cột thêm riêng biệt.


1

Bạn cũng có thể buộc các cột trong bảng bằng cách sử dụng force: true, nếu bảng của bạn đã tồn tại.

ví dụ :

ActiveRecord::Schema.define(version: 20080906171750) do
  create_table "authors", force: true do |t|
    t.string   "name"
    t.datetime "created_at"
    t.datetime "updated_at"
  end
end

1

Bạn cũng có thể sử dụng phương thức change_table đặc biệt trong quá trình di chuyển để thêm các cột mới:

change_table(:users) do |t|
  t.column :email, :string
end

0

Bạn có thể quay lại lần di chuyển cuối cùng bằng cách

rake db:rollback STEP=1

hoặc khôi phục di chuyển cụ thể này bằng cách

rake db:migrate:down VERSION=<YYYYMMDDHHMMSS>

và chỉnh sửa tập tin, sau đó chạy rake db:mirgatelại.



0

Bạn cũng có thể thêm cột vào một vị trí cụ thể bằng cột trước hoặc sau cột như:

rails generate migration add_dob_to_customer dob:date

Tệp di chuyển sẽ tạo mã sau ngoại trừ :: email. bạn cần thêm sau :: email hoặc trước :: email

class AddDobToCustomer < ActiveRecord::Migration[5.2]
  def change
    add_column :customers, :dob, :date, after: :email
  end
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.