Deep in Deep

プログラミング勉強中。遠回りですが、ゆっくり深く学んでいきたい。

2022年を振り返って

はじめに

振り返りを書こう、書こうと思っていたら、大晦日の23時になっていました。馬鹿野郎ですみません。

2022年を振り返ろうと思ったのですが、とにかく今年は自分を取り巻く環境が大きく変わった一年でした。

人生の中でも大きな転換期だったのではないかと思います。

印象に残っている部分をかいつまんで、振り返り、来年の抱負みたいなのも書けたらいいな。

3月末で前職を退職

Twitterのプロフィールにも記載してありますが、自分は看護師です。病院で働いていました。

2021年の春くらい、新しい大きなことに挑戦したくなり、以前より気になっていたプログラミングについての勉強を始めました。

ご縁があり、現在働かせていただいている会社に就職することが決まり、3月末に前職を退職しました。

長く暮らした田舎を出て、上京するのは少しつらい気持ちや不安もありました。

東京について一番印象に残っているのは「電車がマジで長い」です。地元は2両編成がいいとこなので...

上京後

上京後は主にRubyRuby on Rails関連のタスクをアサインいただいて作業しておりました。

Rubyはここまでの約1年、独学してきましたがレベル感としては初心者の域を抜け出せず苦労することも多かったです。

アサインしていただくタスクは、現状の実力だと難しいけれど、調べたり学習しながら進めていけば何とか実装できるような難易度でした。

ほどよいレベル感でタスクをアサインしていただいたおかげで、日々の業務で少しずつですが成長できた気がします。

Git周りの操作やインフラ周りのことについて詳しい先輩も居り、たくさんサポートしていただきました。

メインPCをWindows

独学でRubyなどを触っていたころはMacBook AirのM1チップ搭載モデルを使用しておりました。

開発業務を行っていく中でDocker環境を構築する必要性がでてきました。

Dockerを使用して開発をする際、M1チップ搭載のMacBook Airだとうまく動作しないものが多かったり、個別で設定が必要なケースが多かったです。

また、メモリは16GB積んでいましたが、プロジェクトによっては動作が重く作業中ストレスがたまることもありました。

いい機会だと思い、環境をWindowsにまるっと変更することにしました。

ハードウェアについての知識は乏しかったため、職場の先輩に相談しながらパーツを購入し、自分で組んでみました。

Windows環境だと、WSLを使用すればUNIX系をコマンド操作で開発業務を行うことができて便利でした。

昨今、WindowsMac論争のようなものを見かけることもありますが、正直どっちでもいいかと思いました。Windowsの場合は、ハード面のカスタマイズがしやすく、パーツも多いため、拡張性に富んでいると感じます。

ラズパイを購入、ネットワーク周りの環境を調整

業務では直接かかわることがない部分でしたが、インフラ周りに興味を持った時期がありました。

自前でWebサーバを建ててみたくなり、ラズパイを購入しました。

このラズパイを使用して、メインのPCからSSHで接続できるようにしたり、メインPCを遠隔で起動させるためのwake on LANの仕組みを作ったりして遊びました。

おかげでリモート環境で自宅のPCを操作できるようになり快適な開発環境を手に入れました。

後半はJavaScriptとの格闘

2022年の後半はReactやTypeScriptを触る機会が増えました。昨年Rubyを学ぶ前にもっとJavaScriptを触っておけばよかった...!!と思うこともありましたが、たくさん書いているうちにだんだんコードも読めるようになったり、既存のコードの修正などもできるようになりました。

ReactやTypeScriptあたりの練度はまだ足りていないと痛感することが多いので、2023年直近の課題であります。

この辺りはReactとRailsを合わせてSPAのアプリケーションを自作してみて、いろいろと試行錯誤して学んでいきたいところです。

現在抱えている課題

2022年、成長できた点も多くありましたが、課題もたくさんあります。

技術面

技術的な課題としてはReactやTypeScriptなどの練度不足が一番気になるところです。どうしてもバックエンドのみのタスクは少なく、基本的にはバックエンドの処理も書きつつ、画面に映る部分の修正も必要になるケースが多いです。

この辺りの学習は継続していき、できる仕事の幅は広げていきたいと思います。

精神面、日常生活における課題

精神的な部分においても課題と感じている部分はあります。

自分は緊張、プレッシャーに弱いところがあります。納期が近づいているのに、うまい具合に処理が組めないとか、バグを連発してなかなか修正できないようなときに、かなり混乱してしまうことがあります。

そういう時に冷静に対応できるようにしたいというのが、精神的な課題です。

エラーや起こったトラブルに関しては、「OOというエラーの時はXXをしたら解決できた」というような、トラブルシューティング的なメモをNotionやGitHubのメモ用のリポジトリなどに残しておき、すぐに確認できるようにしておくなど、非常事態にもある程度冷静に対処できるよう、 日ごろから対策をしていきたいですね。

日常生活においては、やはり生活リズムの調整です。

就業時間がフレックスな働き方ですと、朝起きる時間が少し遅くなってしまったり、夜勉強していて寝るのが遅くなってしまうこともあります。

また、リモートワークに伴い、運動不足を感じることも増えました。

このあたりの自己管理をしっかり行い、健康に毎日元気に作業ができるようにしていきたいですね。

抱負

2023年の抱負は「強みを見つけて伸ばす」です。

2022年は手探りでいろいろなことを浅く広く勉強しました。できることは増えましたが、OOなら任せろ、というような自分の強みはイマイチ自分の中でピンとくるものがありません。

いろいろな技術を好き嫌い言わずに学んでみたり、興味がわいたことは直接業務で使わないことでも積極的に学んでいき、その中でこれを極めたい!というものを見つけて、その部分を伸ばしていけるような一年にしていきたいです。

読みたくて買ったけど読めていない技術書も何冊かたまってしまっているので、どんどん読んでいかないとですね。隅から隅まで読むというよりはザーっと読んで、必要な時に読み返すようにしないといけません。技術書を読んで、まとめておきたいことがあれば、このブログに 記事として残していき、自分の中で学んだことを整理していこうと思います。

仕事もプライベートもバタバタする一年になりそうですが、体を壊さず、楽しく過ごしていきたいですね。

おわり。

ラズパイを使って自宅のデスクトップPCを遠隔操作で起動する!

最近、自宅のメインのデスクトップPCをリモートデスクトップのホストにして、thinkpadをクライアントとして使用し、外部から自宅のPC上で作業できるような環境を作りました。( 別途記事作成しようかと思ってます )

この環境を作ったおかげで、外出先でも結構快適に作業ができるようになったので、かなり気に入っています。

メインPCがMacBookの人なら関係ないと思いますが、自宅ではデスクトップPCで作業しているけど、外出先ではしかたなくラップトップ上の環境で作業をしている方にはかなりお勧めできます。

一点不安なことが

この素晴らしい環境ですが、一点不安なことがありました。

「これ、ホストPCの電源落ちたら、詰むやん」

この点だけが怖くて、こうなった場合は急いで帰宅するしかないのかな、、、なんて思っていました。

このことを会社の先輩に相談したところ、「Wake on LAN( WOL )」について教えてくださいました。

Wake on LANとは

Wake on LANというのは、

コンピュータネットワークに特定のパケットを送信させることにより、そのパケットの内容に該当するコンピュータが自ら電源を投入させる仕組みである。自明に、ネットワークの特性を生かしたコンピュータの電源操作が可能となる。 ( 引用: ウィキペディア Wake-on-LAN )

という技術だそうです。会社とか学校などで大量のPCを一括で電源onにしたり、遠隔地のPCの電源を入れるような用途で使われるみたいです。

今回やってみたこと

  • ラズパイを使ってホストPCにマジックパケットを送り、遠隔地からホストPCの電源を投入
  • ラズパイにはクライアント用のthinkpadからsshで接続して、wakeonlanコマンドを使用
  • ラズパイによるホストPCの死活監視 -> 電源がoffになってしまったときに自動で再起動するようにする、というのは今回は設定しておりません。( またいつかやる )

環境

  • ホストPC: Windows10Pro( マザボ: ASROCK B450 Steal Legend ) => ルーターに有線接続
  • クライアントPC: ThinkPad E14Gen4 Windows11Home => 外部でリモートデスクトップ接続作業
  • ラズパイZero2w -> ルータとは無線接続。ホストPCと同一ネットワークに所属

クライアントPCからラズパイへは、外部からでもSSH可能な状態

準備

今回行う作業の準備は大きく分けて3つ。BIOS/UEFIの設定とホストPC( Windows )の設定、ラズパイ側の準備です。

BIOS/UEFI

BIOS/UEFIの設定の中で、Wake on LANを有効にするかどうかの項目があるようで、そちらの設定を行う必要がある。

自分の場合は、マザボがASROCK B450 steal legendだったので、UEFIAdvanced > ACPI Configuration > PCIE Devices Power OnEnabledに変更。

Advanced > ACPI Configuration > Deep SleepDisabledにするようだが、defaultでDisabledなのでそのままでOKでした。

Save and ExitでUEFI終了

Windows( host )側

  • Win + Xで開かれるメニュー( 左下Windowsマークを右クリックしても開かれるよ )から「デバイスマネージャー」を選択
  • 「ネットワークドライバ」 > 「Realtek PCIe GbE Family Controller」(これは人それぞれ違う可能性あり。)を右クリック > 「オプション」
  • 「詳細設定」タブ内にwake on lan とか ウェイクオンラン、みたいな設定項目があるか確認
    • ある場合 -> それらを「有効」/ 「Enable」に変更
    • ない場合 -> ドライバの更新が必要と思われる。
      • 自分の場合はドライバの更新、WindowsUpdateをして最新状態にしたはずだが、NICのドライバのバージョンが古いままだった
      • Realtekのページに行き、最新版のドライバをダウンロードし、インストール。
      • 先ほど開いていたオプションの「ドライバ」タブの更新履歴を確認し、最新版が当たったことを確かめる
  • オプション内、「電源の管理」タブ > 「このデバイスで、コンピュータのスタンバイ状態を解除できるようにする」、「Magic Packetでのみ、コンピュータのスタンバイ状態を解除できるようにする」をチェック
  • コントロールパネルを開く
  • ハードウェアとサウンド >> 電源オプション >> 電源ボタンの動作の変更 >> 「現在利用可能でない設定を変更します」クリック >> 「高速スタートアップを有効にする」のチェックをはずす
  • MACアドレスを調べる
ipconfig /all

ラズパイ側

クライアントPCからSSH接続できるのは大前提としておきます。

wakeonlanのpackageをinstallする。

sudo apt install wakeonlan

以上

動作確認

  • クライアントPCを携帯のテザリングなどを使用して、外部ネットワークに接続させておく
  • クライアントPCからホストPCにリモートデスクトップ接続を行い、その中でホストPCの電源をシャットダウンさせる
  • リモートデスクトップ接続は解除され、ssh接続も当然切れます。
  • クライアントPC -> ラズパイ へssh
  • ラズパイにて以下を実行
wakeonlan XX:XX:XX:XX:XX:XX<先ほど控えておいたホストPCのMACアドレス>
  • ホストPC起動しました( やった~ )

おわりに

今回はWake on LANの技術を使用して、PCの電源を遠隔で投入する方法を試してみました。

遠隔でoffにすることもできるそうですが、それにはリブーターという機械がいる? みたいで、今回は見送りました。

また、ラズパイに自宅PCの死活監視をさせて、必要に応じてWake on LANを使用し、電源投入する方法についても調べてみたいと思います。

一つ言えるのは、「マジでラズパイ買ってよかった」です。

勢いと気分でなんとなく買ってみたラズパイだけど、現在の自分の作業環境の中で、結構なくてはならないアイテムになりつつあります...

これからもどんどんラズパイを活用できたらいいな!!

【自前Webサーバ構築への道1】ラズパイ買いました

ちょっと前ですが、ラズベリーパイ(Raspberry Pi: 以下、ラズパイ)を購入したので、その日記です。

なぜラズパイを買ったのか

ラズパイを買った目的としては、大きく2つあります。

かっこいいから

ひとつは、なんかかっこいいからです。

自宅内にサーバがあって、それが動いているって、なんだかかっこよくないですか?

自分はサーバ運用等の経験もなく、そのあたりを自分の手元の環境で試したいと思ったため、購入しました。

気軽に使用できるメモ置き場を作りたかった

コードを書いている中で出会ったエラーやその解決に至った流れ、技術書やブログ等を読んで新しく得た知見などはメモに残しておくと後々活用できていいですよね。

今だと、Notion等のサービスも大変便利で、利用されている方も多いのではと思います。

こういうのを車輪の再開発というのかもしれませんが、自分専用のメモ置き場を作ってみたかったというのも、今回ラズパイを買った大きな理由の一つです。

Webサーバの構築・運用をしたり、メモ置き場としてのWebサイトを作成するためにはたくさん勉強しないといけないと思うので自分のスキルを少しでも上げるためにも、ゆっくりになってしまいますが、勉強しながらメモ置き場づくりを進めていきます。

今回購入したラズパイについて

今回はラズパイのZero 2Wというモデルを購入しました。また、ラズパイを購入するのは初めてでしたので、専用のHDMI端子なども付属しているセットを購入しました。

ラズパイZero 2W の初心者セットを購入しました

ラズパイ、思ったより小さくてびっくりしました。AirPodsProと比較するとこんな感じ。

AirPodsProと同じくらいの大きさ!

半導体の供給不足に伴って、商品の在庫が安定しない中、購入サイトをブラっと見てみたら、以前売り切れだったものが再販されておりましたので購入させていただきました。

状況が大変厳しい中、供給してくださったメーカー様ありがとうございます。

これから不定期更新ですが、セットアップの時に行ったことや詰まったことなどを記事にしていこうかと思います。

GitHubインシデントレポート

はじめに

個人開発においてもチーム開発においても大変お世話になっているGit、GitHub

大変便利なツールですが、まだ慣れない点も多く、しばしば使い方を誤ってしまうことがあります。

人間はミスをします。よく労働災害や医療事故などのお話の中に登場する「ハインリッヒの法則」というものがあります。

アメリカの損害保険会社の安全技師であったハインリッヒ氏が発表した法則で、

「同じ人間が起こした330件の災害のうち、1件は重い災害(死亡や手足の切断等の大事故のみではない。)があったとすると、29回の軽傷(応急手当だけですむかすり傷)、傷害のない事故(傷害や物損の可能性があるもの)を300回起こしている。」

というものです。(参考: [厚生労働省]職場のあんぜんサイト

今のところ、大きな事故は起こしていないものの、軽微な事故、事故寸前で気づいたというような失敗も経験しています。大きな事故が起こってしまう前にそれぞれのヒヤリハットについて分析し、どのようにしたらそういったミスが起きないか、という対策を考えることは大事かもしれません。

自戒の念も込めて、自分の恥ずかしいミスを曝そうと思います。「あ~あるある。」というようなミスもあるかもしれませんし、「え!?そんなことしたん?」っていうミスもあるかもしれませんが、今後自分が同じ過ちを犯さないように、簡単にですが、ミスが起こった背景やそれについての対策などを書き残しておこうかと思います。

失敗その1 コンフリクト解消のMerge commitのミス

起こったことを端的に

developブランチから切ったブランチAで作業中。developブランチにブランチBをMergeしたことで、developとブランチAの間でコンフリクトが発生。

それを解除した(できたと思っていた)ら、developブランチにおけるブランチBで実装したコードが全部消えてしまった。

なぜそんなことが起こったか

コンフリクトが起こった時の解消方法については、以前も記事にしました。 yusei-qqq.hatenablog.com

コンフリクトが起こったときはmainやdevelop等のブランチを最新のものにして、開発ブランチにMergeしてあげて、コンフリクトを解消してあげたらよい、という認識でした。

こちらについては概ね間違いではないと思うのですが、自分はコンフリクトが起こっているファイルのみcommitしたのです。

developブランチをブランチAにMergeした際、ブランチBでの実装分の変更がstaging状態で追加されます。これと、今回発生したコンフリクトを解除したものをmerge commitとして commitするべきだったのですが、ブランチAの実装分にブランチBの実装も入ってしまったら、何か良くない気がして、あろうことか、staging状態になっていたブランチBの変更分を git reset --hard + git checkoutして亡き者にしてしまい、コンフリクトが起こっていたファイルのみcommitしてしまったという状況です。

こちらの問題が発生したブランチがmain等の本番ブランチでなかった+デプロイ前であったため、Revert等行うことにより、ブランチBの実装分は元に戻ったのですが、本当に肝を冷やしました。

原因と解決策

こちらが起こった原因に関しては、自分のGitに関する理解不足です。Merge Commitがどのようなものかきちんとわかっていなかったため起こりました。

git mergeを実行して、コンフリクトが発生した場合は素直にコンフリクトの解消を行い、stagingに上がっている変更たちもまとめてcommitしたらよかったです。

また、commit名についても、git commit -m 'コンフリクト解消'のようにしてもいいかと思いますが、git commitだけ実行すると、Merge branch 'master' into developのようなcommitメッセージになるので、「ああ、ここでMergeしたんだな」というのも分かりやすいかと思いました。

コンフリクトの解消

コンフリクト?

チームで開発しているリポジトリにプルリクエストを投げたら、コンフリクトが出ているからMergeできないよ!という旨のメッセージが出ることがある。

コンフリクト(conflict)というと、日本語で「対立」とか「紛争」っていう意味があるみたい。

その意味の通り、これまでにmerge済みの最新バージョンのコードと今回プルリクエストを投げている部分のコードに対立が生じているという意味。

実際にコードを見たほうがわかりやすいかもしれない。

↓ こちらがmainブランチのコード

  6 import { Game } from "./components/Game";
  7 import { app } from './reducers';
  8 import { GameContainer } from './containers'
  9 import './index.css';
 10 // コンフリクトのテスト1

↓ そして、今回mainブランチに向けてPRを飛ばそうと思ったconflict_testブランチのコードがこちら

  6 import { Game } from "./components/Game";
  7 import { app } from './reducers';
  8 import { GameContainer } from './containers'
  9 import './index.css';
 10 // コンフリクトのテスト2

二つのコードを見比べてもらうとわかるかと思うが、同じ10行目に、「// コンフリクトのテスト1」と「// コンフリクトのテスト2」という、それぞれ異なるコメントが入っている。

こうなってしまうと、それぞれのコードがぶつかってしまい、どちらを優先してくっつけたらいいんだい?という状態になってしまう。

これは至極単純な例ではあるが、コンフリクトはこんな感じにして起こる。

Ruby on Railsなどでは新しくモデルにカラムを追加するなどして、マイグレーションを行うとdb/schema.rbが自動で更新されるが、このような自動で更新されてしまうファイルなどでもコンフリクトは起きやすく、また、自動生成されるファイルであるため手動で書き直したりすることは避けたい。

そういった場合はやや方法が複雑になる(コンフリクトしたschema.rbをきれいにマージする手順←チェリー本の著者、伊藤先生がとってもわかりやすい記事を書いてくださっていました!)が、今回は上記のような、至極単純なコンフリクトが起こった際にどのようにしてコンフリクトを解消するのかをメモしておこうと思う。

コンフリクト、どう直す?

ここでは上で例として示したコンフリクトを解消する方法について書いていく。

登場するブランチ

  • main
  • conflict_test(現在こちらのブランチにて作業中。以下、作業ブランチとして説明する)

作業しているファイル

  • src/index.js

PR先のブランチを最新の状態にする

git checkout mainでmainブランチに切り替える。

続いて、git pull origin mainでリモートリポジトリの最新の更新分をローカルリポジトリにpullする

これで、mainブランチは最新の状態となった。

作業ブランチに戻る

git checkout conflict_testで作業ブランチに戻る。

mainブランチの内容を作業ブランチにmerge

git branchコマンド等で、現在いるブランチが作業ブランチであることが確認する。

git merge mainとすると、mainブランチの内容を作業ブランチにmergeできる。

しかし、今回はコンフリクトが発生しているため、「はい、mergeできましたよ」とはならない。

Auto-merging src/index.js
CONFLICT (content): Merge conflict in src/index.js
Automatic merge failed; fix conflicts and then commit the result.

このようなエラー分がでるはず。簡単に訳すと、「コンフリクトが起きているから、自動mergeできなかったよ」という感じか。

テキストエディタで当該ファイルを開くと

  6 import { Game } from "./components/Game";
  7 import { app } from './reducers';
  8 import { GameContainer } from './containers'
  9 import './index.css';
 10 <<<<<<< HEAD
 11  // コンフリクトのテスト2
 12 =======
 13  // コンフリクトのテスト1
 14 >>>>>>> conflict

という風に表示されている。

コンフリクトしている部分を正しい内容に修正してあげる

先ほどのコンフリクト部分は以下のように修正した。

  6 import { Game } from "./components/Game";
  7 import { app } from './reducers';
  8 import { GameContainer } from './containers'
  9 import './index.css';
 10  // コンフリクトのテスト1
 11  // コンフリクトのテスト2

修正したらgit add src/index.jsでステージにあげる。

この段階で、git statusをしてみると

On branch conflict_test
All conflicts fixed but you are still merging.
  (use "git commit" to conclude merge)

Changes to be committed:
        modified:   src/index.js

無事、コンフリクトは解消されたようです。まだmergeされていないので、commitせよ、と言われているので、

git commit -m 'コンフリクトを解消'というようにして、commitし、リモートリポジトリにpushする。これでPRのページを見てもらうと、おそらくコンフリクトは解消されており、 mergeできるようになっているはず。

さいごに

以上、簡単なコンフリクトを解消する方法でした。

実際に困るのは途中でも書いたような、フレームワークなどによって自動生成される部分のコンフリクトかもしれない。上記で紹介した、伊藤先生の記事が本当にわかりやすく、自分もかなり助けられました。

また、特定のコミットを引っこ抜いてくる、cherry-pickという技もあるので、こちらも併せて読んでおくといいかもしれません!

【Git】cherry-pickで解決🍒

ERBでクラスの宣言がうまく出来なかった話

ERBを使っていて困ったこと

以前、生のRubyでWebアプリを作成する、「作りながら学ぶRuby入門 第2版」という本を読んでいたとき、データベースとの連携をActiveRecordを使用して行った。

RubyのファイルでActiveRecordを使用して、例えばbooksというテーブルのレコードを操作する場合、

class Book <ActiveRecord::Base
end

のような宣言をしてから

book = Book.find(1)

という感じで、レコードを探したりしていた。

Webアプリを作成するにあたって、ERBというテンプレートエンジンを利用してhtml形式の中でRubyのコードを使う場面があった。

その際に、データベースに接続して操作することがあり、erbファイル内で上記のようなクラスの宣言をしようと思って

<% class Book < ActiveRecord::Base %>
<% end %>

というような記述をした。そうすると、エラーがでてしまい、うまくクラスを読み込むことができず、データベースの操作がままならなかった。

解決策

このときは、上記のようなクラスの宣言の仕方ができないのなら、Book.rbのような別ファイルを作成し、

(Book.rb)
class Book < ActiveRecord::Base
end

それをERB側でrequireする形で実装した。

(books_show.erb)
<% require "<Book.rbのパス>/Book" %>

かなり泥臭い方法での実装となってしまったが、これでやりたいことはできた。もっといい解決策があれば取り入れていきたいです。

短いですけど、今回はこのくらいで!それではまた。

生RubyでActiveRecordを使ってみる(接続編)

生のRubyで色々頑張ってみた

最近 、久保秋真先生の「作りながら学ぶRuby入門 第2版」という本を読みながらRuby門中

他の入門書とはだいぶ色が違って、文法の細かい解説等は必要最低限な入門書。とにかく「作りながら」学んでいく、パラシュート学習法を体現したような本。

正直、この本からRubyを始めます!って言う人には勧めにくいが、一度他の書籍でRubyの基本的な文法を学んだ後に取り組むにはいい感じ。

他の書籍だと、文法等の解説が細かい分、サンプルコードというか、書籍の中で作り上げるサンプルプログラムの規模に限界がある。

本書だと、文法の解説を最小限にした分、出来上がるサンプルプログラムはDBMSと連携させたり、実際にWebアプリとしての形で完成するものとなっている。

世の中にはRuby on Railsという便利なフレームワークがあるではないか、という人もいるかもしれない。

ただ、フレームワークは様々な機能を裏側でやってくれており、使う側も中でどのような処理が行われているのか理解しないまま使っていることも多いのかもしれない。

少なくとも、自分はそうでした。

こういった便利なツールの裏側でどんな魔法が使われているのか、少し紐解いていくことでコードがスッキリかけたり、見慣れないエラーが出た時の対応も、訳もわからず使っている時よりはしやすいはず。

Rubyでデータベースとの連携をやってみる

前置きが長くなったが、とりあえず本書の教えの通り、純真無垢な生Rubyであれやこれやすることにした。

準備編

まずはDBとの連携だが、本書のサンプルコードではDBIというライブラリを使用してSQLite3と連携している。DBIについて調べているとRuby/DBI ライブラリ・リファレンスに以下のような記述が…

[2021.5] Ruby/DBI はすでに完全に廃れています。'dbi' gem パッケージは 2010 年が最終です。'activerecord' が代替です。

なんてこったい。

ちょっと大変かもしれないが、廃れているDBIを覚えるなら、ActiveRecordで読み替えながらやってみようじゃないか、と思ったわけです。

ActiveRecordのことを調べると大抵はRuby on Railsの記事ばかりでしたが、こちらの記事を見つけた。

[Qiita]Ruby 単体で ActiveRecord を使いたい

この記事ではMySQLを使用しており、せっかくだからMySQLも環境構築してみることにしました。(別記事で環境構築で大変だったことなどを書きます!)

Ruby側でDB接続設定

さて、MySQL側でデータベース作成やテーブル作成が済んだら、Ruby側でDBの接続設定を記載します。

require 'active_record'

ActiveRecord::Base.establish_connection(
    adapter:  'mysql2',
    host:     'localhost',
    username: '<user_name>', # 設定したユーザー名またはroot
    password: '<password>',  # 設定したパスワード
    database: '<database_name>' # 使用するデータベース名
)

これで準備したMySQLのデータベースと接続することができます。

ただ、毎回これを書くのは面倒だし、Git等でバージョン管理する上で、パスワード直書きはなんだか怖い。

もう少し調べてみると、yamlファイルにこれらの設定を書き出してRuby側でyamlファイルを読み込むことで、データベースへの接続を行う方法をとっている方もいました。

yamlファイルに接続設定を記載する方法

まずはdatabase.ymlを作成。

db:
  sample:
    adapter: 'mysql2'
    host: 'localhost'
    username: '<user_name>', 
    password: '<password>',
    database: 'sample' 

  bookinfos:
    adapter: 'mysql2'
    host: 'localhost'
    username: '<user_name>', 
    password: '<password>',
    database: 'bookinfos' 

のように記載しておく。

Ruby側では以下のように記載してデータベースと接続する。

require 'yaml'
require 'active_record'

# データベースに接続する

config = YAML.load_file('<yamlファイルへのパス>')
ActiveRecord::Base.establish_connection(config['db']['sample'])

接続完了パチパチ

これでデータベースとは接続できたわけだけど、少し気になることがありました。

Railsで同じようにyamlファイルにDBの接続設定を書き出して接続している人のコードだと、ActiveRecord::Base.establish_connection(config[db:]['sample'])みたいに、dbのところをシンボルで渡しているんですよね。

最初、それを真似してシンボルで書いたらエラーが出ました。

Rubyyamlライブラリでyamlファイルを読み込んで、出力するとわかるのだが、中身はハッシュになっている。しかもハッシュのキー、つまり先ほどのdbの部分は文字列でした。

それで文字列を渡さないとエラーが出ちゃうんだね。

調べてみると、Railsの方ではHashクラスをいじってあるらしくて、そのおかげでシンボルを渡して接続することができているみたい。

余談

とりあえず接続できればいいじゃんって言う人にとってはどうでもいい内容なのかもしれないけど、こういったことを知ることができてよかった。

Rubyって動的型付け言語だからデータ型を意識することって少ないのかも知れないけれど、だからこそメソッドがどういうデータの型を返すのか、とか返されたハッシュのキーはシンボルなのか文字列なのか、とかそういったことを意識することが大事なんだと思います。

これらを意識していると、不意に「引数がちょっとおかしいぞ」っていうエラーが出た時などの対応力がついてくるんじゃないかな、と思います。メソッドの内容を噛み砕いて説明してあるブログ(スクールが書いてるブログ等)にはあんまり載っていないんですよね、こういうこと。

公式リファレンスにはこのような情報がしっかり書かれています。何か新しいメソッドとか、わからないことがあったらまずはリファレンスに帰る!それでも分かりにくいことがあったら、噛み砕いて書いてくれてある記事やQiitaなどを参考にしてみるといいかもしれませんね。

ちょっと長くなってしまいましたが、これで生RubyActiveRecordを使ってみる(接続編)はおしまいです!ありがとうございました。Rubyたのしい!

参考: Ruby3.1 リファレンスマニュアル library yaml | プログラマーのためのYAML入門(初級編)