1 วงจรชีวิตของออบเจกต์
ในการทำงานปกติของแอปพลิเคชัน Rails ออบเจกต์อาจถูกสร้างขึ้น อัปเดต และลบทิ้งได้ Active Record มีการเชื่อมต่อไปยังวงจรชีวิตของออบเจกต์เหล่านี้เพื่อให้คุณสามารถควบคุมแอปพลิเคชันและข้อมูลของคุณได้
Callback ช่วยให้คุณสามารถเรียกใช้ตรรกะก่อนหรือหลังการเปลี่ยนแปลงสถานะของออบเจกต์ได้
class Baby < ApplicationRecord
after_create -> { puts "Congratulations!" }
end
irb> @baby = Baby.create
Congratulations!
จะเห็นได้ว่ามีเหตุการณ์วงจรชีวิตหลายอย่างและคุณสามารถเลือกเชื่อมต่อกับเหตุการณ์เหล่านี้ได้ก่อนหรือหลังหรือแม้กระทั่งรอบเหตุการณ์
2 ภาพรวมของ Callback
Callback คือเมธอดที่ถูกเรียกในช่วงเวลาที่กำหนดของวงจรชีวิตของออบเจกต์ ด้วย callback คุณสามารถเขียนโค้ดที่จะทำงานเมื่อออบเจกต์ Active Record ถูกสร้าง บันทึก อัปเดต ลบ ตรวจสอบความถูกต้อง หรือโหลดจากฐานข้อมูล
2.1 การลงทะเบียน Callback
เพื่อใช้ callback ที่มีอยู่คุณต้องลงทะเบียน callback นั้น คุณสามารถสร้าง callback เป็นเมธอดธรรมดาและใช้เมธอดคลาสแบบ macro-style เพื่อลงทะเบียน callback:
class User < ApplicationRecord
validates :login, :email, presence: true
before_validation :ensure_login_has_a_value
private
def ensure_login_has_a_value
if login.blank?
self.login = email unless email.blank?
end
end
end
เมธอดคลาสแบบ macro-style ยังสามารถรับบล็อกได้ คิดจะใช้รูปแบบนี้หากโค้ดภายในบล็อกของคุณสั้นมากเพียงพอที่จะพอดีในบรรทัดเดียว:
class User < ApplicationRecord
validates :login, :email, presence: true
before_create do
self.name = login.capitalize if name.blank?
end
end
อีกวิธีหนึ่งคุณสามารถส่ง proc เข้าไปใน callback เพื่อเรียกใช้งาน
class User < ApplicationRecord
before_create ->(user) { user.name = user.login.capitalize if user.name.blank? }
end
สุดท้ายคุณสามารถกำหนดว่างาน callback ของคุณเอง ซึ่งเราจะพูดถึงในภายหลังอย่างละเอียด ด้านล่าง
class User < ApplicationRecord
before_create MaybeAddName
end
class MaybeAddName
def self.before_create(record)
if record.name.blank?
record.name = record.login.capitalize
end
end
end
Callback ยังสามารถลงทะเบียนเพื่อทำงานเฉพาะในเหตุการณ์วงจรชีวิตบางอย่าง ซึ่งช่วยให้คุณควบคุมได้อย่างสมบูรณ์เมื่อและในบริบทใด callback ของคุณจะถูกเรียกใช้
class User < ApplicationRecord
before_validation :normalize_name, on: :create
# :on ยังสามารถรับอาร์เรย์ได้
after_validation :set_location, on: [ :create, :update ]
private
def normalize_name
self.name = name.downcase.titleize
end
def set_location
self.location = LocationService.query(self)
end
end
ถือว่าเป็นการปฏิบัติที่ดีที่จะประกาศเมธอด callback เป็น private หากปล่อยให้เป็น public จะสามารถเรียกใช้จากภายนอกโมเดลได้และละเมิดหลักการของการห่อหุ้มออบเจกต์
คำเตือน. หลีกเลี่ยงการเรียกใช้ update
, save
หรือเมธอดอื่น ๆ ที่สร้างผลข้างเคียงให้กับออบเจกต์ภายใน callback ตัวอย่างเช่น อย่าเรียกใช้ update(attribute: "value")
ใน callback นี้ สามารถเปลี่ยนแปลงสถานะของโมเดลและอาจทำให้เกิดผลข้างเคียงที่ไม่คาดคิดในระหว่างการ commit แทนนั้นคุณสามารถกำหนดค่าโดยตรงได้อย่างปลอดภัย (ตัวอย่างเช่น self.attribute = "value"
) ใน before_create
/ before_update
หรือ callback ก่อนหน้านี้
3 การเรียกใช้ Callbacks ที่มีอยู่
นี่คือรายการทั้งหมดของ Callbacks ที่มีอยู่ใน Active Record แสดงในลำดับเดียวกันที่จะถูกเรียกใช้ในระหว่างการดำเนินการที่เกี่ยวข้อง:
3.1 การสร้างออบเจ็กต์
before_validation
after_validation
before_save
around_save
before_create
around_create
after_create
after_save
after_commit
/after_rollback
3.2 การอัปเดตออบเจ็กต์
before_validation
after_validation
before_save
around_save
before_update
around_update
after_update
after_save
after_commit
/after_rollback
คำเตือน. after_save
ทำงานทั้งในการสร้างและการอัปเดต แต่เสมอ หลัง ของ Callbacks ที่เฉพาะเจาะจงมากกว่า after_create
และ after_update
ไม่ว่าจะเรียกใช้ Macro ในลำดับใด
3.3 การทำลายออบเจ็กต์
หมายเหตุ: Callbacks before_destroy
ควรวางไว้ก่อนการเชื่อมโยง dependent: :destroy
(หรือใช้ตัวเลือก prepend: true
) เพื่อให้แน่ใจว่าจะทำงานก่อนที่ระเบียนจะถูกลบโดย dependent: :destroy
คำเตือน. after_commit
ให้การรับรองที่แตกต่างกันจาก after_save
, after_update
, และ after_destroy
ตัวอย่างเช่นหากเกิดข้อผิดพลาดใน after_save
การทำธุรกรรมจะถูกยกเลิกและข้อมูลจะไม่ถูกบันทึก ในขณะที่ทุกอย่างที่เกิดขึ้นหลังจาก after_commit
สามารถรับรองได้ว่าการทำธุรกรรมได้เสร็จสิ้นและข้อมูลถูกบันทึกในฐานข้อมูล ข้อมูลเพิ่มเติมเกี่ยวกับ transactional callbacks ด้านล่าง
3.4 after_initialize
และ after_find
เมื่อมีการสร้างออบเจ็กต์ Active Record after_initialize
callback จะถูกเรียกใช้ ไม่ว่าจะใช้ new
โดยตรงหรือเมื่อบันทึกถูกโหลดจากฐานข้อมูล มันสามารถใช้เพื่อหลีกเลี่ยงความจำเป็นในการเขียนโค้ดเพื่อแทนที่เมธอด initialize
ของ Active Record
เมื่อโหลดบันทึกจากฐานข้อมูล after_find
callback จะถูกเรียกใช้ ถ้าทั้งสองอย่างถูกกำหนดไว้
หมายเหตุ: Callbacks after_initialize
และ after_find
ไม่มีคู่สมรรถนะ before_*
สามารถลงทะเบียนได้เหมือนกับ Callbacks อื่น ๆ ของ Active Record
class User < ApplicationRecord
after_initialize do |user|
puts "คุณได้เริ่มต้นออบเจ็กต์!"
end
after_find do |user|
puts "คุณได้พบออบเจ็กต์!"
end
end
irb> User.new
คุณได้เริ่มต้นออบเจ็กต์!
=> #<User id: nil>
irb> User.first
คุณได้พบออบเจ็กต์!
คุณได้เริ่มต้นออบเจ็กต์!
=> #<User id: 1>
3.5 after_touch
Callback after_touch
จะถูกเรียกเมื่อมีการสัมผัสกับออบเจ็กต์ Active Record
class User < ApplicationRecord
after_touch do |user|
puts "คุณได้สัมผัสกับออบเจ็กต์"
end
end
irb> u = User.create(name: 'Kuldeep')
=> #<User id: 1, name: "Kuldeep", created_at: "2013-11-25 12:17:49", updated_at: "2013-11-25 12:17:49">
irb> u.touch
คุณได้สัมผัสกับออบเจ็กต์
=> true
สามารถใช้งานร่วมกับ belongs_to
ได้:
class Book < ApplicationRecord
belongs_to :library, touch: true
after_touch do
puts 'มีการสัมผัสกับหนังสือ'
end
end
class Library < ApplicationRecord
has_many :books
after_touch :log_when_books_or_library_touched
private
def log_when_books_or_library_touched
puts 'มีการสัมผัสกับหนังสือหรือห้องสมุด'
end
end
irb> @book = Book.last
=> #<Book id: 1, library_id: 1, created_at: "2013-11-25 17:04:22", updated_at: "2013-11-25 17:05:05">
irb> @book.touch # กระตุ้น @book.library.touch
มีการสัมผัสกับหนังสือ
มีการสัมผัสกับหนังสือหรือห้องสมุด
=> true
4 การเรียกใช้ Callbacks
เมทอดต่อไปนี้เป็นตัวกระตุ้น Callbacks:
create
create!
destroy
destroy!
destroy_all
destroy_by
save
save!
save(validate: false)
toggle!
touch
update_attribute
update
update!
valid?
นอกจากนี้ยังมีการเรียกใช้after_find
callback โดยใช้เมธอด finder ต่อไปนี้:all
first
find
find_by
find_by_*
find_by_*!
find_by_sql
last
after_initialize
callback จะถูกเรียกทุกครั้งที่มีการสร้างอ็อบเจ็กต์ใหม่ของคลาสนี้
หมายเหตุ: เมธอด find_by_*
และ find_by_*!
เป็น dynamic finders ที่สร้างขึ้นโดยอัตโนมัติสำหรับแต่ละ attribute อ่านข้อมูลเพิ่มเติมได้ที่ ส่วน Dynamic finders
5 การข้าม Callbacks
เช่นเดียวกับการตรวจสอบความถูกต้อง ยังสามารถข้าม callback ได้โดยใช้เมธอดต่อไปนี้:
decrement!
decrement_counter
delete
delete_all
delete_by
increment!
increment_counter
insert
insert!
insert_all
insert_all!
touch_all
update_column
update_columns
update_all
update_counters
upsert
upsert_all
อย่างไรก็ตาม ควรใช้เมธอดเหล่านี้อย่างระมัดระวัง เนื่องจากกฎธุรกิจที่สำคัญและตรรกะในแอปพลิเคชันอาจถูกเก็บไว้ใน callbacks การข้ามไปโดยไม่เข้าใจผลกระทบที่อาจเกิดขึ้นอาจทำให้ข้อมูลไม่ถูกต้อง
6 หยุดการทำงาน
เมื่อคุณเริ่มลงทะเบียน callback ใหม่สำหรับโมเดลของคุณ มันจะถูกจัดคิวเพื่อทำงาน คิวนี้จะรวมถึงการตรวจสอบความถูกต้องของโมเดล การลงทะเบียน callback และการดำเนินการฐานข้อมูลที่จะทำงาน
ทั้งหมดใน callback chain จะถูกครอบตัดด้วย transaction หาก callback ใดๆ ที่เกิดขึ้นเกิดข้อผิดพลาด การทำงานจะถูกหยุดและจะมีการ ROLLBACK ถ้าต้องการหยุด chain โดยตั้งใจใช้:
throw :abort
คำเตือน. ข้อยกเว้นใดๆ ที่ไม่ใช่ ActiveRecord::Rollback
หรือ ActiveRecord::RecordInvalid
จะถูกเรียกใช้ใหม่โดย Rails หลังจากที่ chain ของ callback ถูกหยุด อีกทั้งอาจทำให้โค้ดที่ไม่คาดหวังเช่น save
และ update
(ซึ่งโดยปกติจะพยายามส่งคืน true
หรือ false
) เกิดข้อผิดพลาด
หมายเหตุ: หากเกิด ActiveRecord::RecordNotDestroyed
ภายใน after_destroy
, before_destroy
หรือ around_destroy
callback จะไม่ถูกเรียกใช้ใหม่และเมธอด destroy
จะส่งคืน false
7 Relational Callbacks
Callbacks ทำงานผ่านความสัมพันธ์ของโมเดล และสามารถกำหนดได้โดยใช้ความสัมพันธ์นั้นเอง พิจารณาตัวอย่างที่ผู้ใช้มีบทความหลายเรื่อง บทความของผู้ใช้ควรถูกลบหากผู้ใช้ถูกลบ ให้เพิ่ม after_destroy
callback ในโมเดล User
ผ่านความสัมพันธ์กับโมเดล Article
:
class User < ApplicationRecord
has_many :articles, dependent: :destroy
end
class Article < ApplicationRecord
after_destroy :log_destroy_action
def log_destroy_action
puts 'Article destroyed'
end
end
irb> user = User.first
=> #<User id: 1>
irb> user.articles.create!
=> #<Article id: 1, user_id: 1>
irb> user.destroy
Article destroyed
=> #<User id: 1>
8 Conditional Callbacks
เช่นเดียวกับการตรวจสอบความถูกต้อง เรายังสามารถกำหนดให้เรียกใช้เมธอด callback ตามเงื่อนไขที่กำหนดได้ โดยใช้ตัวเลือก :if
และ :unless
ซึ่งสามารถรับสัญลักษณ์ เมธอด Proc
หรือ Array
ได้
คุณสามารถใช้ตัวเลือก :if
เมื่อคุณต้องการระบุเงื่อนไขที่ callback ควร ถูกเรียกใช้ หากคุณต้องการระบุเงื่อนไขที่ callback ไม่ควร ถูกเรียกใช้ คุณสามารถใช้ตัวเลือก :unless
ได้
8.1 การใช้ :if
และ :unless
กับ Symbol
คุณสามารถเชื่อมโยงตัวเลือก :if
และ :unless
กับสัญลักษณ์ที่เป็นชื่อของเมธอดตัวตรวจสอบที่จะถูกเรียกใช้ก่อน callback
เมื่อใช้ตัวเลือก :if
คำสั่ง callback จะไม่ถูกเรียกใช้หากเมธอดตัดสินใจส่วนหนึ่งคืนค่า false; เมื่อใช้ตัวเลือก :unless
คำสั่ง callback จะไม่ถูกเรียกใช้หากเมธอดตัดสินใจส่วนหนึ่งคืนค่า true นี่เป็นตัวเลือกที่พบบ่อยที่สุด
class Order < ApplicationRecord
before_save :normalize_card_number, if: :paid_with_card?
end
ในกรณีที่ใช้รูปแบบการลงทะเบียนนี้ ยังสามารถลงทะเบียนตัวตัดสินใจหลายตัวที่ต้องเรียกใช้เพื่อตรวจสอบว่าคำสั่ง callback ควรถูกเรียกใช้หรือไม่ จะถูกอธิบายต่อไปนี้ ด้านล่าง.
8.2 การใช้ :if
และ :unless
พร้อมกับ Proc
สามารถเชื่อมโยง :if
และ :unless
กับอ็อบเจกต์ Proc
ได้ ตัวเลือกนี้เหมาะสำหรับการเขียนเมธอดการตรวจสอบที่สั้น ๆ ซึ่งมักจะเป็นเมธอดที่เขียนเพียงหนึ่งบรรทัด:
class Order < ApplicationRecord
before_save :normalize_card_number,
if: Proc.new { |order| order.paid_with_card? }
end
เนื่องจาก proc ถูกประเมินในบริบทของอ็อบเจกต์ สามารถเขียนได้เช่นนี้:
class Order < ApplicationRecord
before_save :normalize_card_number, if: Proc.new { paid_with_card? }
end
8.3 เงื่อนไขตัดสินใจหลายรายการ
ตัวเลือก :if
และ :unless
ยังรองรับอาร์เรย์ของ procs หรือชื่อเมธอดเป็นสัญลักษณ์:
class Comment < ApplicationRecord
before_save :filter_content,
if: [:subject_to_parental_control?, :untrusted_author?]
end
สามารถรวม proc ในรายการเงื่อนไขได้ง่าย ๆ:
class Comment < ApplicationRecord
before_save :filter_content,
if: [:subject_to_parental_control?, Proc.new { untrusted_author? }]
end
8.4 การใช้ทั้ง :if
และ :unless
Callback สามารถผสม :if
และ :unless
ในการประกาศเดียวกันได้:
class Comment < ApplicationRecord
before_save :filter_content,
if: Proc.new { forum.parental_control? },
unless: Proc.new { author.trusted? }
end
Callback จะทำงานเมื่อทุกเงื่อนไข :if
และไม่มีเงื่อนไข :unless
ที่ถูกประเมินเป็น true
.
9 คลาส Callback
บางครั้งเมธอด callback ที่คุณเขียนอาจมีประโยชน์มากพอที่จะนำไปใช้ซ้ำกับโมเดลอื่น ๆ Active Record ช่วยให้เป็นไปได้ที่จะสร้างคลาสที่ห่อหุ้มเมธอด callback เพื่อนำไปใช้ซ้ำได้
ตัวอย่างนี้แสดงถึงการสร้างคลาสที่มี callback after_destroy
เพื่อจัดการกับการล้างข้อมูลของไฟล์ที่ถูกทิ้งในระบบไฟล์ พฤติกรรมนี้อาจไม่ใช่เฉพาะกับโมเดล PictureFile
เราอาจต้องการแบ่งปันมัน ดังนั้นควรห่อหุ้มเป็นคลาสแยกต่างหาก สิ่งนี้จะทำให้การทดสอบพฤติกรรมนั้นและการเปลี่ยนแปลงมันง่ายขึ้น
class FileDestroyerCallback
def after_destroy(file)
if File.exist?(file.filepath)
File.delete(file.filepath)
end
end
end
เมื่อประกาศภายในคลาสเช่นข้างต้น เมธอด callback จะได้รับอ็อบเจกต์โมเดลเป็นพารามิเตอร์ สิ่งนี้จะทำงานกับโมเดลใดก็ได้ที่ใช้คลาสเช่นนี้ดังนี้:
class PictureFile < ApplicationRecord
after_destroy FileDestroyerCallback.new
end
โปรดทราบว่าเราต้องสร้างอ็อบเจกต์ FileDestroyerCallback
ใหม่ เนื่องจากเราประกาศ callback เป็นเมธอดอินสแตนซ์ สิ่งนี้เป็นประโยชน์มากโดยเฉพาะอย่างยิ่งถ้า callback ใช้สถานะของอ็อบเจกต์ที่ถูกสร้างขึ้น อย่างไรก็ตาม บ่อยครั้งจะมีความเหมาะสมกว่าที่จะประกาศ callback เป็นเมธอดคลาส:
class FileDestroyerCallback
def self.after_destroy(file)
if File.exist?(file.filepath)
File.delete(file.filepath)
end
end
end
เมื่อประกาศเมธอด callback ในลักษณะนี้ จะไม่จำเป็นต้องสร้างอ็อบเจกต์ FileDestroyerCallback
ใหม่ในโมเดลของเรา
ruby
class PictureFile < ApplicationRecord
after_destroy FileDestroyerCallback
end
คุณสามารถประกาศ callback ได้เท่าที่คุณต้องการภายในคลาส callback ของคุณ
10 Transaction Callbacks
10.1 การจัดการกับความสอดคล้อง
มี callback อีกสองตัวที่ถูกเรียกใช้หลังจากที่เสร็จสิ้นการทำงานของธุรกรรมฐานข้อมูล: after_commit
และ after_rollback
การทำงานของ callback เหล่านี้คล้ายกับ callback after_save
ยกเว้นว่าจะไม่ถูกเรียกใช้จนกว่าการเปลี่ยนแปลงในฐานข้อมูลจะถูก commit หรือ rollback การใช้งานมีประโยชน์มากที่สุดเมื่อโมเดล active record ของคุณต้องปฏิสัมพันธ์กับระบบภายนอกที่ไม่ได้เป็นส่วนหนึ่งของการทำธุรกรรมในฐานข้อมูล
พิจารณาตัวอย่างเช่น โมเดล PictureFile
ต้องลบไฟล์หลังจากที่บันทึกบันทึกที่เกี่ยวข้องถูกลบไปแล้ว หากมีอะไรที่เกิดขึ้นขึ้นข้อยกเว้นหลังจากที่เรียกใช้งาน callback after_destroy
และการทำธุรกรรมถูก rollback ไฟล์จะถูกลบและโมเดลจะอยู่ในสถานะที่ไม่สอดคล้องกัน ตัวอย่างเช่น สมมุติว่า picture_file_2
ในโค้ดด้านล่างไม่ถูกต้องและเมธอด save!
ยกเลิกการทำงาน
PictureFile.transaction do
picture_file_1.destroy
picture_file_2.save!
end
โดยใช้ callback after_commit
เราสามารถปรับปรุงกรณีนี้ได้
class PictureFile < ApplicationRecord
after_commit :delete_picture_file_from_disk, on: :destroy
def delete_picture_file_from_disk
if File.exist?(filepath)
File.delete(filepath)
end
end
end
หมายเหตุ: ตัวเลือก :on
ระบุเมื่อ callback จะถูกเรียกใช้งาน หากคุณไม่ได้ให้ตัวเลือก :on
callback จะถูกเรียกใช้สำหรับทุก ๆ การกระทำ
10.2 บริบทสำคัญ
เนื่องจากใช้ callback after_commit
เฉพาะในการสร้าง อัปเดต หรือลบเป็นสิ่งที่พบบ่อย มีตัวย่อสำหรับการดำเนินการเหล่านั้น:
class PictureFile < ApplicationRecord
after_destroy_commit :delete_picture_file_from_disk
def delete_picture_file_from_disk
if File.exist?(filepath)
File.delete(filepath)
end
end
end
คำเตือน. เมื่อธุรกรรมเสร็จสิ้น callback after_commit
หรือ after_rollback
จะถูกเรียกสำหรับโมเดลที่ถูกสร้าง อัปเดต หรือลบภายในธุรกรรมนั้น อย่างไรก็ตามหากเกิดข้อยกเว้นขึ้นภายในหนึ่งใน callback เหล่านี้ ข้อยกเว้นจะแผ่ขึ้นและ callback after_commit
หรือ after_rollback
เหลืออยู่จะไม่ถูกเรียกใช้งาน ดังนั้นหากโค้ด callback ของคุณสามารถเกิดข้อยกเว้นได้ คุณจะต้อง rescue และจัดการกับมันภายใน callback เพื่อให้ callback อื่น ๆ ทำงานได้
คำเตือน. โค้ดที่ทำงานภายใน callback after_commit
หรือ after_rollback
ไม่ได้ถูกครอบคลุมด้วยธุรกรรม
คำเตือน. การใช้ทั้ง after_create_commit
และ after_update_commit
ด้วยชื่อเมธอดเดียวกันจะทำให้ callback ที่กำหนดล่าสุดเท่านั้นที่มีผล โดยที่ทั้งคู่จะเปลี่ยนชื่อเป็น after_commit
ซึ่งจะแทนที่ callback ที่กำหนดไว้ก่อนหน้านี้ที่มีชื่อเมธอดเดียวกัน
class User < ApplicationRecord
after_create_commit :log_user_saved_to_db
after_update_commit :log_user_saved_to_db
private
def log_user_saved_to_db
puts 'User was saved to database'
end
end
irb> @user = User.create # ไม่พิมพ์อะไร
irb> @user.save # อัปเดต @user
User was saved to database
10.3 after_save_commit
ยังมี after_save_commit
ซึ่งเป็นตัวย่อสำหรับใช้ callback after_commit
สำหรับการสร้างและอัปเดตพร้อมกัน:
class User < ApplicationRecord
after_save_commit :log_user_saved_to_db
private
def log_user_saved_to_db
puts 'User was saved to database'
end
end
irb> @user = User.create # สร้าง User
User was saved to database
irb> @user.save # อัปเดต @user
User was saved to database
10.4 การจัดลำดับการเรียกใช้ Transactional Callback
เมื่อกำหนด transactional after_
callbacks (after_commit
, after_rollback
, เป็นต้น) หลายตัว ลำดับจะถูกกลับด้านจากที่กำหนด
class User < ActiveRecord::Base
after_commit { puts("this actually gets called second") }
after_commit { puts("this actually gets called first") }
end
หมายเหตุ: สิ่งนี้ยังใช้กับ after_*_commit
variations ทั้งหมด เช่น after_destroy_commit
ด้วย
ข้อเสนอแนะ
คุณสามารถช่วยปรับปรุงคุณภาพของคู่มือนี้ได้
กรุณาช่วยเพิ่มเติมหากพบข้อผิดพลาดหรือข้อผิดพลาดทางความจริง เพื่อเริ่มต้นคุณสามารถอ่านส่วน การสนับสนุนเอกสาร ของเราได้
คุณอาจพบเนื้อหาที่ไม่สมบูรณ์หรือเนื้อหาที่ไม่ได้อัปเดต กรุณาเพิ่มเอกสารที่ขาดหายไปสำหรับเนื้อหาหลัก โปรดตรวจสอบ Edge Guides ก่อนเพื่อตรวจสอบ ว่าปัญหาได้รับการแก้ไขหรือไม่ในสาขาหลัก ตรวจสอบ คู่มือแนวทาง Ruby on Rails เพื่อดูรูปแบบและกฎเกณฑ์
หากคุณพบข้อผิดพลาดแต่ไม่สามารถแก้ไขได้เอง กรุณา เปิดปัญหา.
และสุดท้าย การสนทนาใด ๆ เกี่ยวกับ Ruby on Rails เอกสารยินดีต้อนรับที่สุดใน เว็บบอร์ดอย่างเป็นทางการของ Ruby on Rails.