(ฉันส่งโพสต์นี้ไปที่รายการของฉันเมื่อสองสามเดือนก่อน ถ้าคุณชอบและต้องการอ่านเพิ่มเติม คุณควรสมัคร!)
วันก่อนฉันเจอสถานการณ์แปลกๆ กับแอปของฉัน
สมมติว่าคุณมี Article
โมเดล และบทความเหล่านี้จะถูกสร้างขึ้นเป็นฉบับร่างก่อน ร่างจดหมายเหล่านี้ควรมีน้ำหนักเบา คุณต้องการสร้างและแก้ไขได้ทันที โดยไม่ต้องใช้เนื้อหา หรือแม้แต่ชื่อเรื่อง
แต่เมื่อคุณ เผยแพร่ บทความเหล่านี้ คุณต้องมีการตรวจสอบเพิ่มเติม พวกเขาควรมีชื่อ เนื้อหา และเรื่องอื่นๆ ทั้งหมด
คุณสามารถเขียน if
. ได้มากมาย งบที่จะตรวจสอบตัวเอง แต่คุณคงไม่มีรูปแบบที่ดีในการจัดการกับ Rails และฉันพบว่าการใช้ Rails สำหรับสิ่งที่ Rails จัดการได้ดีจะช่วยให้คุณไม่ต้องปวดหัวในภายหลัง ยังมีวิธีการใช้การตรวจสอบสำหรับสิ่งนี้หรือไม่
if
และ unless
?
การตรวจสอบรองรับ :if
และ :unless
พารามิเตอร์ แต่สิ่งนี้ไม่สะอาดเสมอไป:
class Article < ActiveRecord::Base
# validate in draft mode
validates_presence_of :author_id
# validate only when published
validates_presence_of :body, unless: lambda { |o| o.draft? }
...
end
นอกจากนี้ นี่ไม่ใช่วิธีที่ฉันต้องการเผยแพร่บทความ ฉันต้องการคิดเกี่ยวกับการเผยแพร่บทความเป็น การกระทำ ไม่ใช่ สถานะ มีบทความอยู่ในนั้น ดังนั้นการตั้งค่าและการตรวจสอบแอตทริบิวต์จึงไม่ใช่คำตอบที่ถูกต้อง
ฟีเจอร์ Rails ที่ไม่ค่อยมีใครรู้จักและมีเอกสารประกอบ
ปัญหานี้เหมาะอย่างยิ่งสำหรับบริบทการตรวจสอบความถูกต้องของ Rails ครั้งแรกที่ฉันได้เรียนรู้เกี่ยวกับบริบทการตรวจสอบความถูกต้องที่กำหนดเองจากส่วนสำคัญที่ DHH เขียนไว้ แต่เป็นการยากที่จะหาคำอธิบายที่ดีว่าสิ่งเหล่านี้คืออะไร และจะใช้อย่างไร
เอกสารประกอบสำหรับบริบทที่กำหนดเองค่อนข้างบาง สิ่งเดียวที่ฉันพบในเอกสาร API คือที่นี่ และเอกสาร API สำหรับการตรวจสอบเหล่านี้ไม่ได้กล่าวถึงบริบทที่กำหนดเองเลย! สิ่งนี้ทำให้ยากเป็นพิเศษ – หากคุณไม่รู้ว่าสิ่งที่เรียกว่าอะไร คุณจะค้นหาเอกสารเพิ่มเติมได้อย่างไร
ในที่สุดฉันก็พบภาพรวมที่ดีที่นี่:https://blog.arkency.com/2014/04/mastering-rails-validations-contexts/ มันคุ้มค่าที่จะอ่าน ลองดูตัวอย่างของเรา:
class Article < ActiveRecord::Base
# validate in draft mode
validates_presence_of :author_id
# validate only when published
validates_presence_of :body, on: :publish
...
end
class ArticleController < ApplicationController
respond_to :html
def create
@article = Article.create(article_params)
respond_with @article
end
def publish
@article = Article.find(params[:id])
@article.attributes = article_params
@article.save(context: :publish)
respond_with @article
end
private
def article_params
params.
require(:article).
permit(:body, :title, :author_id)
end
end
ก็ไม่เลวนะ! ที่แปลกอย่างเดียวคือต้องใช้ save
แทน update
ในวิธีการเผยแพร่ ที่เกิดขึ้นเพราะ update
ไม่สามารถใช้บริบทการตรวจสอบเป็นพารามิเตอร์ได้ (อาจเป็นโอกาสสำหรับคำขอดึง)
อยู่เหนือการประหยัด
บริบทการตรวจสอบความถูกต้องแบบกำหนดเองมีประโยชน์มากกว่าการบันทึกเรกคอร์ดด้วยวิธีต่างๆ บริบทใช้งานได้ valid?
:
@article.valid?(:publish)
เพื่อให้คุณสามารถใช้บริบทการตรวจสอบได้ทุกที่ที่คุณต้องการตอบคำถาม:“วัตถุนี้มีคุณสมบัตินี้หรือไม่ แล้วถ้าไม่ใช่ ทำไมล่ะ”
DHH สร้างเมธอดที่ลงท้ายด้วย -able?
ที่มอบหมายให้ valid?(:context)
). ฉันชอบรูปลักษณ์ของมันมาก:
class Article
validate :has_been_published, on: :view
validate :is_not_spam, on: :view
def viewable?
valid? :view
end
private
def has_been_published
if published_at.future?
errors.add(:published_at, "is in the future")
end
end
def is_not_spam
if is_spam?(body)
errors.add(:body, "has been detected as spam")
end
end
end
วิธีนี้ เมื่อคุณตรวจสอบ คุณจะได้ข้อมูลมากกว่าแค่ true
หรือ false
:
unless @article.viewable?
# @article.errors is now filled out
end
บทความสามารถดูได้หรือไม่? แล้วทำไมไม่ล่ะ
แค่เบาก็พอ
มีอีกสองสามวิธีที่คุณสามารถรับพฤติกรรมการตรวจสอบประเภทนี้ได้ คุณสามารถสร้าง ActiveModel
. ที่กำหนดเองได้ วัตถุบริการที่มีการตรวจสอบความถูกต้องของตนเอง คุณสามารถใช้ :if
หรือ :unless
ในการตรวจสอบของคุณ แต่เช่นเดียวกับหลายๆ อย่างใน Rails บริบทการตรวจสอบที่กำหนดเองเป็นการประนีประนอมที่ดีระหว่างความสามารถในการอ่านและความยืดหยุ่น