Bản in tuyệt vời là một viên ngọc đẹp giúp định dạng đầu ra của bạn trong irb
&pry
để làm cho nó dễ đọc hơn.
Ví dụ…
Đây là những gì hiển thị một hàm băm với awesome_print
trông giống như:
Nhưng điều này hoạt động như thế nào?
"Sự thật chỉ có thể được tìm thấy ở một nơi:mã." - Robert C. Martin
Hãy xem mã nguồn để tìm hiểu!
In Awesomely
Tôi muốn bắt đầu phiên đọc mã với cái nhìn tổng quan nhanh về cấu trúc dự án (tệp &thư mục), sau đó tôi muốn đặt một câu hỏi để tập trung khám phá về sau.
Vì vậy, câu hỏi đầu tiên tôi nghĩ ra là :
Làm thế nào để awesome_print
thay đổi đầu ra của pry?
Bây giờ tôi đội mũ thám tử của mình và đưa ra giả thuyết :
“Đá quý này có thể thay thế cho $stdout
để nó có thể nắm bắt đầu ra của pry &sau đó làm cho nó đẹp. ”
Nhưng việc triển khai này sẽ không cho phép bạn tùy chỉnh đầu ra của mình, chẳng hạn như pretty_print
(từ Thư viện Chuẩn của Ruby).
Ngoài ra, chúng tôi sẽ phải phân tích cú pháp hoặc thậm chí đánh giá mã, không phải là một ý tưởng tuyệt vời!
Tiếp theo :
Tôi đã xem xét cách nạp đá quý này.
Điều này sẽ cung cấp cho chúng tôi một điểm vào mã.
Đang tải bản in tuyệt vời
Để tải awesome_print
về sơ suất, bạn phải làm điều này:
require 'awesome_print' AwesomePrint.pry!
Bây giờ chúng ta muốn tìm pry!
ở đâu được xác định.
Tôi đã sử dụng tính năng “tìm kiếm trong thư mục” trong Atom để tìm nó.
Đây là mã :
def pry! Pry.print = proc { |output, value| output.puts value.ai } if defined?(Pry) end
Có vẻ như Pry cho phép bạn sửa đổi đầu ra của nó bằng cách đặt giá trị của print
.
Vì vậy, câu trả lời cho câu hỏi “bắt đầu từ đâu” của chúng tôi 🙂
Bạn muốn tìm hiểu thêm về điều “proc” này? Đọc “Hướng dẫn cơ bản về Blocks, Procs &Lambdas”. Đây là một chương mẫu từ cuốn sách Ruby Deep Dive của tôi.
Proc này có hai đối số :
- đầu ra
- giá trị
Và nó gọi hai phương thức trên các đối tượng đó.
Câu hỏi tiếp theo :
Đây là gì ai
phương pháp?
Đó là một phương thức được xác định trên Kernel
mô-đun:
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} "awesome =awesome.html_safe nếu được định nghĩa? ActiveSupport end awesomeendalias:awesome_inspect:ai
Bởi vì tất cả các đối tượng bao gồm Kernel
theo mặc định, chúng sẽ có ai
này phương pháp có sẵn trên chúng.
Bây giờ chúng ta hãy tìm hiểu sâu hơn một chút và xem Inspector
này như thế nào hoạt động của lớp.
Lớp thanh tra
Ngay sau khi mở inspector.rb
chúng tôi tìm thấy một hàm băm tùy chọn lớn bên trong initialize
phương pháp.
Đây là một phần của nó :
@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. # ... }
Sau đó, chúng tôi có thể tìm thấy mã này :
@formatter = AwesomePrint::Formatter.new(self) @indentator = AwesomePrint::Indentator.new(@options[:indent].abs) Thread.current[AP] ||= []
Vì vậy, điều này thiết lập thêm hai đối tượng dường như xử lý chính việc định dạng và thụt lề của mã.
Nhưng điều gì xảy ra với Thread.current
này điều gì?
Chà, điều này cho phép bạn truy cập vào chuỗi hiện tại. Ngay cả khi bạn không sử dụng các chuỗi trong ứng dụng của mình, bạn sẽ có một, chuỗi “chính”.
AP
này hằng số chỉ là một hằng số được xác định ở đầu inspector.rb
:
AP = :__awesome_print__
Vậy điều gì đang xảy ra ở đây?
Bản in tuyệt vời đang sử dụng Thread.current
&__awesome_print__
để lưu một số dữ liệu chỉ có sẵn trên chuỗi hiện tại.
Điều này được sử dụng để tránh các vấn đề với đa luồng.
Định dạng tuyệt vời
Hãy xem mã định dạng đầu ra, điều này xảy ra bên trong AwesomePrint::Formatter
lớp học.
Cách thức hoạt động là trình kiểm tra (đối tượng được tạo bởi ai
phương thức) sẽ gọi định dạng format
phương pháp.
def unnested(object) @formatter.format(object, printable(object)) end
Sau đó, format
này trên Formatter
lớp sẽ tìm ra cách tốt nhất để xử lý loại đối tượng này và gọi một phương thức khác bằng cách sử dụng một chút lập trình siêu hình.
Đây là phương pháp :
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
Để hiểu Formatter
này chúng ta cũng cần xem xét cast
phương pháp:
def cast(object, type) CORE.grep(type)[0] || :self end
CORE
hằng số là một mảng các ký hiệu đại diện cho các lớp Ruby cốt lõi &:self
là một biểu tượng được sử dụng để có nghĩa là "không tìm thấy" (chỉ trong ví dụ này, không phải trong Ruby nói chung).
CORE = [:array, :bigdecimal, :class, :dir, :file, :hash, :method, :rational, :set, :struct, :unboundmethod]
Điều gì xảy ra là đây :
Nếu đối tượng đang được định dạng nằm trong danh sách "lớp lõi" thì đối tượng đó sẽ có định dạng chuyên biệt.
Nếu không, nó sẽ nhận được một cái chung chung.
Các bộ định dạng chuyên dụng được định nghĩa theo lib/awesome_print/formatters/
thư mục &bao gồm những thứ như Array
, Hash
&Class
.
Ví dụ:đây là phương thức định dạng cho các lớp:
def format superclass = klass.superclass if superclass colorize("#{klass.inspect} < #{superclass}", :class) else colorize(klass.inspect, :class) end end
Bạn có thể viết bộ định dạng của riêng mình nếu bạn muốn.
Tóm tắt
Bạn đã tìm hiểu về đá quý Awesome Print, cho phép bạn hiển thị các đối tượng như mảng và hàm băm một cách đẹp mắt.
Hy vọng bạn thích điều này và học được điều gì đó mới!
Hãy chia sẻ bài đăng này trên mạng xã hội yêu thích của bạn ngay bây giờ để nhiều người có thể học hỏi 🙂