Thêm: default => true vào boolean trong cột Rails hiện có


160

Tôi đã thấy một vài câu hỏi (cụ thể là câu hỏi này ) ở đây về SO về việc thêm giá trị boolean mặc định vào một cột hiện có. Vì vậy, tôi đã thử change_columnđề xuất nhưng tôi không được thực hiện đúng.

Tôi đã thử:

$ change_column :profiles, :show_attribute, :boolean, :default => true

Trả về -bash: change_column: command not found

Sau đó tôi chạy:

$ rails g change_column :profiles, :show_attribute, :boolean, :default => true

... và

$ rails change_column :profiles, :show_attribute, :boolean, :default => true

Sau đó chạy rake db:migrate, nhưng giá trị :show_attributevẫn còn nil. Trong câu hỏi tôi đã tham chiếu ở trên, nó nói trong PostgreSQL bạn cần cập nhật thủ công. Vì tôi đang sử dụng PostgreSQL, tôi đã thêm vào phần sau trong create_profilesquá trình di chuyển của mình :

t.boolean :show_attribute, :default => true

Ai đó có thể cho tôi biết những gì tôi đang làm sai ở đây?

Câu trả lời:


314

change_columnlà một phương pháp ActiveRecord::Migration, vì vậy bạn không thể gọi nó như thế trong bảng điều khiển.

Nếu bạn muốn thêm một giá trị mặc định cho cột này, hãy tạo một di chuyển mới:

rails g migration add_default_value_to_show_attribute

Sau đó, trong quá trình di chuyển được tạo:

# That's the more generic way to change a column
def up
  change_column :profiles, :show_attribute, :boolean, default: true
end

def down
  change_column :profiles, :show_attribute, :boolean, default: nil
end

HOẶC một tùy chọn cụ thể hơn:

def up
    change_column_default :profiles, :show_attribute, true
end

def down
    change_column_default :profiles, :show_attribute, nil
end

Sau đó chạy rake db:migrate.

Nó sẽ không thay đổi bất cứ điều gì với các hồ sơ đã được tạo. Để làm điều đó, bạn sẽ phải tạo rake taskhoặc chỉ cần truy rails consolecập và cập nhật tất cả các bản ghi (mà tôi không khuyến nghị trong sản xuất).

Khi bạn thêm t.boolean :show_attribute, :default => trueđến create_profilesdi cư, người ta trông đợi rằng nó đã không làm gì cả. Chỉ những di chuyển chưa được chạy mới được thực thi. Nếu bạn bắt đầu với một cơ sở dữ liệu mới, thì nó sẽ đặt mặc định thành true.


2
Cuộc gọi change_column đó phải nằm trong upphương thức trong quá trình di chuyển, đây là một lớp mới sẽ được tạo trong db / di chuyển /. ( downPhương pháp nên được viết để hoàn tác những gì up.) Thực hiện thay đổi đó rake db:migrate.
rkb

Ahh, điều đó có ý nghĩa hơn rkb. Cảm ơn!
tvalent2

nó không làm việc cho tôi cho đến khi tôi viết def self.updef self.down
Kamil Szot

Có lẽ bạn đang sử dụng một phiên bản cũ hơn của đường ray. Tôi nghĩ cú pháp này là có từ 3.1.
Robin

Và trong Rails 5, bạn bỏ phần _attribution để nó chỉ cần nói showhoặc bất kể tên cột là gì.
mê cung

95

Là một biến thể của câu trả lời được chấp nhận, bạn cũng có thể sử dụng change_column_defaultphương pháp trong quá trình di chuyển của mình:

def up
  change_column_default :profiles, :show_attribute, true
end

def down
  change_column_default :profiles, :show_attribute, nil
end

Rails API-docs


1
Điều này đảm bảo bạn sẽ không vô tình thay đổi bất kỳ thuộc tính cột nào khác
Brian Low

1
Và trong Rails 5, bạn rời khỏi _attribution để nó chỉ cần nói showhoặc bất kể tên cột là gì.
mê cung

1
@labyrinth Ý bạn là gì? show_attribute tên của cột, tôi không nghĩ đường ray 5 có liên quan gì đến điều đó, phải không?
Robin

34

Tôi không chắc chắn khi nào nó được viết, nhưng hiện tại để thêm hoặc xóa mặc định khỏi một cột trong di chuyển, bạn có thể sử dụng như sau:

change_column_null :products, :name, false

Đường ray 5:

change_column_default :products, :approved, from: true, to: false

http://edgeguides.rubyonrails.org/active_record_migations.html#changing-columns

Đường ray 4.2:

change_column_default :products, :approved, false

http://guides.rubyonrails.org/v4.2/active_record_migations.html#changing-columns

Đó là một cách gọn gàng để tránh xem qua các lần di chuyển hoặc lược đồ của bạn cho các đặc tả cột.


Coi chừng, đó là từ tài liệu Rails 5. Phiên bản Rails 4.2 này không chấp nhận hàm băm nhưng chính xác mặc định mới là tham số thứ ba. guide.rubyonrails.org/v4.2/ Mạnh
Clamoris

Về Rails 5, làm cả hai dường như là cách chính xác nhất, ví dụ null: falsedefault: :somethingvề cơ bản
Dorian

1

Ngoài ra, theo tài liệu:

mặc định không thể được chỉ định thông qua dòng lệnh

https://guides.rubyonrails.org/active_record_migations.html

Vì vậy, không có máy phát điện đường ray làm sẵn. Như được chỉ định bởi các câu trả lời ở trên, bạn phải điền thủ công tệp di chuyển của mình bằng change_column_defaultphương thức.

Bạn có thể tạo trình tạo của riêng mình: https://guides.rubyonrails.org/generators.html


1

Nếu bạn vừa thực hiện di chuyển, bạn có thể quay lại và sau đó thực hiện di chuyển lại.

Để quay lại, bạn có thể thực hiện bao nhiêu bước bạn muốn:

rake db:rollback STEP=1

Hoặc, nếu bạn đang sử dụng Rails 5.2 hoặc mới hơn:

rails db:rollback STEP=1

Sau đó, bạn có thể thực hiện di chuyển lại:

def change
  add_column :profiles, :show_attribute, :boolean, default: true
end

Đừng quên rake db:migratevà nếu bạn đang sử dụng herokuheroku run rake db:migrate


0
change_column :things, :price_1, :integer, default: 123, null: false

Có vẻ là cách tốt nhất để thêm mặc định vào một cột hiện có mà chưa có null: false.

Nếu không thì:

change_column :things, :price_1, :integer, default: 123

Một số nghiên cứu tôi đã làm về điều này:

https://gist.github.com/Dorian/417b9a0e1a4e09a558c39345d50c8c3b


0

Nếu bạn không muốn tạo một tệp di chuyển khác cho một thay đổi nhỏ, gần đây - từ Bảng điều khiển Rails:

ActiveRecord::Migration.change_column :profiles, :show_attribute, :boolean, :default => true

Sau đó thoát và nhập lại bảng điều khiển đường ray, do đó, Thay đổi DB sẽ có hiệu lực. Sau đó, nếu bạn làm điều này ...

Profile.new()

Bạn sẽ thấy giá trị mặc định "show_attribution" là true.

Đối với các bản ghi hiện có, nếu bạn muốn duy trì cài đặt "sai" hiện có và chỉ cập nhật giá trị "không" vào mặc định mới của bạn:

Profile.all.each{|profile| profile.update_attributes(:show_attribute => (profile.show_attribute == nil ? true : false))  }

Cập nhật quá trình di chuyển đã tạo bảng này, do đó, mọi bản dựng DB trong tương lai sẽ có được nó ngay từ khi bắt đầu. Cũng chạy quy trình tương tự trên bất kỳ phiên bản triển khai nào của DB.

Nếu sử dụng phương thức "di chuyển db mới", bạn có thể thực hiện cập nhật các giá trị nil hiện có trong di chuyển đó.

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.