Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

Code Reading Adventures:Awesome Print Gem

การพิมพ์ที่ยอดเยี่ยมเป็นอัญมณีที่ดีที่จัดรูปแบบผลลัพธ์ของคุณใน irb &แงะ เพื่อให้อ่านง่ายขึ้น

ตัวอย่างเช่น…

นี่คือสิ่งที่แสดงแฮชด้วย awesome_print ดูเหมือนว่า:

Code Reading Adventures:Awesome Print Gem

แต่วิธีนี้ทำงานอย่างไร

“ความจริงสามารถพบได้ในที่เดียวเท่านั้น:รหัส” ― โรเบิร์ต ซี. มาร์ติน

มาดูซอร์สโค้ดกันเพื่อหาคำตอบกัน!

การพิมพ์ที่ยอดเยี่ยม

ฉันชอบเริ่มเซสชันการอ่านโค้ดพร้อมภาพรวมคร่าวๆ ของโครงสร้างโปรเจ็กต์ (ไฟล์และโฟลเดอร์) จากนั้นฉันก็ชอบถามคำถามเพื่อเน้นการสำรวจของฉันต่อไป

คำถามแรกที่ฉันคิดคือ :

awesome_print . เป็นอย่างไร เปลี่ยนผลลัพธ์ของ pry?

ตอนนี้ฉันสวมหมวกนักสืบและตั้งสมมติฐาน :

“อัญมณีนี้สามารถแทนที่ $stdout เพื่อให้สามารถดักจับผลลัพธ์ของ pry แล้วทำให้มันสวยได้”

แต่การใช้งานนี้จะไม่อนุญาตให้คุณปรับแต่งผลลัพธ์ของคุณ เช่น pretty_print (จาก Ruby's Standard Library) ทำได้

นอกจากนี้ เราจะต้องแยกวิเคราะห์ หรือแม้แต่โค้ด eval ก็ยังไม่ใช่ความคิดที่ดี!

ถัดไป :

ฉันดูวิธีการโหลดอัญมณีนี้

ซึ่งจะทำให้เราเข้าสู่โค้ดได้

กำลังโหลดงานพิมพ์ที่ยอดเยี่ยม

ในการโหลด awesome_print ในการแงะ คุณต้องทำสิ่งนี้:

require 'awesome_print'
AwesomePrint.pry!

ตอนนี้เราต้องการค้นหาว่า pry! ถูกกำหนดไว้แล้ว

ฉันใช้คุณลักษณะ "ค้นหาในไดเรกทอรี" ใน Atom เพื่อค้นหา

นี่คือรหัส :

def pry!
  Pry.print = proc { |output, value| output.puts value.ai } if defined?(Pry)
end

ดูเหมือนว่า Pry จะให้คุณแก้ไขผลลัพธ์ได้โดยการตั้งค่า print .

นี่จึงเป็นคำตอบสำหรับคำถามว่า "จะเริ่มต้นอย่างไร" 🙂

ต้องการเรียนรู้เพิ่มเติมเกี่ยวกับสิ่งนี้ "proc" หรือไม่? อ่าน “คู่มือขั้นสูงสำหรับบล็อก โปรคส์ และแลมบ์ดาส” นี่คือตัวอย่างบทจากหนังสือ Ruby Deep Dive ของฉัน

โปรนี้รับสองอาร์กิวเมนต์ :

  • เอาต์พุต
  • ค่า

และเรียกใช้สองวิธีบนวัตถุเหล่านั้น

คำถามถัดไป :

นี่คืออะไร ai วิธีการ?

เป็นวิธีการที่กำหนดไว้ใน Kernel โมดูล:

def ai(options = {})
  ap      = AwesomePrint::Inspector.new(options)
  awesome = ap.awesome(self)

  if options[:html]
    awesome = "</pre>#{awesome}</pre>"
    awesome = awesome.html_safe if defined? ActiveSupport
  end

  awesome
end

alias :awesome_inspect :ai
#{awesome}" เจ๋ง =น่ากลัว.html_safe ถ้ากำหนดไว้? ActiveSupport สิ้นสุด Awesomeendalias :awesome_inspect :ai

เนื่องจากวัตถุทั้งหมดมี เคอร์เนล โดยค่าเริ่มต้น พวกเขาจะมี ai . นี้ วิธีการที่มีอยู่

มาเจาะลึกลงไปอีกหน่อยแล้วมาดูกันว่า สารวัตร งานของชั้นเรียน

กลุ่มสารวัตร

ทันทีหลังจากเปิด inspector.rb เราพบแฮชตัวเลือกมากมายใน initialize วิธีการ

นี่เป็นส่วนหนึ่งของมัน :

@options = {
  indent:        4,      # Number of spaces for indenting.
  index:         true,   # Display array indices.
  html:          false,  # Use ANSI color codes rather than HTML.
  multiline:     true,   # Display in multiple lines.
  # ...
}

หลังจากนั้นเราจะพบรหัสนี้ :

@formatter  = AwesomePrint::Formatter.new(self)
@indentator = AwesomePrint::Indentator.new(@options[:indent].abs)

Thread.current[AP] ||= []

ดังนั้นสิ่งนี้จึงตั้งค่าอ็อบเจ็กต์อีกสองอ็อบเจ็กต์ซึ่งดูเหมือนว่าจะจัดการกับการจัดรูปแบบและการเยื้องโค้ดได้

แต่อะไรคือ Thread.current . นี้ สิ่ง?

วิธีนี้ช่วยให้คุณเข้าถึงเธรดปัจจุบันได้ แม้ว่าคุณจะไม่ได้ใช้เธรดในแอปพลิเคชันของคุณ คุณจะมีเธรด “หลัก”

APนี้ AP ค่าคงที่เป็นเพียงค่าคงที่ซึ่งกำหนดไว้ที่ด้านบนของ inspector.rb :

AP = :__awesome_print__

เกิดอะไรขึ้นที่นี่?

งานพิมพ์ที่ยอดเยี่ยมกำลังใช้ Thread.current &__awesome_print__ คีย์เพื่อบันทึกข้อมูลบางอย่างที่มีอยู่ในเธรดปัจจุบันเท่านั้น

ใช้เพื่อหลีกเลี่ยงปัญหาเกี่ยวกับมัลติเธรด

การจัดรูปแบบที่ยอดเยี่ยม

มาดูโค้ดการจัดรูปแบบเอาต์พุตซึ่งเกิดขึ้นใน AwesomePrint::Formatter ชั้นเรียน

วิธีการทำงานคือผู้ตรวจสอบ (วัตถุที่สร้างโดย ai วิธี) จะเรียก รูปแบบ วิธีการ

def unnested(object)
  @formatter.format(object, printable(object))
end

แล้ว รูปแบบ . นี้ วิธีการใน ฟอร์แมตเตอร์ class จะหาวิธีที่ดีที่สุดในการจัดการกับวัตถุประเภทนี้ &เรียกวิธีอื่นโดยใช้ metaprogramming เล็กน้อย

นี่คือวิธีการ :

def format(object, type = nil)
  core_class = cast(object, type)

  awesome = if core_class != :self
    send(:"awesome_#{core_class}", object) # Core formatters.
  else
    awesome_self(object, type) # Catch all that falls back to object.inspect.
  end

  awesome
end

เพื่อให้เข้าใจ ฟอร์แมตเตอร์ .นี้ คลาสเรายังต้องดูที่ cast วิธีการ:

def cast(object, type)
  CORE.grep(type)[0] || :self
end

CORE ค่าคงที่คืออาร์เรย์ของสัญลักษณ์แทนคลาส Ruby หลัก &:self เป็นสัญลักษณ์ที่ใช้แปลว่า "ไม่พบ" (ในตัวอย่างนี้ ไม่ได้ใช้ในภาษา Ruby โดยทั่วไป)

CORE = [:array, :bigdecimal, :class, :dir, :file, :hash, :method, :rational, :set, :struct, :unboundmethod]

อะไรจะเกิดขึ้น :

หากวัตถุที่กำลังจัดรูปแบบอยู่ในรายการ "คลาสหลัก" วัตถุนั้นจะได้รับรูปแบบเฉพาะ

มิเช่นนั้นจะเป็นแบบทั่วไป

ตัวจัดรูปแบบเฉพาะถูกกำหนดภายใต้ lib/awesome_print/formatters/ ไดเรกทอรี &รวมสิ่งต่าง ๆ เช่น Array , แฮช &คลาส .

ตัวอย่างเช่น นี่คือวิธีการจัดรูปแบบสำหรับคลาส:

def format
  superclass = klass.superclass
  if superclass
    colorize("#{klass.inspect} < #{superclass}", :class)
  else
    colorize(klass.inspect, :class)
  end
end

คุณสามารถเขียนตัวจัดรูปแบบของคุณเองได้หากต้องการ

สรุป

คุณได้เรียนรู้เกี่ยวกับ Awesome Print gem ซึ่งช่วยให้คุณแสดงอ็อบเจ็กต์ เช่น อาร์เรย์และแฮชได้อย่างดี

หวังว่าคุณจะสนุกกับสิ่งนี้และเรียนรู้สิ่งใหม่!

โปรดแชร์โพสต์นี้บนโซเชียลเน็ตเวิร์กที่คุณชื่นชอบตอนนี้ เพื่อให้ผู้คนได้เรียนรู้มากขึ้น 🙂