Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Ruby

Thành thạo đầu ra mã với Awesome Print: Ruby Gem cho logging sạch, dễ đọc

Awesome print là gem đẹp định dạng đầu ra trong irb & pry dễ đọc hơn.

Ví dụ…

Đây hiển thị hash với awesome_print:

Thành thạo đầu ra mã với Awesome Print: Ruby Gem cho logging sạch, dễ đọc

Nhưng nó hoạt động như thế nào?

“Sự thật chỉ tìm thấy ở một nơi: mã nguồn.” ― Robert C. Martin

Hãy xem mã nguồn!

In ấn Awesome

Tôi thích bắt đầu đọc mã với tổng quan cấu trúc project (file & folder), rồi đặt câu hỏi tập trung khám phá.

Câu hỏi đầu tiên:

awesome_print thay đổi đầu ra pry như thế nào?

Đặt giả thuyết:

“Gem này có thể thay thế $stdout để capture đầu ra pry & làm đẹp.”

Nhưng triển khai này không cho tùy chỉnh đầu ra, như pretty_print (thư viện chuẩn Ruby).

Cũng phải parse, thậm chí eval mã, ý kiến không hay!

Tiếp:

Tôi xem gem nạp như thế nào.

Điều này cho entry point vào mã.

Nạp Awesome Print

Để load awesome_print trên pry làm:

require 'awesome_print'
AwesomePrint.pry!

Bây giờ tìm pry! định nghĩa ở đâu.

Dùng “search in directory” trong Atom.

Mã:

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

Có vẻ Pry cho phép sửa đầu ra bằng set giá trị print.

Vậy trả lời câu hỏi “bắt đầu đâu” 🙂

Muốn học thêm “proc” này? Đọc “Hướng dẫn tối thượng Blocks, Procs & Lambdas”. Chương mẫu từ sách Ruby Deep Dive.

Proc này nhận 2 tham số:

  • output
  • value

Và gọi 2 phương thức trên đối tượng đó.

Câu hỏi tiếp:

Phương thức ai này là gì?

Đó là phương thức định nghĩa trên module Kernel:

def ai(options = {})
  ap = AwesomePrint::Inspector.new(options)
  awesome = ap.awesome(self)
  if options[:html]
    awesome = "</pre>#{awesome}</pre>"
  end
  awesome = awesome.html_safe if defined? ActiveSupport
  awesome
end
alias :awesome_inspect :ai

Vì mọi object include Kernel mặc định, chúng có phương thức ai.

Bây giờ đào sâu hơn xem class Inspector hoạt động ra sao.

Class Inspector

Ngay sau mở inspector.rb thấy hash options khổng lồ trong initialize.

Phần của nó:

@options = {
  indent: 4,        # Số space indent
  index: true,      # Hiển thị index mảng
  html: false,      # Dùng ANSI color thay HTML
  multiline: true,  # Hiển thị đa dòng
  # ...
}

Sau đó code này:

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

Khởi tạo 2 object xử lý format & indentation.

Cái Thread.current là gì?

Cho truy cập thread hiện tại. Dù không dùng thread app vẫn có thread “main”.

Hằng AP định nghĩa đầu inspector.rb:

AP = :__awesome_print__

Vậy đang xảy ra gì?

Awesome print dùng Thread.current & key __awesome_print__ lưu data chỉ có trên thread hiện tại.

Dùng tránh vấn đề multi-threading.

Định dạng Awesome

Xem mã format output, xảy ra trong class AwesomePrint::Formatter.

Cách hoạt động: inspector (object tạo bởi ai) gọi format.

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

Phương thức format trên Formatter tìm cách tốt nhất xử lý loại object & gọi phương thức khác dùng metaprogramming.

Phương thức:

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 fallback object.inspect.
  end
  awesome
end

Để hiểu Formatter cần xem cast:

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

Hằng CORE là mảng symbol class Ruby core & :self symbol nghĩa “không tìm thấy” (chỉ ví dụ này).

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

Điều xảy ra:

Nếu object format nằm trong danh sách “core class” nó nhận format chuyên biệt.

Ngược lại, nhận format chung.

Formatter chuyên biệt định nghĩa dưới lib/awesome_print/formatters/ bao gồm Array, Hash & Class.

Ví dụ formatter cho class:

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

Bạn tự viết formatter nếu muốn.

Tóm tắt

Bạn đã học gem Awesome Print, cho hiển thị đối tượng như mảng & hash đẹp.

Hy vọng bạn thích & học được điều mới!

Vui lòng chia sẻ bài viết trên mạng xã hội yêu thích để nhiều người học 🙂