Rails: update_attribute เทียบกับ update_attributes


255
Object.update_attribute(:only_one_field, "Some Value")
Object.update_attributes(:field1 => "value", :field2 => "value2", :field3 => "value3")

ทั้งสองอย่างนี้จะอัปเดตวัตถุโดยไม่ต้องแจ้งให้ AR ทราบเพื่ออัปเดตอย่างชัดเจน

Rails API พูดว่า:

สำหรับ update_attribute

อัพเดตแอททริบิวต์เดียวและบันทึกข้อมูลโดยไม่ต้องผ่านขั้นตอนการตรวจสอบความถูกต้องตามปกติ สิ่งนี้มีประโยชน์อย่างยิ่งสำหรับแฟล็กบูลีนในระเบียนที่มีอยู่ เมธอด update_attribute ปกติในฐานจะถูกแทนที่ด้วยสิ่งนี้เมื่อโมดูลการตรวจสอบความถูกต้องถูกผสมซึ่งเป็นค่าเริ่มต้น

สำหรับ update_attributes

อัปเดตคุณลักษณะทั้งหมดจาก Hash ที่ส่งผ่านและบันทึกบันทึก หากวัตถุไม่ถูกต้องการบันทึกจะล้มเหลวและจะส่งคืนค่าเท็จ

ดังนั้นหากฉันไม่ต้องการให้วัตถุตรวจสอบความถูกต้องฉันควรใช้ update_attribute จะเกิดอะไรขึ้นถ้าฉันมีการอัปเดตนี้ก่อนวันที่บันทึกมันจะสแต็คโอเวอร์โฟลว์หรือไม่

คำถามของฉันคือ update_attribute ยังข้ามก่อนบันทึกหรือเพียงแค่การตรวจสอบ

นอกจากนี้ไวยากรณ์ที่ถูกต้องคืออะไรที่จะผ่านแฮชเพื่อ update_attributes ... ลองดูตัวอย่างของฉันที่ด้านบน


ทำไมคุณต้องการที่จะใส่update_attributeคำสั่งในการbefore_saveโทรกลับ? ฉันไม่สามารถคิดเหตุผลที่ดีสำหรับเรื่องนี้
Daniel Pietzsch

1
ฉันมีวัตถุที่ต้องได้รับการปรับปรุงตามจำนวนของวัตถุที่ได้รับการปรับปรุง อะไรคือวิธีที่ดีกว่า
thenengah

ฉันถูกต้องหรือไม่ว่าวัตถุที่คุณต้องการอัปเดตนั้นเป็นคุณสมบัติของวัตถุที่คุณกำลังบันทึก ถ้าใช่คุณสามารถตั้งค่าได้และพวกเขาจะได้รับการอัปเดตพร้อมกับวัตถุที่ถูกบันทึกอยู่แล้ว (เพราะตั้งอยู่ภายในการbefore_saveเรียกกลับ) เฟแทนที่จะupdate_attribute(:discount, 0.1) if amount > 100ทำเช่นdiscount = 0.1 if amount > 100นั้นได้ update_attributeการโทรsaveหาวัตถุซึ่งไม่จำเป็นในกรณีนี้เนื่องจากคำสั่งนั้นอยู่ในการbefore_saveติดต่อกลับและจะได้รับการบันทึกต่อไป ฉันหวังว่ามันสมเหตุสมผล
Daniel Pietzsch

ใช่และไม่. อย่างไรก็ตามสถานะของวัตถุที่คุณอ้างถึงนั้นขึ้นอยู่กับเงื่อนไขอื่น ๆ ที่ไม่สามารถดำเนินการได้ก่อนการบันทึก
thenengah

3
เป็นบันทึกการตรวจสอบวิธีการเหล่านี้เฮี๊ยบ แต่จะยังคงดำเนินการเรียกกลับเช่น after_save ...
rogerdpack

คำตอบ:


328

update_attributeโปรดดูที่ เมื่อคลิกแสดงแหล่งที่มาคุณจะได้รับรหัสต่อไปนี้

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2614
2614:       def update_attribute(name, value)
2615:         send(name.to_s + '=', value)
2616:         save(false)
2617:       end

ตอนนี้อ้างอิงupdate_attributesและดูรหัสที่คุณได้รับ

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2621
2621:       def update_attributes(attributes)
2622:         self.attributes = attributes
2623:         save
2624:       end

ความแตกต่างระหว่างสองคือการupdate_attributeใช้save(false)ในขณะที่update_attributesใช้saveหรือคุณสามารถพูดsave(true)ได้

ขออภัยสำหรับคำอธิบายที่ยาว แต่สิ่งที่ฉันต้องการจะพูดมีความสำคัญ save(perform_validation = true)ถ้าperform_validationเป็นเท็จมันทะลุ (ข้ามจะเป็นคำที่เหมาะสม) ทั้งหมดที่ตรวจสอบsaveที่เกี่ยวข้องกับ

สำหรับคำถามที่สอง

นอกจากนี้ไวยากรณ์ที่ถูกต้องคืออะไรที่จะผ่านแฮชเพื่อ update_attributes ... ลองดูตัวอย่างของฉันที่ด้านบน

ตัวอย่างของคุณถูกต้อง

Object.update_attributes(:field1 => "value", :field2 => "value2", :field3 => "value3")

หรือ

Object.update_attributes :field1 => "value", :field2 => "value2", :field3 => "value3"

หรือถ้าคุณได้รับข้อมูลทั้งหมดและชื่อในแฮชบอกว่าparams[:user]ที่นี่ใช้เพียง

Object.update_attributes(params[:user])

7
Rails 3คำสั่งของคุณเกี่ยวกับการเรียกกลับไม่ถูกต้องอย่างน้อยใน มันบอกอย่างชัดเจนในความคิดเห็นในแหล่งที่ "เรียกกลับ"
Batkins

ฉันสองที่ @Batkins พูด
Raf

3
@Batkins ยังตรวจสอบไม่ได้ทำงาน - นั่นคือส่วนที่สำคัญที่สุด :)
Tigraine

1
การเชื่อมโยงดังกล่าวไม่ถูกต้องอย่างน้อยเป็นของRails 5.1 วิธีการเหล่านี้ถูกย้ายไปยัง ActiveRecord :: Persistence คุณสามารถค้นหาข้อมูลที่อัปเดตได้ที่นี่: อัปเดตแอตทริบิวต์และที่นี่ update_attributesหมายเหตุ: update_attributesตอนนี้เป็นชื่อแทนสำหรับupdate
tgf

74

เคล็ดลับ: update_attributeจะถูกเลิกใช้ในทางรถไฟ 4 ผ่านCommit a7f4b0a1 มันเอาในความโปรดปรานของupdate_attributeupdate_column


45
สิ่งนี้ไม่เป็นความจริงอีกต่อไป วิธีการได้รับการเพิ่มอีกครั้ง ดูgithub.com/rails/rails/pull/6738#issuecomment-39584005
Dennis

20
update_attributeข้ามการตรวจสอบ แต่ประการเรียกกลับupdate_columnจะข้ามทั้งการตรวจสอบและเรียกกลับและปรับปรุงเคยชิน:updated_at, updateเป็นฟังก์ชั่นปกติที่จะเคารพทั้งเรียกกลับและการตรวจสอบ
โมฮัมหมัด AbuShady

2
พวกเขาจะทำให้จิตใจของพวกเขาแล้ว reset_column, update_column เลิกใช้แล้ว
ahnbizcad

2
update_columnไม่เลิกใช้ แต่update_columns(name: value)เป็นที่ชื่นชอบ reset_columnถูกลบแล้ว
onebree

15

update_attribute

วิธีนี้จะอัปเดตแอตทริบิวต์เดียวของวัตถุโดยไม่ต้องตรวจสอบความถูกต้องตามรูปแบบ

obj = Model.find_by_id(params[:id])
obj.update_attribute :language, java

update_attributes

วิธีการนี้จะอัปเดตแอตทริบิวต์หลายรายการของวัตถุเดียวและผ่านการตรวจสอบตามรุ่น

attributes = {:name => BalaChandar”, :age => 23}
obj = Model.find_by_id(params[:id])
obj.update_attributes(attributes)

หวังว่าคำตอบนี้จะล้างออกเมื่อใช้วิธีใดของบันทึกที่ใช้งานอยู่


12

ยังเป็นที่น่าสังเกตว่ามีค่าด้วย update_attributeคุณลักษณะที่ต้องการได้รับการอัปเดตไม่จำเป็นต้องเป็นสีขาวในรายการattr_accessibleเพื่ออัปเดตเมื่อเทียบกับวิธีการมอบหมายจำนวนมากupdate_attributesซึ่งจะอัปเดตเฉพาะattr_accessibleแอตทริบิวต์ที่ระบุ


8

update_attribute เพียงอัปเดตคุณลักษณะของแบบจำลองเพียงอย่างเดียว แต่เราสามารถส่งแอตทริบิวต์หลายรายการได้ update_attributesวิธีการ

ตัวอย่าง:

user = User.last

#update_attribute
user.update_attribute(:status, "active")

มันผ่านการตรวจสอบ

#update_attributes
user.update_attributes(first_name: 'update name', status: "active")

ไม่อัปเดตหากการตรวจสอบล้มเหลว


อธิบายได้ดีมาก ขอบคุณ!
Diego Somar

6

คำตอบที่ดี โปรดสังเกตว่าสำหรับ ruby ​​1.9 ขึ้นไปคุณสามารถ (และฉันคิดว่าควร) ใช้ไวยากรณ์แฮชใหม่สำหรับ update_attributes:

Model.update_attributes(column1: "data", column2: "data")

6

คุณอาจจะสนใจในการเยี่ยมชมบล็อกโพสต์นี้เกี่ยวกับทุกวิธีที่เป็นไปได้ในการกำหนดคุณลักษณะหรือการปรับปรุงการบันทึก (การปรับปรุงเพื่อให้ทางรถไฟ 4) http://www.davidverhasselt.com/set-attributes-in-activerecord/update_attribute, update, update_column, update_columns etc. ตัวอย่างเช่นมันมีความแตกต่างในด้านต่าง ๆ เช่นการตรวจสอบความถูกต้องการใช้งานแตะที่ updated_at ของวัตถุหรือเรียกการเรียกกลับ

ในฐานะที่เป็นคำตอบสำหรับคำถามของ OP update_attributeไม่ได้ผ่านการเรียกกลับ


ใช่แน่นอนฉันได้แก้ไขคำตอบแล้ว ขอบคุณสำหรับความคิดเห็น.
adamliesko

4

update_attributeและupdate_attributesคล้ายกัน แต่มีข้อแตกต่างใหญ่อย่างหนึ่ง: update_attribute ไม่เรียกใช้การตรวจสอบ

นอกจากนี้:

  • update_attributeใช้เพื่ออัปเดตระเบียนด้วยแอตทริบิวต์เดียว

    Model.update_attribute(:column_name, column_value1)
  • update_attributesใช้เพื่ออัปเดตระเบียนด้วยแอตทริบิวต์หลายรายการ

    Model.update_attributes(:column_name1 => column_value1, :column_name2 => column_value2, ...)

วิธีการทั้งสองนี้ง่ายต่อการสับสนเนื่องจากชื่อและงานที่คล้ายกัน ดังนั้นจะถูกลบออกในความโปรดปรานของupdate_attributeupdate_column

ตอนนี้ในRails4คุณสามารถใช้งานได้Model.update_column(:column_name, column_value)ที่Model.update_attribute(:column_name, column_value)

คลิกที่นี่update_columnเพื่อรับข้อมูลเพิ่มเติมเกี่ยวกับ


4

เพื่อตอบคำถามของคุณupdate_attributeข้ามการบันทึก "การตรวจสอบความถูกต้อง" แต่มันยังคงเรียกใช้การโทรกลับอื่น ๆ เช่นafter_saveฯลฯ ดังนั้นหากคุณต้องการ "เพียงแค่อัปเดตคอลัมน์และข้าม AR cruft ใด ๆ " คุณจะต้องใช้

Model.update_all(...)ดูhttps://stackoverflow.com/a/7243777/32453


2

เมื่อเร็ว ๆ นี้ฉันพบปัญหาการตรวจสอบและupdate_attributeเปรียบเทียบupdate_attributesชื่อที่คล้ายกันดังนั้นพฤติกรรมที่แตกต่างดังนั้นสับสน

ในการผ่านการupdate_attributeตรวจสอบแฮชและบายพาสคุณสามารถทำได้:

object = Object.new
object.attributes = {
  field1: 'value',
  field2: 'value2',
  field3: 'value3'
}
object.save!(validate: false)

1

ฉันคิดว่าคำถามของคุณคือถ้ามี update_attribute ใน before_save จะนำไปสู่และวนซ้ำไม่รู้จบ (จากการโทร update_attribute ใน call_save ก่อนเรียกกลับเรียกเดิมเรียกโดย update_attribute โทร)

ฉันค่อนข้างแน่ใจว่ามันจะข้ามการเรียกกลับก่อนเพราะบันทึกจริงไม่ได้บันทึก คุณยังสามารถบันทึกบันทึกโดยไม่ต้องเรียกใช้การตรวจสอบโดยใช้

Model.save false

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