Thêm một giá trị mặc định vào một cột thông qua di chuyển


276

Làm cách nào để thêm giá trị mặc định vào cột đã tồn tại thông qua di chuyển?

Tất cả các tài liệu tôi có thể tìm thấy chỉ cho bạn cách thực hiện nếu cột không tồn tại nhưng trong trường hợp này thì có.

Câu trả lời:


352

Đây là cách bạn nên làm điều đó:

change_column :users, :admin, :boolean, :default => false

Nhưng một số cơ sở dữ liệu, như PostgreSQL, sẽ không cập nhật trường cho các hàng được tạo trước đó, vì vậy hãy đảm bảo bạn cũng cập nhật trường một cách cẩn thận khi di chuyển.


14
Nếu bạn cần di chuyển đảo ngược, hãy đặt nó trong một upkhối chứ không phải một changekhối. Bạn có thể để downtrống khối. Nó sẽ không hoàn nguyên bảng về tình trạng ban đầu nhưng việc di chuyển có thể được khôi phục.
IAmNaN

1
Điều này sẽ giữ dữ liệu nguyên vẹn?
Marco Prins

2
Trên PostgreSQL, vâng, tôi không biết điều gì sẽ xảy ra trên các cơ sở dữ liệu khác.
Maurício Linhares

1
Ý bạn là gì khi bạn nói "đảm bảo rằng bạn cập nhật trường theo cách thủ công khi di chuyển"? Làm thế nào để làm điều đó?
David Argyle Thacker

7
Tôi đã thử nó trên PostgreSQL và nó đã cập nhật các trường được tạo trước đó.
Aboozar Rajabi

190
change_column_default :employees, :foreign, false

1
@DenisLins Tôi đã đồng ý với bạn, vì vậy tôi đã thực hiện một số nghiên cứu để tìm ra lý do tại sao nó không thể, và hóa ra có khả năng một bộ điều hợp cơ sở dữ liệu cụ thể không hỗ trợ nó, vì nó được triển khai ở cấp độ đó. Câu trả lời được chấp nhận vẫn là đặt cược an toàn nhất cho đến khi nó được thực hiện trong mô hình trừu tượng. apidock.com/rails/ActiveRecord/ConnectionAd chương / từ
natchiketa 21/07/2015

5
Bên cạnh đó, bạn cần chỉ định một from:to:nếu bạn muốn nó có thể đảo ngược :)
radubogdan

5
Sử dụng fromtođã được thêm vào Rails 5+ trong cam kết này: github.com/rails/rails/pull/20018/files
Joshua Pinter

113

Đối với Rails 4+ , sử dụngchange_column_default

def change
  change_column_default :table, :column, value
end

1
Điều này đặc biệt tốt nếu bạn có một di chuyển đang thêm một cột và đặt mặc định cho các bản ghi hiện có. Ví dụ: def change `add_column: foos ,: name, default:" Something cho các giá trị hiện tại "` `change_column_default: foos ,: name, default:" "`end
user1491929

2
Cuộc di cư này có một hành vi kỳ lạ. Trong ví dụ của bạn, nó không thể đảo ngược. edgeguides.rubyonrails.org/active_record_migations.html khuyên bạn nên sử dụng nó theo cách này: change_column_default :products, :approved, from: true, to: false- nhưng nó cũng không hoạt động.
Ilya Krigouzov

không thể quay lại sử dụng điều đó?
aldrien.h

Thông thường là có, đối với hầu hết mọi mệnh đề "Thay đổi", vì tất cả các trạng thái trước đó thường rõ ràng, chẳng hạn như sự hiện diện của một cột, đó là kiểu, v.v. Sự thay đổi có thể được khôi phục khi nó được hiển thị ở đó nếu và chỉ khi có mặc định rõ ràng hợp lệ trước đây. Vì thông thường các mặc định là không xác định, bạn có thể có một vấn đề ở đó.
Elindor 16/12/19

48

Sử dụng def changecó nghĩa là bạn nên viết di chuyển có thể đảo ngược. Và change_columnkhông thể đảo ngược. Bạn có thể đi lên nhưng bạn không thể đi xuống, vì change_columnkhông thể đảo ngược.

Thay vào đó, mặc dù có thể là một vài dòng phụ, bạn nên sử dụng def updef down

Vì vậy, nếu bạn có một cột không có giá trị mặc định, thì bạn nên làm điều này để thêm một giá trị mặc định.

def up
  change_column :users, :admin, :boolean, default: false
end

def down
  change_column :users, :admin, :boolean, default: nil
end

Hoặc nếu bạn muốn thay đổi giá trị mặc định cho một cột hiện có.

def up
  change_column :users, :admin, :boolean, default: false
end

def down
  change_column :users, :admin, :boolean, default: true
end

37

** Đường ray 4.X + **

Kể từ Rails 4, bạn không thể tạo di chuyển để thêm một cột vào bảng có giá trị mặc định, Các bước sau đây thêm một cột mới vào một bảng hiện có với giá trị mặc định là đúng hoặc sai.

1. Chạy di chuyển từ dòng lệnh để thêm cột mới

$ rails generate migration add_columnname_to_tablename columnname:boolean

Lệnh trên sẽ thêm một cột mới trong bảng của bạn.

2. Đặt giá trị cột mới thành TRUE / FALSE bằng cách chỉnh sửa tệp di chuyển mới được tạo.

class AddColumnnameToTablename < ActiveRecord::Migration
  def change
    add_column :table_name, :column_name, :boolean, default: false
  end
end

** 3. Để thực hiện các thay đổi trong bảng cơ sở dữ liệu ứng dụng của bạn, hãy chạy lệnh sau trong terminal **

$ rake db:migrate

Làm thế nào là khác nhau để đường ray 3+ hoặc 2+?
Ruby Racer

2
Có ai biết nếu điều này đã được tích hợp vào Rails 5?
sambecker

9

Hành hình:

rails generate migration add_column_to_table column:boolean

Nó sẽ tạo ra sự di chuyển này:

class AddColumnToTable < ActiveRecord::Migration
  def change
    add_column :table, :column, :boolean
  end
end

Đặt giá trị mặc định thêm: default => 1

add_column: bảng ,: cột ,: boolean ,: default => 1

Chạy:

rake db: di chuyển


2
Bây giờ giá trị mặc định là 1 không chính xác là boolean;) Ngoài ra, exampe này thêm một cột mới, thay vì thay đổi cột hiện có, đó là điều mà OP muốn đạt được
radiospiel

@radiospiel Trên thực tế, 1 cũng là một boolean :)
kinduff

Bạn cũng sẽ cần tạo một bản ghi trong bảng khóa ngoại với ID là 1 để làm việc này, để tránh Key is not present in table error.
Promise Preston

-50

Đây là những gì bạn có thể làm:

class Profile < ActiveRecord::Base
  before_save :set_default_val

  def set_default_val
    self.send_updates = 'val' unless self.send_updates
  end
end

EDIT: ... nhưng rõ ràng đây là một sai lầm của Rookie!


Sẽ tốt hơn nếu bạn đặt mặc định trong lược đồ so vớibefore_save
a Rigelstpierre 6/03/2015

6
Thật là một lời đề nghị khủng khiếp
secraftiag

đồng ý, nó thực sự khủng khiếp
Houcheng

2
ouch, bạn có rất nhiều nhiệt để làm một cái gì đó ở cấp độ mô hình thay vì mức cơ sở dữ liệu. -38 là một số điểm huyền thoại.
Nurettin

1
thật là một sai lầm tân binh ... ;-)
webaholik
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.