คุณสมบัติ Rails 6: มีอะไรใหม่และเหตุใดจึงสำคัญ
เผยแพร่แล้ว: 2022-03-11อย่างที่แฟนๆ Ruby on Rails ส่วนใหญ่ทราบกันดีอยู่แล้วว่า Rails 6 กำลังจะมาในเร็วๆ นี้ และมาพร้อมฟีเจอร์และการเปลี่ยนแปลงที่รอคอยอย่างใจจดใจจ่อ จุดมุ่งหมายของบทความนี้คือการทำความคุ้นเคยกับคุณสมบัติหลักที่เพิ่มเข้ามาใน Rails 6 และสรุปว่าคุณสมบัติเหล่านี้สามารถช่วยทำให้แอปพลิเคชันของคุณดีขึ้นได้อย่างไร ซึ่งช่วยประหยัดเวลาอันมีค่าในการพัฒนา
สำหรับผู้เริ่มต้น โปรดจำไว้ว่า Rails 6 ต้องใช้ Ruby 2.5+ และฐานข้อมูลที่อัปเกรดแล้ว ดังนั้น ตรวจสอบให้แน่ใจว่าคุณมีแผนที่จะอัพเกรดระบบของคุณตามนั้น ในกรณีที่คุณยังไม่ได้ดำเนินการดังกล่าว
แล้วคุณสมบัติใหม่เหล่านี้คืออะไร? นี่คือบทสรุปโดยย่อของคุณสมบัติหลักของ Rails 6 ที่คุณน่าจะใช้ในอนาคต:
การทดสอบใน Rails 6
ในฐานะนักพัฒนา Ruby on Rails มืออาชีพ เรามุ่งมั่นที่จะสร้างความครอบคลุมสูงสุดสำหรับโค้ดของเรา อย่างไรก็ตาม การทดสอบกลายเป็นกิจกรรมที่น่าเบื่อหน่ายเมื่อกรณีทดสอบของเรา "หนัก" และเราต้องรอหลายนาทีหรือหลายชั่วโมงเพื่อให้กรณีทดสอบดำเนินการได้
การทดสอบแบบขนาน
Rails 6 มีคำตอบที่นี่ ได้เพิ่มวิธีการ parallelize
ใน ActiveSupport::TestCase
ซึ่งช่วยให้คุณขนานชุดการทดสอบด้วยกระบวนการแยก
ดังนั้น สิ่งที่คุณต้องทำเพื่อขนานกระบวนการสำหรับการทดสอบของคุณคือเพิ่มสิ่งนี้ใน test_helper.rb
ของคุณ:
parallelize(workers: 2)
อีกทางหนึ่ง เราสามารถแทนที่คำสั่งที่ใช้ก่อนหน้านี้สำหรับการทดสอบรัน ตัวอย่างเช่น bin/rails test OR bin/rspec spec
สามารถแทนที่ด้วย PARALLEL_WORKERS=15 rails test OR PARALLEL_WORKERS=15 rspec spec
ดังนั้น คุณสามารถเปลี่ยนคำสั่งสำหรับการรันชุดทดสอบบนแพลตฟอร์ม CI ต่างๆ เช่น Travis, Gitlab, CircleCI และอื่นๆ
นอกจากนี้ยังมี hooks เมื่อมีการสร้าง/ทำลายแต่ละกระบวนการ ซึ่งสามารถใช้ได้ดังนี้:
class ActiveSupport::TestCase parallelize_setup do |worker| # setup databases end parallelize_teardown do |worker| # cleanup databases end parallelize(workers: :number_of_processors) end
หมายเหตุ: หากต้องการเรียนรู้เพิ่มเติม คุณสามารถดู Rails Guides สำหรับรายละเอียดเพิ่มเติมได้
การทดสอบสายเคเบิลการดำเนินการ
เนื่องจากเรากำลังพูดถึงการทดสอบที่มีประสิทธิภาพ เรามาทำความเข้าใจว่า Action Cable ซึ่งเป็นหนึ่งในคุณสมบัติเด่นที่สุดของ Rails 5 ได้รับการปรับปรุงอย่างไร ตอนนี้คุณสามารถทดสอบ Action Cable ในทุกระดับ: การเชื่อมต่อ ช่อง และ การออกอากาศ
การทดสอบการเชื่อม ต่อมีจุดมุ่งหมายเพื่อตรวจสอบว่าตัวระบุการเชื่อมต่อได้รับมอบหมายอย่างถูกต้องหรือคำขอเชื่อมต่อที่ไม่เหมาะสมถูกปฏิเสธ:
class ApplicationCable::ConnectionTest < ActionCable::Connection::TestCase test "connects with params" do connect params: { user_id: 42 } OR cookies.signed[:user_id] = "42" connect assert_equal connection.user_id, "42" end test "rejects connection without params" do assert_reject_connection { connect } end end
การทดสอบช่อง สามารถเขียนขึ้นเพื่อตรวจสอบว่าผู้ใช้สามารถสมัครรับข้อมูลจากช่องและช่องมีสตรีมหรือไม่:
class ChatChannelTest < ActionCable::Channel::TestCase test "subscribes and stream for room" do # Simulate a subscription creation by calling `subscribe` subscribe room: "15" # You can access the Channel object via `subscription` in tests assert subscription.confirmed? assert_has_stream "chat_15" end end
สามารถทดสอบการ แพร่ภาพไปยังช่อง ต่างๆ ได้ดังนี้:
# app/jobs/chat_relay_job.rb class ChatRelayJob < ApplicationJob def perform_later(room, message) ChatChannel.broadcast_to room, text: message end end # test/jobs/chat_relay_job_test.rb require 'test_helper' class ChatRelayJobTest < ActiveJob::TestCase include ActionCable::TestHelper test "broadcast message to room" do room = rooms(:all) assert_broadcast_on(ChatChannel.broadcasting_for(room), text: "Hi!") do ChatRelayJob.perform_now(room, "Hi!") end end end
หมายเหตุ: ดูเคล็ดลับเพิ่มเติมเกี่ยวกับวิธีการทดสอบได้ที่นี่
แทรกและอัพจำนวนมาก
เมื่อถึงจุดหนึ่ง เราทุกคนจำเป็นต้องแทรกหลายระเบียนในครั้งเดียว และพบวิธีแก้ไขปัญหาชั่วคราวหลายอย่างเมื่อทำเช่นนั้น Rails 6 มาพร้อมกับวิธีการใหม่แกะกล่อง — insert_all
คล้ายกับ update_all
จะไม่เรียกใช้การเรียกกลับใด ๆ และจะดำเนินการแบบสอบถาม SQL เดียว มีวิธีการเพิ่มเติม upsert_all
ซึ่งช่วยให้คุณใช้การดำเนินการ upsert ซึ่งถูกเปิดเผยโดยฐานข้อมูลสมัยใหม่มากมาย เช่น Postgres ดังนั้นตอนนี้ คุณสามารถลดการสืบค้นข้อมูลส่วนแทรกและทำให้โค้ดของคุณเหมาะสมยิ่งขึ้น ยังบอกลาอัญมณีที่ใช้ก่อนหน้านี้เช่น activerecord-import
แบบสอบถาม INSERT
SQL เดียวถูกจัดเตรียมโดยวิธีการเหล่านี้ และคำสั่ง SQL เดียวจะถูกส่งไปยังฐานข้อมูล โดยไม่ต้องสร้างอินสแตนซ์ของโมเดล หรือเรียกใช้การเรียกกลับของ Active Record และการตรวจสอบความถูกต้อง นอกจากนี้ยังสามารถกำหนดเกณฑ์เมื่อคีย์หลัก—ดัชนีที่ไม่ซ้ำหรือข้อจำกัดที่ไม่ซ้ำถูกละเมิดพร้อมตัวเลือกในการข้ามหรือเรียกใช้การสืบค้นข้อมูลที่สูงกว่า
ตัวอย่างบางส่วนอยู่ด้านล่าง:
result = Article.insert_all( [ { id: 1, title: 'Handling 1M Requests Per Second', author: 'John', slug: '1m-req-per-second' }, #...snip... ], returning: %w[ id title ], unique_by: :index_articles_on_title_and_author ) result = Article.upsert_all( [ { id: 1, title: 'Handling 1M Requests Per Second', author: 'John', slug: '1m-req-per-second' }, { id: 1, .... }, # duplicate 'id' here { id: 2, .... }, { id: 3, .... }, # duplicate 'title' and 'author' here { id: 4, .... }, { id: 5, .... }, # duplicate 'slug' here { id: 6, .... } ] )
วิธีการ insert
, insert!
และ upsert
เป็น wrappers รอบ ๆ insert_all
, insert_all!
และ upsert_all
ตามลำดับ
หมายเหตุ: มีบทความที่ดีมากที่กล่าวถึงการสืบค้นข้อมูลจำนวนมากเกี่ยวกับฐานข้อมูลต่างๆ หากคุณต้องการข้อมูลเพิ่มเติม อย่าลืมตรวจสอบ
การสลับระหว่างหลายฐานข้อมูล
หนึ่งในคุณสมบัติหลักที่แอปพลิเคชั่นขนาดใหญ่จำนวนมากจะต้องชอบคือสิ่งนี้: ในที่สุด Rails 6 ได้เพิ่มการรองรับฐานข้อมูลหลายตัวสำหรับแอปพลิเคชันของคุณ สร้างขึ้นในและพร้อมใช้งานทันทีที่แกะกล่อง!
แน่นอน ตัวเลือกการออกแบบยังคงเป็นของคุณ ไม่ว่าคุณจะต้องการแบ่งแอปพลิเคชันของคุณออกเป็นไมโครเซอร์วิสหลายตัวโดยที่แต่ละรายการมีฐานข้อมูลแยกกัน หรือใช้เส้นทางแบบเสาหิน หรือเพิ่มแบบจำลองการอ่านหลายแบบสำหรับแอปพลิเคชันของคุณ
อย่างไรก็ตาม ความสามารถในการทำในลักษณะง่ายๆ ดังกล่าวมีศักยภาพที่จะช่วยประหยัด เวลาได้มาก ในด้านการพัฒนา
นี่คือลักษณะของไฟล์ database.yml
ใหม่ของคุณ:
development: primary: database: my_primary_db user: root primary_replica: database: my_primary_db user: ro_user replica: true animals: database: my_animals_db user: root animals_replica database: my_animals_db user: ro_user replica: true
ต่อไปนี้คือวิธีที่น่าสนใจในการระบุวิธีสลับไปยังฐานข้อมูลต่างๆ:
class AnimalsModel < ApplicationRecord self.abstract_class = true connects_to database: { writing: :animals_primary, reading: :animals_replica } end class Dog < AnimalsModel # connected to both the animals_primary db for writing and the animals_replica for reading end
นี่คือหน้า GitHub อย่างเป็นทางการซึ่งมีการจัดทำเป็นเอกสารไว้อย่างดีเช่นกัน โดยส่วนตัวแล้ว ฉันตั้งตารอที่จะมีความสามารถในการแบ่งส่วนฐานข้อมูลในการอัปเดต Rails ในอนาคตเช่นกัน (ลักษณะนี้)
แอคชั่นเมลบ็อกซ์
คุณสมบัติ Rails 6 ที่น่าสนใจอีกประการหนึ่งคือการเพิ่ม Action Mailbox ซึ่งเพิ่มความสามารถในการ กำหนดเส้นทางอีเมลขา เข้าไปยังคอนโทรลเลอร์ เช่น กล่องจดหมายสำหรับการประมวลผลใน Rails

ฟีเจอร์ Action Mailbox ขาเข้าสำหรับ Mailgun, Mandrill, Postmark และ SendGrid คุณยังสามารถจัดการอีเมลขาเข้าได้โดยตรงผ่านทางขาเข้า Exim, Postfix และ Qmail ตอนนี้คุณสามารถจินตนาการถึงผลประโยชน์ที่อาจเกิดขึ้นโดยไม่ต้องลงรายละเอียดเพิ่มเติม อาจเป็นการประมวลผลอีเมลโดยตรงจากแหล่งความช่วยเหลือไปจนถึงตั๋วสนับสนุนอัตโนมัติ Rails 6 ช่วยให้ลูกค้าสามารถตอบกลับโดยตรงผ่านอีเมล และอื่นๆ อีกมากมาย ชั้นเปิดให้คุณสำรวจคุณลักษณะนี้และนำเสนอแนวทางที่เหมาะสำหรับแอปพลิเคชันของคุณ
ต่อไปนี้คือตัวอย่างเล็กๆ เพื่อทำความเข้าใจวิธีใช้ Action Mailbox:
COMMENTS_REGEX = /^comment\+(.+)@example\.com/i # app/mailboxes/application_mailbox.rb class ApplicationMailbox < ActionMailbox::Base routing COMMENTS_REGEX => :comments end # app/mailboxes/comments_mailbox.rb class CommentsMailbox < ApplicationMailbox def process user = User.find_by(email: mail.from) post_uuid = COMMENTS_REGEX.match(mail.to)[1] post = Post.find_by(uuid: post_uuid) post.comments.create(user: user, content: mail.body) end end
นอกจากนี้ วิธีใหม่ในการกำหนดค่าอีเมลมีดังนี้ (ใช้ตัวอย่างของ Sendgrid):
# config/environments/production.rb config.action_mailbox.ingress = :sendgrid
ใช้ rails credentials:edit
เพื่อเพิ่มรหัสผ่านให้กับข้อมูลประจำตัวที่เข้ารหัสของแอปพลิเคชันของคุณภายใต้ action_mailbox.ingress_password
โดยที่ Action Mailbox จะค้นหาโดยอัตโนมัติ:
action_mailbox: ingress_password: …
กำหนดค่า SendGrid Inbound Parse เพื่อส่งต่ออีเมลขาเข้าไปยัง /rails/action_mailbox/sendgrid/inbound_emails
actionmailbox
ชื่อผู้ใช้และรหัสผ่านที่คุณสร้างไว้ก่อนหน้านี้ หากแอปพลิเคชันของคุณอยู่ที่ https://example.com
คุณจะต้องกำหนดค่า SendGrid ด้วย URL ต่อไปนี้:
https://actionmailbox:[email protected]/rails/action_mailbox/sendgrid/i
ในกรณีที่คุณต้องการสำรวจเพิ่มเติม Rails มีคำแนะนำเกี่ยวกับเรื่องนี้แล้วที่นี่
Zeitwerk
Zeitwerk เป็นตัวโหลดโค้ดใหม่สำหรับ Ruby ด้วยโครงสร้างไฟล์แบบเดิม Zeitwerk จะโหลดคลาสและโมดูลของโปรเจ็กต์ตามต้องการ หมายความว่าคุณไม่จำเป็นต้องเขียนไฟล์ที่ต้องใช้การเรียกไฟล์ของคุณเอง ในการเปิดใช้งานใน Rails 6 คุณสามารถทำสิ่งต่อไปนี้:
config.autoloader = :zeitwerk
คุณสามารถอ่านเพิ่มเติมเกี่ยวกับ Zeitwerk ได้ที่นี่
คำแนะนำเครื่องมือเพิ่มประสิทธิภาพ
คุณกังวลว่าข้อความค้นหาบางรายการของคุณใช้เวลาในการดำเนินการนานเกินไปหรือไม่ ตอนนี้คุณมีวิธีกำหนดระยะหมดเวลาสำหรับข้อความค้นหาของคุณด้วย
คำสั่งต่อไปนี้จะทำให้เกิดข้อยกเว้น StatementTimeout
หากการสืบค้นใช้เวลานานกว่าปกติในการดำเนินการ:
User.optimizer_hints("MAX_EXECUTION_TIME(5000)").all
รองรับโดย MySQL และคุณจะต้องสำรวจว่าฐานข้อมูลของคุณรองรับหรือไม่
ตัดทอนฐานข้อมูล
แล้วการ seed data ล่ะ? คำสั่งต่อไปนี้จะตัดตารางฐานข้อมูลทั้งหมดของคุณ และคุณสามารถดำเนินการเริ่มต้นข้อมูลของคุณได้:
rails db:truncate_all
ไม่ต้องลบฐานข้อมูลของคุณเพื่อตั้งต้นอีกต่อไป คุณอาจจะเห็นด้วยว่านี่เป็นวิธีแก้ปัญหาที่หรูหราและรวดเร็ว
ข้อความการกระทำ
บางทีคุณสมบัติที่โดดเด่นอีกอย่างสำหรับแอปพลิเคชันจำนวนมากที่เล่นกับโปรแกรมแก้ไขแบบ WYSIWYG ก็คือการเพิ่มการรองรับตัวแก้ไข Trix ในแอปพลิเคชัน Rails 6 โดยกำเนิด นี่จะเป็นการอัปเกรด/เพิ่มเติมที่ดีสำหรับหลาย ๆ โครงการอย่างแน่นอน
โปรแกรมแก้ไข HTML แบบ WYSIWYG ส่วนใหญ่มีขอบเขตมหาศาล—การใช้งานของเบราว์เซอร์แต่ละตัวมีชุดของจุดบกพร่องและลักษณะเฉพาะของตัวเอง และนักพัฒนา JavaScript ถูกปล่อยให้แก้ไขความไม่สอดคล้องกัน Trix หลีกเลี่ยงความไม่สอดคล้องกันเหล่านี้โดยถือว่า contenteditable
เป็นอุปกรณ์ I/O: เมื่ออินพุตเข้าถึงตัวแก้ไข Trix จะแปลงอินพุตนั้นเป็นการดำเนินการแก้ไขบนโมเดลเอกสารภายใน จากนั้นจึงแสดงผลเอกสารนั้นกลับเข้าไปในตัวแก้ไข สิ่งนี้ทำให้ Trix ควบคุมสิ่งที่เกิดขึ้นหลังจากการกดแป้นพิมพ์ทุกครั้ง
การติดตั้ง:
rails action_text:install # app/models/message.rb class Message < ApplicationRecord has_rich_text :content end
คุณสามารถสำรวจ Action Text โดยละเอียดในเอกสารประกอบอย่างเป็นทางการได้ที่นี่
ความปลอดภัย
การอัปเกรดที่จริงจังไม่เสร็จสมบูรณ์หากไม่มีการปรับปรุงความปลอดภัยเล็กน้อย Rails 6 ก็ไม่ทำให้ผิดหวังในเรื่องความปลอดภัยเช่นกัน การอัพเกรดการรักษาความปลอดภัยที่โดดเด่นครั้งแรกคือการเพิ่มการรองรับการ อนุญาตโฮสต์
การอนุญาตโฮสต์เป็นมิดเดิลแวร์ใหม่ที่ป้องกันการโจมตี DNS rebinding โดยอนุญาตให้โฮสต์ส่งคำขอได้อย่างชัดเจน สิ่งนี้หมายความว่าคุณสามารถกำหนดโฮสต์ที่สามารถเข้าถึงแอปพลิเคชันของคุณได้
การอัพเกรดการรักษาความปลอดภัยอีกประการหนึ่งมีขึ้นเพื่อป้องกันการโจมตีที่พยายามคัดลอกค่าที่ลงนาม/เข้ารหัสของคุกกี้และใช้เป็นค่าของคุกกี้อื่น ทำได้โดยซ่อนชื่อคุกกี้ในฟิลด์วัตถุประสงค์ จากนั้นลงชื่อ/เข้ารหัสพร้อมกับค่าคุกกี้ จากนั้น เมื่ออ่านฝั่งเซิร์ฟเวอร์ เราจะตรวจสอบชื่อคุกกี้และทิ้งคุกกี้ที่ถูกโจมตี เปิดใช้งาน action_dispatch.use_cookies_with_metadata
เพื่อใช้คุณลักษณะนี้ ซึ่งเขียนคุกกี้ด้วยวัตถุประสงค์ใหม่และข้อมูลเมตาการหมดอายุที่ฝังไว้
Webpack เป็น Bundler เริ่มต้น
ในฐานะที่เป็นมาตรฐานโดยพฤตินัยด้วยเฟรมเวิร์ก JavaScript ที่ทันสมัยมากมายสำหรับการพัฒนาส่วนหน้า Rails 6 ได้เพิ่ม Webpack เป็นชุดรวม JavaScript เริ่มต้นผ่าน webpacker gem โดยแทนที่ไปป์ไลน์ Rails Asset นี่เป็นการเพิ่มที่ค่อนข้างตรงไปตรงมา และเราจะไม่ลงรายละเอียดมากนัก พอจะพูดได้ว่า Webpack จะช่วยบรรเทาปัญหาให้กับนักพัฒนา front-end ที่ทำงานหนักเกินไปได้
การป้องกันสภาพการแข่งขัน
Rails 6 มีวิธีการใหม่ที่ใช้ในการป้องกันเงื่อนไขการแข่งขัน SELECT/INSERT ในโค้ดของเรา (ฉันแน่ใจว่าผู้อ่านหลายคนต้องพบกับความโชคร้ายในการเผชิญกับสภาวะการแข่งขันในขณะที่พวกเขาขยายโครงการ) นี่คือเธรด GitHub ในกรณีที่คุณต้องการข้อมูลเพิ่มเติม
ตารางพื้นฐานต้องมีคอลัมน์ที่เกี่ยวข้องซึ่งกำหนดด้วยข้อจำกัดเฉพาะ แม้ว่าเราจะหลีกเลี่ยงสภาวะการแข่งขันระหว่าง SELECT → INSERT จาก #find_or_create_by
แต่ที่จริงแล้ว เรามีสภาวะการแข่งขันอื่นระหว่าง INSERT → SELECT ซึ่งสามารถทริกเกอร์ได้หาก DELETE ระหว่างสองคำสั่งนี้เรียกใช้โดยไคลเอ็นต์อื่น แต่สำหรับการใช้งานส่วนใหญ่ นั่นเป็นเงื่อนไขที่เรามีโอกาสโดนน้อยกว่ามาก
ข้อมูลประจำตัวใน Rails 6
นับตั้งแต่ยุคของ Rails 5.2 ข้อมูลประจำตัวได้รับการขนานนามว่าเป็น “วิธีการรถไฟ” แบบใหม่เพื่อจัดการกับข้อมูลที่ละเอียดอ่อนพร้อมสัญญาว่าจะกำจัดไฟล์ .env ที่น่าอับอายออกไปทุกครั้ง ด้วยข้อมูลประจำตัว คีย์ที่เข้ารหัสสำหรับบริการของบุคคลที่สามสามารถตรวจสอบได้โดยตรงในการควบคุมแหล่งที่มา
อย่างไรก็ตาม จนถึงตอนนี้ Rails ใช้ไฟล์ที่เข้ารหัสเดียวกันสำหรับทุกสภาพแวดล้อม ซึ่งทำให้การจัดการกับคีย์ต่างๆ ในการพัฒนาและการผลิตค่อนข้างยุ่งยาก โดยเฉพาะอย่างยิ่งเมื่อต้องจัดการกับโปรเจ็กต์ขนาดใหญ่และโค้ดดั้งเดิม
ใน Rails 6 ในที่สุดสิ่งนี้ก็แก้ไขได้ด้วยการสนับสนุนข้อมูลประจำตัวต่อสภาพแวดล้อม รายละเอียดเพิ่มเติมสามารถสำรวจได้อีกครั้งในเธรด GitHub อย่างเป็นทางการ
Rails 6 เป็นการอัปเดตที่ดีหรือไม่?
ใช่ และที่จริงแล้ว Rails 6 สามารถอธิบายได้ว่าเป็นการอัปเดตครั้งใหญ่ แม้ว่าจะมีเพียงไม่กี่คนที่เรียกมันว่าตัวเปลี่ยนเกม เนื่องจาก Ruby on Rails มีมานานหลายปีแล้ว มีคนเพียงไม่กี่คนที่คาดหวังการเปลี่ยนแปลงที่ปฏิวัติวงการ แต่การกลับชาติมาเกิดครั้งที่ 6 ทำให้เกิดเรื่องมากมาย
ฟีเจอร์บางอย่างที่เปิดตัวใน Rails 6 ดูเหมือนจะมีการปรับปรุงเล็กน้อย ในขณะที่ฟีเจอร์อื่นๆ มีศักยภาพในการประหยัดเวลาในการพัฒนาได้มาก ปรับปรุงความปลอดภัย ความทนทาน และอื่นๆ บรรทัดล่าง: Rails เติบโตเต็มที่แล้ว นักพัฒนาจำนวนมากยังคงกระตือรือร้นเกี่ยวกับอนาคต และด้วยการเปิดตัว Rails 6 ก็ดีขึ้นไปอีก
แน่นอนว่ารายการฟีเจอร์ของ Rails 6 นี้ยังไม่สมบูรณ์ และหากต้องการดูการเปลี่ยนแปลงทั้งหมด คุณจะต้องตรวจสอบบันทึกการเปลี่ยนแปลง นอกจากนี้ยังมีการเลิกใช้งานจำนวนมากที่คุณควรพิจารณา สุดท้ายนี้ หากคุณยืนกรานที่จะทบทวนทุกการเปลี่ยนแปลงและอัปเดตตัวเอง โปรดอ่านบันทึกย่อประจำรุ่นฉบับเต็ม