เพิ่มค่าเริ่มต้นให้กับคอลัมน์ผ่านการย้ายข้อมูล


276

ฉันจะเพิ่มค่าเริ่มต้นให้กับคอลัมน์ที่มีอยู่แล้วผ่านการโยกย้ายได้อย่างไร

เอกสารทั้งหมดที่ฉันสามารถหาได้แสดงให้คุณเห็นว่าต้องทำอย่างไรหากไม่มีคอลัมน์อยู่ แต่ในกรณีนี้

คำตอบ:


352

นี่คือวิธีที่คุณควรทำ:

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

แต่ฐานข้อมูลบางอย่างเช่น PostgreSQL จะไม่อัปเดตฟิลด์สำหรับแถวที่สร้างไว้ก่อนหน้านี้ดังนั้นโปรดตรวจสอบให้แน่ใจว่าคุณอัปเดตฟิลด์ manaully ในการย้ายข้อมูลด้วย


14
หากคุณต้องการการโยกย้ายแบบย้อนกลับได้ให้วางสิ่งนี้ลงในupบล็อกแทนที่จะเป็นchangeบล็อก คุณสามารถปล่อยให้downบล็อกว่างเปล่า มันจะไม่คืนค่าตารางกลับสู่สภาพเดิม แต่การโยกย้ายสามารถย้อนกลับได้
IAmNaN

1
สิ่งนี้จะทำให้ข้อมูลยังคงอยู่หรือไม่?
Marco Prins

2
ใน PostgreSQL ใช่ฉันไม่รู้ว่าจะเกิดอะไรขึ้นกับฐานข้อมูลอื่น
Maurício Linhares

1
คุณหมายความว่าอย่างไรเมื่อคุณพูดว่า "ให้แน่ใจว่าคุณอัปเดตฟิลด์ด้วยตนเองในการย้ายข้อมูล" เราจะทำอย่างนั้นได้อย่างไร?
David Argyle Thacker

7
ฉันลองใช้ PostgreSQL แล้วก็อัปเดตฟิลด์ที่สร้างไว้ก่อนหน้านี้
Aboozar Rajabi

190
change_column_default :employees, :foreign, false

1
@ DenisLins ฉันเห็นด้วยกับคุณดังนั้นฉันจึงทำการค้นคว้าบางอย่างเพื่อหาสาเหตุว่าทำไมมันอาจไม่เป็นเช่นนั้นและมีความเป็นไปได้ที่อะแดปเตอร์ฐานข้อมูลบางตัวไม่รองรับมันเนื่องจากมีการใช้งานในระดับนั้น คำตอบที่ยอมรับยังคงเป็นเดิมพันที่ปลอดภัยที่สุดจนกว่าจะมีการใช้งานในรูปแบบนามธรรม apidock.com/rails/ActiveRecord/ConnectionAdapters/ …
natchiketa

5
นอกจากนั้นคุณจะต้องระบุfrom:และto:ถ้าคุณอยากให้มันเป็นแบบพลิกกลับได้ :)
radubogdan

5
การใช้fromและtoเพิ่มใน Rails 5+ ในการคอมมิชชันนี้: github.com/rails/rails/pull/20018/files
Joshua Pinter

115

สำหรับRails 4+ให้ใช้change_column_default

def change
  change_column_default :table, :column, value
end

1
สิ่งนี้ดีมากโดยเฉพาะถ้าคุณมีการย้ายข้อมูลที่เพิ่มคอลัมน์และตั้งค่าเริ่มต้นสำหรับระเบียนที่มีอยู่ ตัวอย่างเช่น: def change `add_column: foos,: ชื่อ, ค่าเริ่มต้น:" บางอย่างสำหรับค่าที่มีอยู่ "` `change_column_default: foos,: ชื่อ, ค่าเริ่มต้น:" "end
user1491929

2
การโยกย้ายครั้งนี้มีพฤติกรรมแปลก ๆ ในตัวอย่างของคุณมันกลับไม่ได้ edgeguides.rubyonrails.org/active_record_migrations.htmlแนะนำให้ใช้วิธีนี้: change_column_default :products, :approved, from: true, to: false- แต่ก็ใช้งานไม่ได้เช่นกัน
Ilya Krigouzov

ไม่สามารถย้อนกลับโดยใช้สิ่งนั้นได้หรือ
aldrien.h

โดยทั่วไปแล้วใช่สำหรับประโยค "เปลี่ยน" เกือบทุกครั้งเนื่องจากสถานะก่อนหน้านี้ทั้งหมดมักจะชัดเจนเช่นการมีอยู่ของคอลัมน์ประเภทของมัน ฯลฯ การเปลี่ยนแปลงสามารถย้อนกลับได้ตามที่ปรากฏถ้าหากมี ค่าเริ่มต้นที่ชัดเจนที่ถูกต้องก่อนหน้านี้ เนื่องจากเป็นเรื่องปกติที่ค่าเริ่มต้นจะไม่ได้กำหนดคุณอาจมีปัญหา
Elindor

48

การใช้def changeหมายถึงคุณควรเขียนการย้ายข้อมูลที่สามารถย้อนกลับได้ และchange_columnไม่สามารถย้อนกลับได้ คุณสามารถขึ้นไปได้ แต่ไม่สามารถลงได้เนื่องจากchange_columnไม่สามารถย้อนกลับได้

แต่อาจเป็นสองบรรทัดพิเศษ แต่คุณควรใช้def upและdef down

ดังนั้นหากคุณมีคอลัมน์ที่ไม่มีค่าเริ่มต้นคุณควรทำเช่นนี้เพื่อเพิ่มค่าเริ่มต้น

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

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

หรือถ้าคุณต้องการเปลี่ยนค่าเริ่มต้นสำหรับคอลัมน์ที่มีอยู่

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

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

37

** Rails 4.X + **

ในฐานะของ Rails 4 คุณไม่สามารถสร้างการโยกย้ายเพื่อเพิ่มคอลัมน์ในตารางที่มีค่าเริ่มต้นได้ ขั้นตอนต่อไปนี้เพิ่มคอลัมน์ใหม่ไปยังตารางที่มีอยู่ซึ่งมีค่าเริ่มต้นเป็นจริงหรือเท็จ

1. เรียกใช้การโยกย้ายจากบรรทัดคำสั่งเพื่อเพิ่มคอลัมน์ใหม่

$ rails generate migration add_columnname_to_tablename columnname:boolean

คำสั่งดังกล่าวจะเพิ่มคอลัมน์ใหม่ในตารางของคุณ

2. ตั้งค่าคอลัมน์ใหม่เป็น TRUE / FALSE โดยแก้ไขไฟล์การย้ายข้อมูลใหม่ที่สร้างขึ้น

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

** 3 หากต้องการทำการเปลี่ยนแปลงลงในตารางฐานข้อมูลแอปพลิเคชันของคุณให้เรียกใช้คำสั่งต่อไปนี้ในเทอร์มินัล **

$ rake db:migrate

สิ่งนี้แตกต่างกับราง 3+ หรือ 2+ อย่างไร
Ruby Racer

2
ไม่มีใครรู้ว่าสิ่งนี้ได้รวมอยู่ใน Rails 5 หรือไม่?
sambecker

9

ดำเนินการ:

rails generate migration add_column_to_table column:boolean

มันจะสร้างการโยกย้ายนี้:

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

ตั้งค่าเริ่มต้นการเพิ่ม: default => 1

add_column: ตาราง,: คอลัมน์,: boolean,: default => 1

วิ่ง:

rake db: โยกย้าย


2
ตอนนี้ค่าเริ่มต้นของ 1 ไม่ใช่บูลีนอย่างแน่นอน;) นอกจากนี้ exampe นี้จะเพิ่มคอลัมน์ใหม่แทนที่จะเปลี่ยนคอลัมน์ที่มีอยู่ซึ่งเป็นสิ่งที่ OP ต้องการบรรลุ
radiospiel

@radiospiel อันที่จริงแล้ว 1 ก็เป็นบูลีนเหมือนกัน :)
kinduff

นอกจากนี้คุณยังจะต้องสร้างบันทึกในตารางที่สำคัญต่างประเทศที่มีรหัส 1 Key is not present in table errorสำหรับการทำงานเพื่อหลีกเลี่ยงการ
สัญญาเพรสตัน

-50

นี่คือสิ่งที่คุณสามารถทำได้:

class Profile < ActiveRecord::Base
  before_save :set_default_val

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

แก้ไข: ... แต่เห็นได้ชัดว่านี่เป็นความผิดพลาดหน้าใหม่!


มันจะดีกว่าถ้าคุณตั้งค่าเริ่มต้นใน schema vs เป็นbefore_save
rigelstpierre

6
ช่างเป็นคำแนะนำที่น่ากลัวอะไร
svelandiag

ตกลงกันว่ามันแย่จริงๆ
Houcheng

3
อุ๊ปส์คุณมีความร้อนแรงมากในการทำอะไรบางอย่างในระดับโมเดลแทนที่จะเป็นระดับฐานข้อมูล -38 เป็นคะแนนระดับตำนาน
nurettin

1
เป็นมือใหม่ผิดพลาด ... ;-)
webaholik
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.