D IT Y

タマキ工務店のIT日記

チェリー本輪読会 第7週目まとめ

f:id:shirotamaki:20210619091936p:plain

🍒 はじめに

チェリー本輪読会の第7週目のエントリーになります。

輪読会の概要については第1週目にまとめています。

🍒 輪読会 第7週目まとめ

第5章5.4.1〜第5章5.8まで

期間:2021年07月5日〜2021年07月9日

ハッシュのキーにはシンボルを使う

チェリー本輪読会 第6週目まとめ - D IT Yのハッシュの書き方でも言及しましたが、ハッシュのキーは文字列とシンボルを使うことができますが、シンボルを使うことが推奨されています。理由としては、文字列より高速に処理でき、イミュータブルなので勝手に値が変えられる心配がないためです。

また、ハッシュのキーを指定する際、文字列とシンボルを混在して使用することも可能ですが、混乱を招くため統一したほうが良いです。

下記はキーを混在して書いた例です。エラーは起きませんが、統一感がなく混乱を招きます。

*irb(main):001:0> records = { 'first_single' => 'LAMP', :second_sigle => 'ダイヤモンド', third_single: '天体観測'
 }*
=> {"first_single"=>"LAMP", :second_sigle=>"ダイヤモンド", :third_single=>"天体観測"}

メソッドのキーワード引数

可読性を上げるためにキーワード引数を使用します。

def メソッド名(キーワード引数1: 引数1の値,  キーワード引数2: 引数2の値)
    #  メソッドの実装
end

キワード引数名: 値の形式は、引数名だけではなく、デフォルト値の指定も同時に行っています。

irb(main):022:1* def count(math: 0, english: 0)
irb(main):023:1*   puts total_score = math + english
irb(main):024:0> end
=> :count
irb(main):025:0> count(math: 90, english: 80)
170
=> nil
irb(main):026:0> count(math: 50)
50
=> nil

キーワード引数がシンボルではない話

輪読会で話題に上がった内容ですが、下記の記事が参考になりました。

Rubyのキーワード引数はシンボルっぽく定義するけど、シンボルそのものではない、という話 - Qiita

ハッシュで使用頻度の高いメソッド

keysメソッド

全キーを配列で返します。指定したキーで返ってきます。(文字列なら文字列。シンボルならシンボルで返ってきます)

irb(main):001:0> records = { 'first_single' => 'LAMP', second_sigle: 'ダイヤモン
' }
=> {"first_single"=>"LAMP", :second_sigle=>"ダイヤモンド"}
irb(main):002:0> records.keys
=> ["first_single", :second_sigle]

Hash#keys (Ruby 3.0.0 リファレンスマニュアル)

valuesメソッド

ハッシュの値を配列として返します。

irb(main):006:0> records = { 'hit_song' => 'およげ!たいやきくん', number_of_sal
es: 4570000 }
=> {"hit_song"=>"およげ!たいやきくん", :number_of_sales=>4570000}
irb(main):007:0> records.values
=> ["およげ!たいやきくん", 4570000]

class Hash (Ruby 3.0.0 リファレンスマニュアル)

has_key? メソッド

エイリアスメソッド(key? /include?/member?)

ハッシュの中に指定されたキーが存在するかどうか確認するメソッドです。

エイリアスメソッドであるinclude?が、英単語的に分かりやいのでこちらを採用します。

irb(main):010:0> hit_records = { mj: 'スリラー', eagles:'イーグルスベスト版', ac
dc: 'バックインブラック' }
=> {:mj=>"スリラー", :eagles=>"イーグルスベスト版", :acdc=>"バックインブラ...
irb(main):011:0> hit_records.include?(:mj)
=> true
irb(main):012:0> hit_records.include?(:beatles)
=> false

Hash#has_key? (Ruby 3.0.0 リファレンスマニュアル)

** でハッシュを展開させる

作成したハッシュを別のハッシュの中で展開することができます。

変数の前に**ダブルスプラットを書きます。**hit_records

mergeメソッドも同じ結果が得られます。{ acdc: 'バックインブラック'}.merge(hit_records) 

irb(main):013:0> hit_records = { mj: 'スリラー', eagles:'イーグルスベスト版'}
=> {:mj=>"スリラー", :eagles=>"イーグルスベスト版"}
irb(main):014:0> { acdc: 'バックインブラック', **hit_records}
=> {:acdc=>"バックインブラック", :mj=>"スリラー", :eagles=>"イーグルスベスト版"}

ちなみに、*を使って展開する方法は、splat展開と言います。

第4週目で取り上げた内容です。

チェリー本輪読会 第4週目まとめ - D IT Y

メソッドの定義に存在しないキワード引数を受けとる

**変数名として引数へ用意します。

キーワード引数を使うメソッドに、存在しないキーワードを渡すとエラーが発生します。エラーを回避するために、**を付けた引数を用意することで、指定されていないキーワードを受け取ることができます。

irb(main):015:1* def hit_records(mj: 'スリラー', eagles:'イーグルスベスト版', **others)
irb(main):016:1*   puts others
irb(main):017:0> end
=> :hit_records
irb(main):020:0> hit_records(mj: 'スリラー', eagles: 'イーグルスベスト版', acdc: 'バックインブラック')
{:acdc=>"バックインブラック"}
=> nil

( )の省略

Rubyではメソッドの呼び出しの( )を省略することができます。

# 同じ意味
puts ('hit_records')
puts 'hit_records'

しかし、ハッシュキーワード引数では、( )を省略できない場合があります。

以下は、メソッドの呼び出し時に( )を省略した際、エラーとなります。

irb(main):021:1* def hit_records(artists = {})
irb(main):022:1*   puts artists
irb(main):023:0> end
=> :hit_records
irb(main):024:0> hit_records {mj: 'スリラー', eagles:'イーグルスベスト版'}
/Users/shiro/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/irb-1.3.6/lib/irb/workspace.rb:116:in `eval': (irb):24: syntax error, unexpected ':', expecting '}' (SyntaxError)
hit_records {mj: 'スリラー', eagles:'イ...

( ) を付け加えると実行できます。

irb(main):025:1* def hit_records(artists = {})
irb(main):026:1*   puts artists
irb(main):027:0> end
=> :hit_records
irb(main):028:0> hit_records ({mj: 'スリラー', eagles:'イーグルスベスト版'})
{:mj=>"スリラー", :eagles=>"イーグルスベスト版"}
=> nil

第2引数にハッシュが来る場合は、省略してもエラーになりません。

irb(main):033:1* def hit_records(genre, artists = {})
irb(main):034:1*   puts artists
irb(main):035:0> end
=> :hit_records
irb(main):036:0> hit_records 'pop', {mj: 'スリラー', eagles:'イーグルスベスト版'}
{:mj=>"スリラー", :eagles=>"イーグルスベスト版"}
=> nil

Railsでは省略している場合が多い

Railsで用意しているメソッドは、基本的に( ) は省略していることが多いようです。

link_torender など。

# Railsのコード抜粋

<%= render 'form', book: @book %>

<%= link_to 'Back', books_path %>

RubyDSL(←チェリー本12章参照)っぽく見えるメソッドを省略する傾向があるようです。

DSL(ドメイン固有言語)とは - IT用語辞典 e-Words

これからRailsを学ぶ上で覚えておきたいと思いました。

ハッシュへ初期値を設定する

ハッシュへ存在していないキーを指定するとnilが返ってきます。

irb(main):006:0> hit_records = {}
irb(main):007:0> hit_records[:mj]
=> nil

Hash.newを使い、引数へ初期値となる値を入力することで、指定できます。

バックインブラック を初期値として指定しています。

irb(main):037:0> hit_records = Hash.new('バックインブラック')
irb(main):038:0> hit_records[:acdc]
=> "バックインブラック"

同じく値に初期値を設定し、変数a、変数bへそれぞれ別のキーを指定して代入してみます。

変数a、変数bともに代入できました。aとbは同じオブジェクトIDを保持しています。

irb(main):044:0> hit_records = Hash.new('バックインブラック')
=> {}
irb(main):045:0> a = hit_records[:acdc]
=> "バックインブラック"
irb(main):046:0> b = hit_records[:mj]
=> "バックインブラック"

insertメソッドを使い、変数aの文字列を変更してみます。

String#insert (Ruby 3.0.0 リファレンスマニュアル)

変数aに変更を加えた場合、変数bも同じオブジェクトIDなので、値も一緒に変わってしまいます。

irb(main):058:0> a.insert(0, "ヒットアルバム_")
=> "ヒットアルバム_バックインブラック"
irb(main):059:0> b
=> "ヒットアルバム_バックインブラック"

上記の問題を回避するためには、{ }を使う必要があります。

変数aと変数bは異なるオブジェクトIDです。変数aを変更しても変数bは変わりません。

irb(main):066:0> hit_records = Hash.new{'バックインブラック'}
=> {}
irb(main):067:0> a = hit_records[:acdc]
=> "バックインブラック"
irb(main):068:0> b = hit_records[:mj]
=> "バックインブラック"
irb(main):069:0> a.insert(0, "ヒットアルバム_")
=> "ヒットアルバム_バックインブラック"
irb(main):070:0> b
=> "バックインブラック"

to_aメソッド, to_hメソッド, to_symメソッド

ハッシュから配列へ変換する場合はto_aメソッドを使用します。

配列の配列(2次元配列)が返ります。

irb(main):003:0> hash = { mj: 'king_of_pop', elvis:'king_of_rock', jb: 'king_of_
soul' }
=> {:mj=>"king_of_pop", :elvis=>"king_of_rock", :jb=>"king_of_soul"}
irb(main):004:0> hash.to_a
=> [[:mj, "king_of_pop"], [:elvis, "king_of_rock"], [:jb, "king_of_soul"]]

反対に、to_hメソッドと使用することでハッシュへ戻すことができます。

irb(main):005:0> arry =  [[:mj, "king_of_pop"], [:elvis, "king_of_rock"], [:jb,
"king_of_soul"]]
=> [[:mj, "king_of_pop"], [:elvis, "king_of_rock"], [:jb, "king_of_soul"]]
irb(main):006:0> arry.to_h
=> {:mj=>"king_of_pop", :elvis=>"king_of_rock", :jb=>"king_of_soul"}

to_symメソッドを使用すると、文字列をシンボルへ変換することができます。

irb(main):013:0> moji = 'キング'
=> "キング"
irb(main):014:0> moji.to_sym
=> :キング

反対にシンボルを文字列に戻す場合は、to_sメソッドになります。

irb(main):017:0> symbol = :キング
=> :キング
irb(main):018:0> symbol.to_s
=> "キング"

イディオム

イディオムとは、慣用句、成句、熟語などと訳されます。習慣として長い間広く使われてきた定番の書き方をイディオムと言います。

イディオム - Wikipedia

ここでは、Rubyでよく使われるイディオムを紹介します。

ぼっち演算子 lonely operator

&. 演算子を使ってメソッドを呼び出すと、メソッドを呼び出されたオブジェクトがnilでない場合はその結果を、nilだった場合はnilを返します。

基本的な使い方は、オブジェクト&.メソッドになります。

irb(main):039:0> content  = 'コンテンツ'
=> "コンテンツ"
irb(main):040:0> content&.to_sym
=> :コンテンツ
irb(main):041:0> content = nil
=> nil
irb(main):042:0> content&.to_sym
=> nil

&. 演算子が下記のような姿に見えるため、通称「ぼっち演算子」と呼ばれています。

www.instagram.com

nilガード

通称「nilガード」と呼ばれている||=を使った自己代入の書き方になります。

下記、変数contentがnilまたはfalseであれば、||=を使い代入を試みた場合、コンテンツが代入されます。

irb(main):043:0> content = nil
=> nil
irb(main):044:0> content ||= 'コンテンツ'
=> "コンテンツ"

しかし、すでに変数contentの中身が存在する場合は代入ができません。

irb(main):048:0> content = 'コンテンツ'
=> "コンテンツ"
irb(main):049:0> content ||= '別のコンテンツ'
=> "コンテンツ"

メモ化などでも使われ、以下はSinatraを使ってアプリを作成していた際に使用したnilガードです。

PG.connect(dbname: 'memos') というデータベースへ繋ぐ処理が重いため、毎回接続処理を行なわないようにしました。nilガードを使い@connectionへキャッシュとして保持する目的で使用しました。

メモ化 - Wikipedia

class Memo
  def conn
    @connection ||= PG.connect(dbname: 'memos')
  end
en

!! ダブルバンを使った真偽値の型変換

! バンひとつだと、否定の演算子になります。

irb(main):023:0> a = true
=> true
irb(main):024:0> b = !a
=> false
irb(main):025:0> a = false
=> false
irb(main):026:0> b = !a
=> true
irb(main):027:0> a = nil
=> nil
irb(main):028:0> b = !a
=> true

!! バンバンを使うことで、否定の否定となり、trueまたは falseのどちからに変換することができます。ここで、注目したいのは、nilです。nil!は、trueが返ります。その後もう一度、!することで、true ⇒ false へ変換することができます。

irb(main):029:0> a = true
=> true
irb(main):030:0> b = !!a
=> true
irb(main):031:0> a = false
=> false
irb(main):032:0> b = !!a
=> false
irb(main):033:0> a = nil
=> nil
irb(main):034:0> b = !!a
=> false

参加人数

7月7日の七夕。

この日も、普段と変わらず輪読会が始まりました。

最初は「今日はいつもより多いな〜」ぐらいにしか思っていなかったのですが、その後天の川の星のようにどんどんを増え、最終的に21名の方が集まっていました(凄)

もちろん、過去最高の参加人数でした。

「もはやRubyコミュニティの1イベント並みの規模ですね…! rindokukai.rbとかやったらおもしろそうw」

メンターさんも参加人数の多さに驚いていました。

現在は、フィヨルドブートキャンプ内での開催ですが、将来は外部で参加者を広く募り開催できたら面白そうだなと思いました。

神降臨

七夕の翌日、またもうひとつ奇跡が起きました。

何と、まさかの伊藤さん降臨...!!!

f:id:shirotamaki:20210731103517p:plain

あまりの突然の出来事に、

全員驚き、それまでワイワイガヤガヤしていた輪読会が一気に静まり返りました…

人間は驚きと緊張が重なると静かになるようです。笑

輪読会の開催当初から気にかけていただき、質問等にも快く解答をいただけたりと、普段からお世話にはなっていたのですが、まさかリアルタイムで、直接本を書いた著者からお話しを聞けるとは思ってもいませんでした。驚きと同時にとても嬉しかったです。

伊藤さん、ありがとうございました!

KPTふりかえり会

早いもので、輪読会をスタートしてから7週間が経過しました。

会を進めていくうちに、進行や各自の負担など見直すべきこと、取り入れたいことなど意見が出ていました。しかし、輪読会後の雑談等でたまに話し合う機会もありましたが、雑談の話題のひとつで毎回終わってしまっていました。

そんな中、メンターの@rllllhoさんから、「一度KPTしてみては?」とアドバイスをいただき、KPTふりかえり会をしてみることにしました。

KPTとは?

  • K:keep = 良かったこと(今後も続けること)
  • P:problem= 悪かったこと(今後はやめること)
  • T:try = 次に試すこと

【徹底解説】正しい「KPT」が仕事の成果を生み出す!進め方のコツ、現場の事例を紹介 | SELECK [セレック]

ふりかえりメソッド「KPT」の基本とはじめ方 | Social Change!

まず、KPTを行う目的を決めました。

  • 輪読会を、楽しく・有意義(学び、成長)に運営するため

この目的に向かい、K P T の順番で、メンバー同士で率直な意見を交わしていきました。

改めてみんなでふりかってみる事で色々な気づきがありました。Tryする良き案も多く出てとても有益なKPTとなりました。今後も定期的(月1回程度)に開催をしていく予定です。

参考書籍

🍒 まとめ

今週はハッシュとシンボルを中心に学習しました。

ハッシュ、シンボルともによく使われるものですが、文字列との違いなど理解に自信がありませんでした。しかし、今回輪読会を通し学ぶことで理解でき、現在取り組んでいるSinatraを使ったメモアプリ作成の課題クリアの助けにもなりました。

また、輪読会としてもますます盛り上がりをみせており、今週は参加人数が21名まで達しました。そして何より、チェリー本の生みの親、伊藤さんのサプライズでの登場には驚きました!また来ていただけるとのことで、今後の楽しみのひとつになりました。

いよいよ次は、正規表現に入ります!

では、また来週!(次回、第8週目)