読みましょう-雄弁なルビー- CH 4


おそらくRubyをRubyistのようにプログラムすることを学ぶ私の個人的なお勧めです.Eloquent Ruby 私がこの日に頻繁に推薦する本です.それは、それが2011年にリリースされて、それ以来、ものが少し変わったと言いました.
このシリーズは、2011年(Ruby 1.9.2を中心に)から変更されたか、更新された可能性があることに注意して、雄弁ルビーの上で読むことに集中します(2021 -ルビー3.0 . x).

Note: This is an updated version of a previous unfinished Medium series of mine you can find here.



第4章Rubyのスマート文字列を利用する
この章はString そして、イントロは私が非常に真実であるとわかった何かを言及します.ほとんどの人々はプログラマが主に番号を扱うと仮定するでしょう.
データを解析し、それを直列化し、ユーザ入力、本当にテキストの周りのプログラミングセンターの多くString s、それの残りの多くがコレクションのまわりで終わるところ.私にとって、数字はそれらの2つにほとんど遠く3番目です、しかし、それは個人的な意見です.

文字列で来る
ルビーはRubyであり、本を作るにはいくつかの方法があることを示しているString , Rubyでとても多くの他のもののように.一般的に私のために従う簡単なルールは、単一引用符で(完全に意味のない)パフォーマンスの違いにもかかわらず、すべてのために二重引用符を使用することでした.
とにかく、単一引用符でバックスラッシュの例をいくつか挙げます.
# Escaping a single quote mark
a_string_with_a_quote = 'Say it ain\'t so!'

# Escaping a backslash
a_string_with_a_backslash = 'This is a backslash: \\'
今、私がダブル引用符が一般的により簡単になると言う理由は、1つの引用されたストリングが特別な構文を評価するよりむしろ文字通りに扱うということです
single_quoted = 'I have a tab: \t and a newline: \n'
double_quoted = "I have a tab: \t and a newline: \n"
としても同様に補間に適用されます.
author = "Ben Bova"
title = "Mars"

puts "#{title} is written by #{author}"
# Mars is written by Ben Bova
#
puts '#{title} is written by #{author}'
# #{title} is written by #{author}
一般的に引用符の1つの弱さは、次の例のいくつかの例として、お互いに混合を取得するときです.
str = "\"Stop\", she said, \"I cannot deal with the backslashes.\""

# versus using single quotes to wrap
str = '"Stop", she said, "I cannot deal with the backslashes."'
...しかし、本と同様に、私はまた、これがどこにあるかに同意します%q 構文はより便利です.
str = %q("Stop", she said, "I can't live without 's and "s.")
また、使用することができた事実に入る%q[] or %q$$ またはとにかく、おそらくベストを好む%q() 一般的に対処するのは簡単です.
今すぐ次のいずれかを覚えて%q それは単一引用符と同じです%Q はダブルです.私の前の言及と同様に、私は一般的には、特定の理由を持っていない限り、ダブル引用符を好む%Q これらの場合.
それから、本は異所に入ります:
multi_line = <<EOF
Here's a lot of text. Some
of it goes on multiple lines!
EOF
ここでの弱さは言及しない<<TAG 構文はスペースに敏感です:
m1 = <<EOF
Here's a lot of text. Some
of it goes on multiple lines!
EOF

m2 = <<EOF
    Here's a lot of text. Some
    of it goes on multiple lines!
EOF
このようなコードがあれば、
module Container
  class Something
    def a_method
      puts <<EOF
        Text here that is slightly long
        because why not?
      EOF
    end
  end
end
...すべては、左にインデント?今ではString . おそらく、最近ではなく、より一般的な"squiggly "IradDoc構文が必要になります.
module Container
  class Something
    def a_method
      puts <<~EOF
        Text here that is slightly long
        because why not?
      EOF
    end
  end
end
非常に多くの理由がない<<<<~ , Squiggly構文が自動的に左の少なくともインデントの行にトリミングするので、それは長いテキストのために非常に非常に役に立ちます.

もう一つのAPI

ストリッピングとチョピング
Array Rubyのクラスの多くの他の多くの本当の楽しみは、彼らが来ているメソッドを取得し、ルビーのString クラスにはいくつかあります.本が始まるlstrip 一つは
' hello'.lstrip
# => 'hello'
...直観はサーブするかもしれないrstrip , とstrip どちらが終わるのか.私が使用するより一般的なもの、および本の言及はchomp を返します.String :
"It was a dark and stormy night\n".chomp
# => "It was a dark and stormy night"

# ...but only one newline
"hello\n\n\n".chomp
# => "hello\n\n"
今、私は常に忘れて、使用の多くを見つけていない方法.chop :
"hello".chop
# => "hell"
...それが何であっても最後の文字をオフにします.個人的に私は本当にこの1つの使用の多くを見ていないが、それは私です.

ケース操作
次に、文字列の場合について説明します.
"hello".upcase
# => "HELLO"

"HELLO".downcase
# => "hello"

"Hello"
# => "hELLO"
最近のバージョンも追加capitalize :
"hello".capitalize
# => "Hello"
...以前は柵専用であったが、一般的に十分な用法では意味をなす.

置換
次に、置換を行います.
"It is warm outside".sub("warm", "cold")
# => "It is cold outside"
...しかし、それは1つの代用だけで動きます.あなたが欲しいgsub 複数の
"yes yes".sub("yes", "no")
# => "no yes"

"yes yes".gsub("yes", "no")
# => "no no"
さて、本はこれに言及しないとバンを残してsub! , gsub! ) これらのメソッドの変形は少し後になりますが、危険な違いがあります.
リマインダーバンメソッドとしては、一般的に基本的なオブジェクトを突然変異、何か注意してください.多くの場合、彼らは戻りますnil 彼らが最適化理由のために修正をしないならば、そして、それがそうするならば、オブジェクト.つまり、連鎖がループをスローします.
"abcd".sub!("ab", "ba").sub!("cd", "dc")
# => "badc"

"abcd".sub!("ac", "ba").sub!("cd", "dc")
# NoMethodError (undefined method `sub!' for nil:NilClass)
キャッチ?ほとんどのこれらのメソッドをコーディングしていない、それはバグの本当の厄介なソースすることができます.一般に、パフォーマンスの向上を必要としない限り、Bangメソッドを避ける.ほとんどの時間をしない.

分割
次はsplit , これは我々が分割することができますString s文字か、指定されていない場合に空白文字
"It was a dark and stormy night".split
# => ["It", "was", "a", "dark", "and", "stormy", "night"]
次に、文字ベースの分割の例を示します.
"Bill:Shakespeare:Playwright:Globe".split(":")
# => ["Bill", "Shakespeare", "Playwright", "Globe"]
...でも一つはsplit 実際には、2つの引数をとります.デリミタ(項目を区切るもの)と最大数に達する数の数を指定します.
%Q(data: { "a": 1, "b": 2 }).split(":")
# => ["data", " { \"a\"", " 1, \"b\"", " 2 }"]

%Q(data: { "a": 1, "b": 2 }).split(":", 2)
# => ["data", " { \"a\": 1, \"b\": 2 }"]
注意してください.それは微妙です、しかしString ここでは、値がJSONのような形式である重要な値のより多くです: グローバルに、しかし、一度、キーと値が分離されるところ.また、おそらくsplit(/: */, 2) 両者の間のスペースを説明する.

行、文字、およびバイト数
何回か来ている1つのトピックはなぜですかString 持っていないeach メソッド.繰り返し、アイテムは何でしょうか?String sは、さまざまな概念の多くのコレクションです.バイト、文字、codepoints、行、おそらく多くの私は忘れている.ここに1つの明白なiterableがない点.
だからRubyは自分で決めることができます.
"some\nlines\nof\ntext".lines
# => ["some\n", "lines\n", "of\n", "text"]

"some\nlines\nof\ntext".each_line { |line| puts line }
# some
# lines
# of
# text
#  => "some\nlines\nof\ntext"

"abc".chars
# => ["a", "b", "c"]

"abc".each_char { |c| puts c }
# a
# b
# c
#  => "abc"

"abc".bytes
# => [97, 98, 99]

"abc".each_byte { |b| puts b }
# 97
# 98
# 99
#  => "abc"

"😅🎉✨".codepoints
# => [128517, 127881, 10024]

"😅🎉✨".each_codepoint { |c| puts c }
# 128517
# 127881
# 10024
#  => "😅🎉✨"
この本はRubyが許可することに言及しているString sに対するインデックス[] 以下のように:
"abc"[0]
# => "a"
...これは、文字を繰り返すことを意味するが、一度絵文字とユニコードと非ASCIIのすべての楽しい魔法になるString sそれは少し仕事を難しくし始める.
としても、本の章の最後に置くことを覚えて[-1] は最後の文字と範囲を有効にする[3..5] ):
"some text"[-1]
# => "t"

"some text"[3..5]
# => "e t"

インザワイルド
その本はその後、いくつかの現実世界の例に入るString 操作を開始html_escape RSSライブラリの標準ライブラリから
def html_escape(s)
  s
    .to_s
    .gsub(/&/, "&amp;")
    .gsub(/\"/, "&quot;")
    .gsub(/>/, "&gt;")
    .gsub(/</, "&lt;")
end
...けれどもHash フォームは後で動作するほうが簡単です.
ESCAPED_ENTITIES_MAP = {
  "&"  => "&amp;",
  "\"" => "&quot;",
  ">"  => "&gt;",
  "<"  => "&lt;",
}

ESCAPED_ENTITIES = Regexp.union(ESCAPED_ENTITIES_MAP.keys)

def html_escape(s)
  s.to_s.gsub(ESCAPED_ENTITIES, ESCAPED_ENTITIES_MAP)
end

html_escape(%Q(<a href="link.html?a&b">text</a>))
# => "&lt;a href=&quot;link.html?a&amp;b&quot;&gt;text&lt;/a&gt;"
知っている便利な、とにかく、トピックに戻る.
この本は、いくつかのレールの概念、インフレクタと多元化に言及します.内部のクラスを決定するのに使用されますcurrent_employee.rbCurrentEmployee , と関連DBテーブルはcurrent_employee . として、本は、これが行われる言及String 処理
これは規則のセットを介して、特に多元化の周り、不規則な多元化のようなケースのように動作しますperson 多様化people :
inflect.irregular("person", "people")
inflect.irregular("man", "men")
inflect.irregular("child", "children")
inflect.irregular("sex", "sexes")
...を介してgsub! , を返します.nil 前述の
inflections.plurals.each do |(rule, replacement)|
  break if result.gsub!(rule, replacement)
end
今1つはおそらくこれを行うことができますfind 代わりに、突然変異を避けるが、Railsといくつかの最適化ケースを知っているかもしれません.

トラブルがない
ルビーString sは変更可能です.このあたりの方法がありますfreeze と凍結した文字列リテラル
# frozen_string_literal: true

"string".freeze
つまり、上記からのそれらのBangメソッドのどれかが、基礎をつぶすでしょうString :
first_name = "Susan"
given_name = first_name

first_name[-2..-1] = "ie"
# => "ie"

first_name
# => "Susie"

given_name
# => "Susie"

first_name.downcase!
# => "susie"

first_name
# => "susie"

given_name
# => "susie"
あなたが本当に本当にそれを必要としない限り、物事を変異するときに注意してくださいが、ほとんどの時間?もうだめだ.

ラッピング
これは第4章を包みますString ルビーのsですが、我々がRegexに入る第5章の本当の面白い部分のいくつかを残します.
平均時間で?その本は正しい.String sはRubyで例外的に一般的です、そして、それらを扱うことはあなたがRubyですることの重要な部分であるでしょう.それらのドキュメントで快適になることは確かに賢明な投資です.