20210404_アウトプット(Ruby)
今日やったこと
- ゼロからわかるRuby超入門の続き(7:メソッド〜8:クラスまで)8時間50分
1%の成長
- ようやくモヤモヤしていたRubyのクラスと向き合えた
新しく学んだこと
メソッド
putsがメソッド内にある時と外にある時の違い
- メソッド内にある時・・・表示させることもメソッドの仕事の一つとしている。
- メソッド外にある時・・・処理と表示は別にしており、表示結果を配列や変数にして別のところで使うこともできる。
💡 つまり、外に「表示させる」ことを持ってくると、利用範囲が広がる。
おさらい 戻り値と引数
- 戻り値とは? 呼び出し元へオブジェクトを返す
- 引数とは? メソッドへオブジェクトを渡す
- returnを使わない限り、最後の値が戻り値となる。
引数の便利な機能
キーワード引数
引数が2つ以上になったときは、キーワード引数を検討しよう!
- キーワード引数のメリットは、大きく2つある。
(1)引数の渡す順番が異なっていてもシンボルを手がかりに、きちんとオブジェクトが渡されること
(2)ラベルのようになるので可読性が上がること
def order(item:, size:) "#{item}を#{size}サイズでください" end puts order(item: "ポテト", size: "大盛り") #=> ポテトを大盛りサイズでください
デフォルト値の設定
- 通常はイコールで代入。
- シンボルの時だけ、キーと値のように書く。
- デフォルト値を設定すると、ラベルを探しに行くので、引数の順番がメソッドと呼び出し側で異なっていても適切に渡すことが出来るよ。
def order(item = "ハンバーガー") "#{item}をください" end puts order #=> ハンバーガーをください #💡引数を省略するとデフォルト値が適用
def order(item:, size: "普通") "#{item}を#{size}サイズでください" end puts order(item: "ポテト") #=> ポテトを普通サイズでください #💡:sizeを省略したところ、デフォルト値の「普通」が適用となり、引数エラーとならない。
スコープとは?(おさらい)
- 変数の見ることのできる範囲と、寿命のこと
- ローカル変数は、メソッド内でしか使うことが出来ない(外から呼び出したり、中のものを外で使えない)
クラスとは?(おさらい)
- クラスは工場。クラス自身が仕事をすることもあれば、そこから生まれたオブジェクトが仕事をすることもある
- 新しいクラスを作ることは、新しい特徴をもったキャラクター(プログラムの世界ではオブジェクト)を作ることができる。
- クラス名はキャメルケースにする。(=定数でもある)
- Methodsメソッドとは、そのオブジェクトで呼び出せるメソッドを一覧表示することが出来る。
レシーバ.methods
クラスを理解しよう!!!
🤔私:「超入門」からやり直したのもクラスに苦手意識があったからなんだ。どのオブジェクトもクラスに属していることはわかっているんだけど、オリジナルのクラスを組み立てるルールがいまいちわからないよ。
🥸先生:具体的に、どのようなルールが分からなかったの?
🤔私:attr_accessorを使ったり使わなかったり、引数渡したはずなのにエラーになってしまったり、いまいちふわっとした理解で書けないんだよね。
🥸先生:超入門本から基礎をしっかり理解しよう。
超入門本からこんなふうに理解した!
前提知識
- Rubyは全てがオブジェクトであり、何かしらのクラスに所属している。
クラス.new
で、クラスがインスタンスとして生成される。- レシーバとは、メソッドを使って呼び出されるオブジェクトの中身のこと。(例えば、
2.even?
では2の「整数オブジェクト」がレシーバであるし、["ポメ", "ペキニーズ"].size
では、["ポメ", "ペキニーズ"]
の「配列オブジェクト」がレシーバである)
今日理解したこと
クラスの中身を作るにあたって、目的が大きく4つあると理解。
目的 | 内容 | ポイント | コード例 |
---|---|---|---|
ただのローカル変数等を呼ぶため | そのままの文字列や渡された引数をシンプルに式展開する等 | 異なる動作は出来ない | ① |
インスタンス変数とするため | ゲッターやセッター(あるいはattr_accessor)を使い変数を取得・代入する | インスタンス毎に異なる動作が出来る/代入されて実行されることで初めてインスタンスとなる/複数のメソッドを跨いで使える | ② |
イニシャライズメソッドとするため | newメソッドでクラスを生成時に引数で渡すことによって、生成時に持っていて欲しいデータを設定する | 引数として届くことが他のメソッドと違う点 | ③ |
クラスメソッドとするため | クラス全体を呼び出される中身として表示する | クラスが実行するのでオブジェクトを作ることなく呼び出すことが出来る(全体の振る舞い) | ④ |
ただのローカル変数等を呼ぶため①
class Drink def order(name) puts "#{name}をください" end end drink = Drink.new drink.order("お茶") #=> お茶をください
インスタンス変数とするため②
class Drink def name=(text) #🌟インスタンス変数へ代入している(👈attr_writer :name) @name = text end def name #🌟インスタンス変数を外から取得出来るようにする(👈attr_reader :name) @name end end drink = Drink.new drink.name= "お茶" #💡代入している。「drink.name = "お茶"」でも可。 puts drink.name #=> お茶
- ゲッターとセッターは
attr_accessor :name
と一つにすることが出来る。
イニシャライズメソッドとするため③
class Drink def initialize(name) @name = name end def name @name end end drink = Drink.new("牛乳") puts drink.name #=> 牛乳
- newメソッドへ渡す値を帰ると、色々なDrinkオブジェクトを作れる。
- 外から呼び出すには、参照用のメソッドを上記のように定義するか、アクセサメソッドが必要である。(ようやく繋がった・・・)
クラスメソッドとするため④
class Cafe def self.welcome "いらっしゃいませ!" end end puts Cafe.welcome 🌟呼び出す際はクラス.メソッド名だけでOK #=> いらっしゃいませ!
あるいは
class Cafe class << self def welcome "いらっしゃいませ!" end end end puts Cafe.welcome #=> いらっしゃいませ!
- 下の段は、複数のクラスメソッドを書くときに便利(ネストが一つ深くなる)またちょっと先の話になるけれどクラスメソッドをprivateメソッドにしたいときは
class << self
の構文を使うよ。 - インスタンスメソッドからクラスメソッドを呼ぶことも出来る(
self.class.クラスメソッド
またはクラス.クラスメソッド
)逆に、クラスメソッドからインスタンスメソッドを呼び出すことは出来ないので注意。(どのインスタンスメソッドであってもクラスメソッドは共通なので呼び出せるが、インスタンスメソッドはレシーバがその都度異なるため) クラス.new
のnew
はクラスメソッドだよ!!!
そのほか便利なメソッド
メソッド | 読み方 | 内容 |
---|---|---|
instance_variablesメソッド | インスタンスバリアブル | インスタンス変数の変数名一覧を取得するメソッド |
ancestorsメソッド | アンセスター(祖先)メソッド | 継承関係上の祖先をたどることが出来るメソッド |
継承のルール
- 継承は
<
一つ!(つい、クラスメソッドの2つとごっちゃになる) - 継承の目的は、「似たメソッドを何度も書くの面倒」なので、それらを引き継ぎつつ、「一部変えたい」という時に使える。
- ”「子クラス」は「親クラス」の一種である”と声に出しても違和感がない時は適切な継承と言える。
- 親子のクラス🐓🐤で同名のメソッドがある時は、「最初に該当したメソッド🐤」を呼び出す
- もし「最初に該当したメソッド🐤」ではなく、親クラスの同名メソッドを呼び出したい時は「🐓super🐓」と書く。
- 同名の「子クラス」と「親クラス」のインスタンス変数や、privateメソッドは、継承がきっかけでオーバーライドを引き起こし、バグを起こす原因にもなりうるので注意。
制限のルール
🤔私:それぞれのメソッドのルールを上手く使えば外からも中からも呼び出せるようになったね!
🥸先生:あえて「レシーバを指定して呼び出すことができないインスタンスメソッド」としてprivate
メソッドがあるよ。
🤔私:出来ること減らしてしまうので、無意味では?どうしてプライベートにするの?
🥸先生:private
メソッドにする=外から呼び出さないようにすると明示することで「このクラスとオブジェクトではAメソッドではなくBメソッドを使ってくださいね」と設計上の意図を他のプログラマーに伝える大事な役割を担っているよ。
感想
20210402・03_アウトプット(Ruby)
今日やったこと
HTMLの理解を深める 50分
ゼロからわかるRuby超入門の続き(6)3時間40分
Laravelのアプリ 1時間(mysql接続ができておらず、migrateがうまくいかなかった もう少し調べよう)
1%の成長
ブロック変数について、ハッシュと配列でごっちゃになっていた部分が整理できた。ハッシュの時は、原則キーと値の2つを渡す。
each_key
やeach_value
などのメソッドを使う時だけ、そのうちの一部を指定しているので1つとなる。配列の時は、配列の直後にメソッドをつけることが出来たが、ハッシュの場合には代入した変数に対して
delete
やmerge
メソッドを行うことを理解。
新しく学んだこと
ハッシュ全体のこと
ハッシュをpメソッドで出力する際はハッシュを丸かっこで囲わないと、文法の解釈が曖昧となりエラーとなること。
シンボルへ変換するときは
to_sym
メソッドがあること。キーとシンボルを同じ意味に捉えていた。しかし、違った。
🟢「キーとバリュー」は「見出しと内容」という概念のことを指す。
🟢シンボルは「キー」を表現する方法の一つ。ハッシュロケットを使う場合には、シンボル以外(文字列など)をキーにすることが出来る。ハッシュに対して、キーを指定して探そうとした時、値がない場合は
nil
を返すが、デフォルトを設定することもできる。
menu = { coffe: 300, caffe_latte: 400} menu.default = "その値はないよ" p menu[:tea] #=> "その値はないよ"
mergeメソッド
- merge メソッドを使い、2つのハッシュを1つにまとめることができる。
coffee_menu = { coffee: 300, caffe_latte: 400 } tea_menu = { tea: 300, tea_latte: 400 } menu = coffee_menu.merge(tea_menu) p menu #=> {:coffee=>300, :caffe_latte=>400, :tea=>300, :tea_latte=>400}
- 逆でもOK(そうすると、teaからの順になった)
menu
ではなく、coffee_menu
やtea_menu
を代入後の変数にしたら、NameErrorになった💡個別で値の代入をする時は書き換え(上書き)が出来るけれど、「ハッシュ自体を定義した変数」と「マージした後の変数」という同義にならない場合はちゃんとエラーになるんだと勉強になった。- ハッシュに直接繋いでもNameErrorになった(
{ coffee: 300, caffe_latte: 400 }.merge(tea_menu)
deleteメソッド
- キーと値する時はdeleteメソッドを使う。
ハッシュ.delete(キー)
menu = { book: 500, note:100 } menu.delete(:note) p menu #=> {:book=>500}
eachメソッド
menu = { coffee: 300, tea: 400 } menu.each do |key, value| p "#{key}は#{value}円です" end #=> "coffeeは300円です" "teaは400円です"
メソッド | ブロック変数の数 | 内容 |
---|---|---|
each | 2つ(key・value) | キーと値を表示 |
each _key | 1つ(key) | キーのみ表示 |
each_value | 1つ(value) | 値のみ表示 |
感想
- 午前中に、オンラインスクールの時の仲間と近況報告。息抜きになった😌仲間がわからないと言っていたAWSにおけるエンジンエックスの役割を説明したら、理解につながったようで嬉しかった。
- 最近、メリハリを大事にするよう心掛けている。ついプログラミング以外の時に、心のどこかでプログラミングのことを考える気持ちが抜けないでいた。自分のメンタル的にも関わる相手にとっても良くないなーと感じていたものの、ついつい心配性で考えてしまう癖がある。プログラミングもそうでないことも1つ1つ楽しみながら気持ちを切り替えよう!
20210401_アウトプット(Ruby)
今日やったこと
- ゼロからわかるRuby超入門の続き(5の練習問題)40分
1%の成長
- リファレンスをみながらメソッドを探すことに少しずつ慣れてきた
- また練習問題解くときに、vimを使うようにしていて、ファイル作成や行のコピーに慣れてきた
- メソッドの中でもよく使うsplitやmap、joinメソッドが理解できるようになった
新しい発見
「配列の中身の合計」とみた時に
+=
で順番に足す構文を想像してしまうが、sum
メソッドなら一行で記述できる%Wと%wの違いは、%W(式展開あり)と%w(なし)の違い。””を使わなくて済むのでスッキリする
split ⇄ joinである
p ["100", "50", "300"].join(",") #=> "100,50,300" p "100,50,300".split(",") #=> ["100", "50", "300"]
復習
メソッド | 意味 |
---|---|
uniq | 重複なくす |
clear | 配列の中身を空にする |
sample | ランダムに配列の中から1つの要素を出力する |
map | 中身に同じ処理をする(新しい配列を得ることが目的!) |
downcase | 全て小文字にする |
感想
- 今日は勉強時間をあまり取ることができなかった。しかし15分以上のマイルールは達成できた。(自分を責めずに、休む自分も大事にしよう💦😊)
- 配列の展開はよく使うと思うので、繰り返し復習したい。
- やりたいことが沢山あって優先順位に迷うけれど、今やっているRuby超入門の本をまずやり切ろう。
- あっという間に新年度。昨日と今日、同じ一週間なのに、人事異動で人がガラッと変わると大きく雰囲気が変わる。若干緊張するけどフレッシュな気持ちになるのでこの雰囲気は好きだなあ。天気も暖かくなってきたし、晴れやかでいい。🌸
- 新年度明けの忙しさと、勉強の両立、乗り切ろう!!!
20210331_アウトプット(mysqlエラー→解決できた😍)
今日やったこと
- mysqlのエラーと格闘 →解決🎉(4時間)
1%の成長
- エラーと向き合えた
- mysqlの理解ちょっと進んだ
- バージョンアップって学ぶこといっぱいある(上手くいったと思っていても、後で地雷を踏んで爆発することがある💣)
新しい発見
ログの確認
この記事を見て、ログも合わせて確認しようと思った。
ログから読み取ったこととしては、「REDOログはMySQL5.7.9以前に作成されたもの。Data Dictionaryの初期化に失敗したよ」
% tail -f /usr/local/var/mysql/noMacBook-Air.local.err 2021-03-30T22:00:27.181813Z 0 [Warning] [MY-010159] [Server] Setting lower_case_table_names=2 because file system for /usr/local/var/mysql/ is case insensitive 2021-03-30T22:00:27.195807Z 1 [System] [MY-011012] [Server] Starting upgrade of data directory. 2021-03-30T22:00:27.195917Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started. 2021-03-30T22:00:27.284951Z 1 [ERROR] [MY-013090] [InnoDB] Unsupported redo log format (0). The redo log was created before MySQL 5.7.9 👈👀❗️ 2021-03-30T22:00:27.285128Z 1 [ERROR] [MY-012930] [InnoDB] Plugin initialization aborted with error Generic error. 2021-03-30T22:00:27.286229Z 1 [ERROR] [MY-011013] [Server] Failed to initialize DD Storage Engine. 2021-03-30T22:00:27.286786Z 0 [ERROR] [MY-010020] [Server] Data Dictionary initialization failed. 👈👀❗️ 2021-03-30T22:00:27.287122Z 0 [ERROR] [MY-010119] [Server] Aborting 2021-03-30T22:00:27.287726Z 0 [System] [MY-010910] [Server] /usr/local/opt/mysql/bin/mysqld: Shutdown complete (mysqld 8.0.23) Homebrew. 2021-03-30T22:00:27.6NZ mysqld_safe mysqld from pid file /usr/local/var/mysql/efuERIKAnoMacBook-Air.local.pid ended 2021-03-30T22:00:37.6NZ mysqld_safe Logging to '/usr/local/var/mysql/efuERIKAnoMacBook-Air.local.err'. 2021-03-30T22:00:37.6NZ mysqld_safe Starting mysqld daemon with databases from /usr/local/var/mysql 2021-03-30T22:00:37.824064Z 0 [System] [MY-010116] [Server] /usr/local/opt/mysql/bin/mysqld (mysqld 8.0.23) starting as process 7372
REDOログって何?
- 更新履歴のファイルだよ(データベースへの変更があるたびに記録)。ただし上限があるのでいっぱいになると上書きし始める。
- 上書きすると、そこからログを使って復旧できなくなるため、REDOログが、いっぱいになる前にアーカイブ ログが作成される。
- アーカイブ ログは、勝手に消えることはないので定期的に削除しないと容量がいっぱいになってしまう。アーカイブ ログについて通常は自動で削除する設定をする。
調べたところから立てた仮説
昨日調べたことも含めて、今回エラーが発生した経緯は、以下の通りでは?と仮説を立て始めた。
(1)macをBigSurにし、RubyやRailsをアップデートした時、mysqlは5.6をインストールしてサーバー起動。
(2)brew upgrade
により、てHomebrewでインスールしたパッケージたちが全てバージョンアップ(mysqlも5.6から8.0へ)
(3)macの電源を切った。
(4)ターミナルを再起動した際、mysql8.0が起動。今まで作ったアプリたちはmysql5.6だったので「mysql5.6のログ残っているよ、8.0でこのまま立ち上げできないよ」とエラーに陥った。
と考えた。
当初は「/tmp/mysql.sock
がない」ことが原因だと思っていたが、ディレクトリはmysql8.0において存在している。
そのことから、「意図せずmysql8.0の起動になっている部分」を「mysql5.6で起動」すれば上手くいくのではないか?と思った。
↓↓この記事が参考になった。
直った!!!!!
覚書
- バージョン指定して起動したら直った。😻❗️💗
noMacBook-Air ~ % /usr/local/opt/mysql@5.6/bin/mysql.server start Starting MySQL .. SUCCESS! noMacBook-Air action_app % mysql -v Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 5 Server version: 5.6.51 Homebrew Copyright (c) 2000, 2021, Oracle and/or its affiliates. (省略)
- ちなみに、もう一度落として、スタートしたら同じエラーでた(エラーを再現できた!!!)原因はこれだったのか💡嬉しかった〜!!!
- よく理解しないまま、Qiitaの記事を見て、mysql5.6のファイル等を削除しなくて良かったと感じた😭✨🙏笑
noMacBook-Air ~ % /usr/local/opt/mysql@5.6/bin/mysql.server stop Shutting down MySQL . SUCCESS! noMacBook-Air ~ % sudo mysql.server start Password: Starting MySQL . ERROR! The server quit without updating PID file (/usr/local/var/mysql/efuERIKAnoMacBook-Air.local.pid).
感想
- 時間はかかったけれど、解決できて嬉しかった〜!
- この感覚は、オリアプを作っていた頃の気持ちを思い出した(笑)
- プログラミングって「背景や意図など新しい知識を知れた時の面白さ」「エラーに苦しむけど調べまくってブラウザに反映した時(形にできた時)の嬉しさ」2種類あると最近感じている。
- 最初は「Railsなどの続きやりたいし、変なところでエラー出ないでー!!」と内心思ったが、結果として面白かったから良かった。
- dumpコマンドで、バックアップを取ることを知った。結果として、mysql5.6のままなので、時間ある時に5.7から8.0にチャレンジしてみよう😊!!
20210330_アウトプット(mysqlエラーと格闘)
今日やったこと
- mysqlのエラーと格闘(3時間45分) →未解決
新しい発見
上記エラーについて調べたり、感じたこと
mysql5.6使っていたが、mysql5.7のあとは、8.0と一気にメジャーアップデートされていたことを知る。
mysql8.0はシークエルプロ使えないみたい。ただし、それに変わるアプリもあることを知る。
brew update
したことにより、Mysqlのバージョンも最新版へ意図せずアップグレードしていたことが原因の様子。解決法を探すとバージョン5.6や5.7にダウングレードする方法が出てくる。
はじめはそれを試みていたが、ふとそれは「エラーを解消」だけが目的であり、そもそも「最新版の8.0」によるメリットは何か?(どんな影響があるのか)、もしそちらの方がよければ8.0を使う方法を模索した方がいいのではないかとも思い始めた。そういえば一次情報ちゃんと調べてなかったと思い始めた。
mysql8.0のメリット
SQLを勉強していた時に、それを扱うリレーショナルベース管理システムごとの癖が結構違うと感じていたが、mysql8.0では、それらのメソッドが便利になったり記述が簡略化されるようになったと理解。
全てを理解は出来なかったが、ハードディスクの大容量化などによりログの出力する方がデフォルトに変わったり、クエリキャッシュと呼ばれるデータを抽出した時に一時的に残さないモードにしておかないと新しいバージョンでは起動しなくなったり、ユーザー認証に変更があることを知った。
一次情報見てみよう
バージョンアップする前に確認すること(今回の場合、意図せずバージョンアップしちゃったけど互換性を確認するため)
Rubyの時に学んだようにちびちびバージョンアップした方がいい。
- バックアップを取る必要もある。
- mysqlのアップグレードに伴う予備チェックをするコマンド
mysqlcheck -u root -p --all-databases --check-upgrade =>mysqlcheck: Got error: 2002: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (38) when trying to connect
- そもそもなぜ、
/tmp/mysql.sock
に接続しようとしているの?
掘り下げ1:cofig>database.yml
において指定していた。
default: &default adapter: mysql2 encoding: utf8mb4 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: socket: /tmp/mysql.sock 👈👀❗️
掘り下げ2: リファレンスにもこの場所がデフォルトですって書いてあった。(知らなかった。)
サーバーがローカルクライアントと通信するために使用する UNIX ソケットファイルのデフォルトの場所は、/tmp/mysql.sock です
- mysqlのWebページ見づらい・・と思っていたが、右上のタブでバージョン切り替えてリファレンス読めることがここら辺でだんだん分かってきた。
バージョンを確認するコマンド(エラー内容がより詳しく出た)
起動しているか存在しているか確認して!
noMacBook-Air ~ % mysqladmin version mysqladmin: connect to server at 'localhost' failed error: 'Can't connect to local MySQL server through socket '/tmp/mysql.sock' (38)' Check that mysqld is running and that the socket: '/tmp/mysql.sock' exists!
この2つの記事が解決の糸口になりそう😣
ソケットファイルの指定方法
MySQL :: MySQL 8.0 Reference Manual :: B.3.3.6 How to Protect or Change the MySQL Unix Socket File
今回のエラー原因では?
MySQL :: MySQL 8.0 Reference Manual :: B.3.2.2 Can't connect to [local] MySQL server
感想
- エラー解決に必死になっていたけれど「1次情報そういえばちゃんとみてない」と視点を持てたのはよかった。
- なぜならばRubyやRailsなども、サポートされなくなるからバージョンアップするのに、必死になって「グレードダウン」する方法を調べているのでは?と思えてきたため。
- 上手くいくかわからないけれど、会社で失敗するより個人で失敗する方がいいので、ターミナルのちょっと不安なコマンドも、意味を調べながら、チャレンジしてみようと思っている💦(エラー解決しますように・・・)
- 調べたり、「どういう意味?」で今日の勉強終わってしまったが、向き合えたからよしとしよう。
- バージョン8.0で、あとデフォルトのコネクト先を設定すればいける気がするんだけど違うのかな?そもそも設定どうするんだ?
- しっかり寝てまた明日向き合ってみよう。
- 自分の大事に思っている考えと技術力が高い方の思考が似ているととても嬉しい。少しでも近づけるように技術力アップ頑張ろうと励みになる。
20210329_アウトプット(Ruby)
1%の成長
- ゼロからわかるRuby超入門(3時間半)
新しい発見
sizeメソッドとlengthメソッドはエイリアスメソッド(別名メソッド)
私🤔:配列の要素数ってどうやって数えるの?
先生🥸:sizeメソッド
やlengthメソッド
で数えることができるよ。
私🤔:異なるメソッド名でも、同じ実装になるんだね。
先生🥸:うん、それらをエイリアスメソッド(別名メソッド)といい、文脈や好みで使い分けるよ。 同じ実装でも速度が違う場合があるので、速さを一つの基準にしてもいいかもしれないね。
puts [2, 4, 6].size #=>3 puts [2, 4, 6].length #=>3
require 'benchmark' Benchmark.bm 10 do |r| r.report "size" do end r.report "length" do end end # 結果 user system total real size 0.000011 0.000010 0.000021 ( 0.000007) length 0.000003 0.000001 0.000004 ( 0.000003)
配列の全要素の合計を得るにはsumメソッド/平均を出すにはそれをsizeメソッドかlengthメソッドで割る
- 注意としては、合計値を使って平均を出すときに、デフォルトは整数になっているので
to_f
(小数)に変換するメソッドを使わないと正しい値がでない場合があること。
a = [1, 2, 2] puts a.sum / a.size #=> 1 puts a.sum.to_f / a.size #=> 1.6666666666666667
uniqとuniq!の違いは何?/新しい配列を作り出すか・配列そのものを変更(破壊的)するか
- 末尾に!がつく/つかないメソッドがある。
- !がつくと、オブジェクトを破壊的に変更し、!がつかないと新しい配列を作って返すものが多い。
ブロックを渡せるメソッド
p [1, 3, 2, "2", "3"].uniq # => [1, 3, 2, "2", "3"] p [1, 3, 2, "2", "3"].uniq { |n| n.to_s } # => [1, 3, 2]
- 2つめはブロックで一つずつ、配列の中身を全て文字列にしてから重複を取り除いている(これを
to_i
にして全て整数にしてから重複を取り除くでも結果は同じ)
配列をランダムに操作
メソッド | 内容 |
---|---|
sample | 配列の中からランダムで一つ選ぶ |
shuffle | 配列の中身をランダムに並び替える |
配列の並びかえ
私🤔:そのまま、reverseメソッドを使う時と、sortメソッド+reverseメソッドの違いは何?
先生🥸:配列の中身を「そのまま逆」にするか、中身が大きい順/小さい順、アルファベット順(かつ大文字優先)など並び替えたものをリバースするかの違いだよ。
ary1 = [ "d", "a", "e", "c", "A" ].sort.reverse #=> ["e", "d", "c", "a", "A"] ary2 = [1, 2, 4, 5, 6, 4, 0].sort.reverse #=> [6, 5, 4, 4, 2, 1, 0]
- 注意点としては、「文字列」の数字をソートした時は、正しく大きい順/小さい順にならないので、uniqメソッドで学んだ時のようなブロックにして(全てto_iメソッドで変換して)並び替えるよ。また大小の比較をしながら並び替えるため、ブロック引数として2つ渡す必要があるよ。
p ary2.sort{|a, b| a.to_i <=> b.to_i } #=> ["7", "8", "9", "10", "11"] (ブロックを使って数字としてソート)
配列の「中身」をくっつけるjoinメソッド
- 配列の中身をくっつける
- くっつける時に、要素間に指定の文字を入れて欲しい
というような場合は
joinメソッド
が便利!
puts ["りんご", "みかん", "いちご"].join("と") #=>りんごとみかんといちご puts ["りんご"].join("と") #=>りんご
- とても便利だと感じたのは、要素が一つの時には「連結していない」と判断してつかないようになること。
文字列を分割して、配列にするsplitメソッド
- 文字列と文字列の間は「半角スペース」分空いている、「”と”」で繋がっているなど、法則性があるときにその文字列で区切って配列にしてくれるメソッド。
puts "りんご みかん バナナ".split(" ") りんご みかん バナナ
puts "りんごとみかんとバナナ".split("と") りんご みかん バナナ
配列の中身に対して、同じように〇〇したい時に使えるmapメソッド
- 配列の各要素に対して同じ処理をして、変換後の要素を「新しい要素」として作り出すメソッド。
私🤔:eachメソッド
と何が違うの?
先生🥸:eachメソッド
は、各要素に対してブロックで処理を行うことが目的で、mapメソッド
は各要素を変換した新しい配列を作ることは目的になるよ。
puts ["赤", "白", "黒"].map do |x| "{x}色" end #=> 赤色 白色 黒色
- リファクタリングとして、
do ~ end
を{ ~ }
にできる。
result = ["abc", "123"].map { |text| text.reverse } p result #=> ["cba", "321"]
result = ["abc", "123"].map(&:reverse) p result #=> ["cba", "321"]
- また各要素に対する処理で、あるメソッドで呼び出す(処理を施す)場合については、シンボルである
&:メソッド名
で表現できる。 - ただし、これが使えるのが①ブロック引数が一つだけ②引数がないこと③メソッドを1回呼び出したら終わり、という条件が揃った時。
🤔私:&:メソッド名
ってどういう状態?
🥸先生:&
と、:メソッド名
の組み合わせ。&
はprocオブジェクト(ブロックをオブジェクト化するクラス)の一つでブロック処理を一つのカタマリにしている。:メソッド名
はシンボル(オブジェクトの種類の一つ。)にしている状態だよ。
感想
- split、mapについて、ネットでふわっとした概念で理解していたので、役割がきちんと理解できて嬉しかった。
- 今日はSPI勉強できなかったけれどRubyについて、引き出しが増えたのでよしとしよう。
- どうしても眠いので今日はもう寝る。
20210328_アウトプット(Ruby)
1%の成長(昨日の自分の知識より1%成長する)
Wantedlyの「将来やってみたいこと」「やったこと」を追記・投稿(1時間)
ゼロから分かるRuby入門(チャプター1から4まで)(4時間)
paizaのスキルチェック(1時間)
SPI(1時間30分)
新しい発見
ゼロからわかるRuby入門
簡単なプログラムをかく
- pメソッドはデバッグの道具として使う。(プログラムの機能として意図して表示するときはputs)
🤔(どうして?)
pメソッドが唯一、戻り値が「引数のオブジェクト」になるからだよ。(putsメソッドは改行ありでnil、printメソッドは改行なしでnilとなる。nilじゃどこが間違えているのか分からない。)
- エラーメッセージの時に、コロン(:)で区切られた数字は、プログラムの何行目でエラーが起きたのかを教えてくれる。
条件分岐
慣習的に末尾に
?
がつくメソッドはtrue
かfalse
で返すことが多い。even?
(偶数か?)、odd?
(奇数か?)後置ifのときはend不要。
elsif
は複数書けるが、書きすぎると読みづらくなる。そんなときは、&&
・||
・case
を検討しよう。
内容 | 選択肢がこんな時に使う |
---|---|
if | 二択 |
case | 三択以上 |
「一つ選ぶ」は
case 変数
と定義。caseを書かないときは、whenの後に条件をかく。case文のとき、複数に合致するものがない時の選択肢としてelse。
繰り返し
慣習的に、ブロックを複数行で書くときは、
do ~ end
、一行で書くときは、{ ~ }
。「条件付き繰り返し」が
`while
case 変数 when 候補1 変数の値が候補1の時と等しい時の処理(複数行書くことも可能) when 候補2 変数の値が候補2の時と等しい時の処理(複数行書くことも可能) end
変数を書かずに、「候補1」や「候補2」に条件を書くことも可能。(wallet >= 500)
while 条件 条件を満たしている間、繰り返し実行する処理 end
ブロックの時のように
do
は不要。「繰り返し実行する処理」の戻り値を元に「条件」を判定する。なので条件が「変数 < 2」だった時、1週目の時の戻り値は「1」なので、「2」まで実行されることがスッキリ。
配列
- 配列の中身のオブジェクトクラスはバラバラでも可能(例 文字列、整数、小数点が入った配列)
- 変数を使わずにメソッドを呼び出すことも可能
p ["牛乳", "お茶"].first #=> "牛乳"
要素の追加 | メソッド |
---|---|
末尾に追加① | push |
末尾に追加② | << |
先頭に追加 | unshift |
要素の削除 | メソッド |
---|---|
末尾の要素を1つ削除 | pop |
先頭の要素を1つ削除 | shift |
popメソッドとshiftメソッドは、削除した要素を返す。
|
はパイプと読む。
感想・振り返り
- 「全部頑張らないと」のように、変に自分を追い詰める癖を改善したいので、1%の成長項目を追加してみた。「1%進めよう」という気持ちでやってみたら、「変な焦り」に囚われることなく、一つずつ出来て良かった。
- 昨日、ルビィのぼうけんを読んでいて、最後の鳥井さんのコメントにあった「よく観察すること」「その中からパターンを見つけること」「小さいことから始めて大きくしていくこと」に励まされた。あとビットの世界の絵がとても可愛い。素敵だ。
- Rubyを書くことがまだまだ下手な自分を受け入れよう。Ruby入門の本から始めてみて着実に成長しよう。
- 今思うとここ一週間を振り返って「自分はエンジニアに向いていないのかもしれない」「なんでこんなにコード書けないんだろう」と「自分ができる感覚が持てない」ことが一番辛かった。
- 「出来る気が持てない」と、やる気やモチベーションが大きく低下することを実感した。
- 「出来る実感」を持つにはどうしたらいいか。今何が出来る?小さく成長するにはどうしたらいい?
- なぜ書けないのか?①何より自信がない。②問題を細かく「順序進行」「繰り返し」「条件分岐」に分ける力が弱いのでは。③型がふわっとした理解。特に、メソッドへの引数の渡し方・クラス・ブロック引数・モジュールあたりの知識の理解がまだまだ。
- 嬉しかったのは、基礎を4までだけど、行なってからpaizaを解いてみたら解けるようになったこと。楽しくなってきた。ちょっとずつ自信つけていこう。