Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

コードリーディングアドベンチャー:素晴らしいプリントジェム

素晴らしいプリントは、出力をirbでフォーマットする素晴らしい宝石です。 &pry 読みやすくするため。

例…

これは、awesome_printでハッシュを表示するものです。 次のようになります:

コードリーディングアドベンチャー:素晴らしいプリントジェム

しかし、これはどのように機能しますか?

「真実は、コードという1つの場所でしか見つけることができません。」 ―ロバートC.マーチン

ソースコードを見て調べてみましょう!

素晴らしい印刷

プロジェクト構造(ファイルとフォルダー)の概要を簡単に説明してコード読み取りセッションを開始した後、質問をして、今後の調​​査に集中するのが好きです。

最初に思いついた質問はです :

awesome_printはどうですか pryの出力を変更しますか?

今、私は探偵の帽子をかぶって仮説を立てます

「この宝石は$stdoutに取って代わる可能性があります これにより、こじ開けの出力をキャプチャして、きれいにすることができます。」

ただし、この実装では、pretty_printのように出力をカスタマイズすることはできません。 (Rubyの標準ライブラリから)あります。

また、コードを解析したり、評価したりする必要がありますが、これは素晴らしいアイデアではありません。

次へ

この宝石がどのようにロードされるかを調べました。

これにより、コードへのエントリポイントが提供されます。

素晴らしいプリントの読み込み

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」についてもっと知りたいですか? 「Blocks、Procs、Lambdasの究極のガイド」をお読みください。これは私のRubyDeepDive本のサンプルの章です。

このプロシージャは2つの引数を取ります

  • 出力

そして、それらのオブジェクトに対して2つのメソッドを呼び出します。

次の質問

この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} "awesome =awesome.html_safe定義されている場合? ActiveSupport end awesomeendalias:awesome_inspect:ai

すべてのオブジェクトにKernelが含まれているため デフォルトでは、このaiがあります それらで利用可能な方法。

それでは、もう少し深く掘り下げて、このInspectorがどのように機能するかを見てみましょう。 クラスは機能します。

インスペクタークラス

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] ||= []

したがって、これにより、フォーマット自体とコードのインデントを処理するように見えるオブジェクトがさらに2つ設定されます。

しかし、このThread.currentとは何ですか 事?

これにより、現在のスレッドにアクセスできます。アプリケーションでスレッドを使用していない場合でも、「メイン」スレッドがあります。

このAP 定数は、inspector.rbの先頭で定義されている定数です。 :

AP = :__awesome_print__

では、ここで何が起こっているのでしょうか?

素晴らしい印刷はThread.currentを使用しています &__awesome_print__ 現在のスレッドでのみ利用可能なデータを保存するためのキー。

これは、マルチスレッドの問題を回避するために使用されます。

素晴らしいフォーマット

AwesomePrint::Formatter内で発生する出力フォーマットコードを見てみましょう。 クラス。

これが機能する方法は、インスペクター(aiによって作成されたオブジェクト)です。 メソッド)はformatを呼び出します メソッド。

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

次に、このformat Formatterのメソッド クラスは、このタイプのオブジェクトを処理し、メタプログラミングを少し使用して別のメソッドを呼び出すための最良の方法を見つけます。

方法は次のとおりです

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

このFormatterを理解するには クラスでは、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などを含める 、HashClass

たとえば、クラスのフォーマッタメソッドは次のとおりです。

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

必要に応じて、独自のフォーマッターを作成できます。

概要

配列やハッシュなどのオブジェクトを適切に表示できるAwesomePrintgemについて学習しました。

これを楽しんで、何か新しいことを学んだことを願っています!

より多くの人が学ぶことができるように、今すぐお気に入りのソーシャルネットワークでこの投稿を共有してください🙂


  1. VCRGemを使用してテストスイートを改善する方法

    Rubyアプリケーションが何らかの外部APIを使用している場合は、おそらくテストとAPIレートの制限が遅いという問題に直面している可能性があります。 。 解決策は何ですか? クライアントライブラリからHTTPメソッドを手動でスタブし、事前に決定された応答を返すことができます。 しかし、それは多くの作業と醜いコードです! より良い解決策は、 Webmock+VCRのような宝石の強力な組み合わせを使用することです。 。 WebMockは、次のような一般的なHTTPライブラリからのHTTPリクエストをインターセプトします。 net / http ファラデー RestClient

  2. コードリーディングアドベンチャー:素晴らしいプリントジェム

    素晴らしいプリントは、出力をirbでフォーマットする素晴らしい宝石です。 &pry 読みやすくするため。 例… これは、awesome_printでハッシュを表示するものです。 次のようになります: しかし、これはどのように機能しますか? 「真実は、コードという1つの場所でしか見つけることができません。」 ―ロバートC.マーチン ソースコードを見て調べてみましょう! 素晴らしい印刷 プロジェクト構造(ファイルとフォルダー)の概要を簡単に説明してコード読み取りセッションを開始した後、質問をして、今後の調​​査に集中するのが好きです。 最初に思いついた質問はです : aw