Ruby

こんにちは、しきゆらです。
今回は、タイトル通り非Railsアプリのデプロイ作業をCapistranoで自動化するための手順をメモしておきます。

Capistranoといえば、Ruby製のデプロイツールです。
A remote server automation and deployment tool written in Ruby. | https://capistranorb.com/

Capistranoさん自体はRubyやRails専用ではなく、様々なものをデプロイすることができるように設計されています。
とはいえ、調べて出てくる情報の大半はRailsのデプロイについてばかり。
Sinatraのデプロイすら情報が少ないような状態です。
そんな中で、非Railsどころかただ単にCronなどで定期実行するだけの簡単なスクリプトを自動でデプロイするのを自動化する情報なんて見つけるのが難しい。

ということで、今回はフレームワークを使っていないただのRubyスクリプトをCapistranoを使ってサーバへデプロイする方法をメモしておきます。

日記

こんにちは、しきゆらです。
今回は、久々に買った商品を紹介してみます。

だいぶ古い記事ですが、「【日記】iPod ClassicをBluetoothで無線化する」で無線デビューした私ですが
ここからBluetoothヘッドホンやイヤホンを使うようになりました。
煩わしい線がなく、音楽プレイヤーを携帯していればどこでも使えるためとても便利になりました。
(無線化する前は、部屋の中を移動できるように3mのケーブルでヘッドホンを使っていました・・・懐かしい)

 

Ruby

こんにちは、しきゆらです。
気が付けば、7月が終わっていました。

今回は、ちょいちょい書くRSpecさんの記述で見たことないものが出てきたのでメモしておきます。
タイトル通り「described_class」というものです。

こいつは何かというと、ドキュメントによると以下の通り。

If the first argument to an example group is a class, the class is exposed to
each example in that example group via thedescribed_class()method.

described class – Metadata – RSpec Core – RSpec – Relish | https://relishapp.com/rspec/rspec-core/v/3-9/docs/metadata/described-class

簡単に言えば、RSpecの最初に「RSpec.describe ClassNamedo」のように書くと思いますが、
このClassNameを参照するためのメソッドのようです。

確かに、このクラスのSpecですよ、と宣言しているので何度も参照することになるとは思いますが、まさか専用のメソッドが用意されているとは知りませんでした。

 

今回は、これだけ。
おわり

Mac

こんにちは、shikiyuraです。
今回は、タイトル通りMacでcronを使わずにコマンドを定期実行する方法をメモしておきます。

コマンドを定期実行するためによく使われるものは、cronだと思います。
私も、今回のことがなければ真っ先に思い浮かぶものはcronです。
Macにもcronはあるようですが、権限やOSのセキュリティの壁などにふさがれて気軽に動かせないようです。

参考

では、どうすればいいのか。
Macに入っているlaunchdというものを使えばいいのです。
launchdとは、デーモンとエージェントを管理してくれるものです。
Macの「ターミナル」でのlaunchdを使ったスクリプトの管理 – Apple サポート | https://support.apple.com/ja-jp/guide/terminal/apdc6c1077b-5d5d-4d35-9c19-60f2397b2369/mac

裏側で自動起動させたり、定期的にコマンド実行させたりすることも可能です。
では、こいつらを使ってcronの代わりに特定コマンドを定期実行できるようにしてみます。

Windows,環境構築

2021/07/19追記

またまた手順が変わっていたので、改めて記事をまとめなおしました。
こちらの記事をご覧下さい。
【WSL2】Ubuntu 20.04でPID1をsystemdにする 2021年7月版

2020/08/19追記

Win環境を構築しなおして、こちらの手順をやったところうまくいきませんでした。
まとめ直した記事を公開していますので、よろしければこちらもよろしくお願いします。
【WSL2】Ubuntu20.04でPID1をSystemdにする

本文

こんにちは、しきゆらです。
今回は、前回なんとか動くようになったsystemctlについて調べなおしつつ、きちんと動くようになったので改めてメモしておきます。

前回、【WSL】WSL2でMySQL8.0が動かないのを解決するにて、mysqlを動かすために systemctlをごにょごにょして動くようにしました。
ひとまず動くようにはなったんですが、自動起動させてもきちんと動いてくれず困っていました。
今回は、そもそもなぜsystemctlさんが動かないのかを調べつつ、解決方法が見つかったのでメモしておきます。

Windows,環境構築

こんにちは、しきゆらです。

気が付いたらWSL2が正式対応になっていました。
いい時代になりましたね。
Linux環境のためにWindowsに仮想環境を立ち上げたり、高いMacに移行しなくても、お手軽に開発環境を整えることができるようになりました。

開発環境もWindows、面倒が少なくてよい。

さて、先日PCを組みなおしたためOSがまっさらになっていたので、改めてWSL2の環境構築を行いました。
そんな中で、MySQL8.0を使おうとしたときに詰まったので、その様子と解決までの流れをメモしておきます。
(組みなおしたPCについては、興味がないと思うので書きません)

Windows,環境構築

こんにちは、しきゆらです。
今回は、先日1.0 になったWindows TerminalさんをUbuntuのターミナルっぽくしてみたのでメモしておきます。

以前、MacのターミナルをUbuntuのターミナルっぽくする記事を書きましたが、そのWindows版ですね。

Windows TerminalさんをUbuntuのターミナルっぽくしたくて調べてみたところ、海外のサイトで配色の情報をまとめてくれているところがありました。
https://superuser.com/questions/497240/ubuntu-purple-terminal-colors-in-conemu | windows – Ubuntu purple terminal colors in ConEmu – Super User
そこを参考に、Windows Terminalさんの設定をしています。

では、いかにUbuntuっぽいカラースキーマをドーン。
久々に設定ファイルを覗いたのですが、割とわかりやすくなっていますね。
少し前に見たときは、色を配列にぶち込んであるだけで、どれがどこに対応しているのかわかりにくかったのですが、
きちんと色の名前をキーとして設定できるようになっていました。

"schemes": 
[
  {
    "name" : "Ubuntu Like",
    "cursorColor": "#FFFFFF",
    "selectionBackground": "#FFFFFF",
    "background" : "#300A24",
    "foreground" : "#CCCCCC",
    "black" : "#2e3436",
    "blue" : "#3465a4",
    "cyan" : "#06989a",
    "green" : "#4e9a06",
    "purple" : "#75507b",
    "red" : "#cc0000",
    "white" : "#d3d7cf",
    "yellow" : "#c4a000",
    "brightBlack" : "#555753",
    "brightBlue" : "#729fcf",
    "brightCyan" : "#34e2e2",
    "brightGreen" : "#8ae234",
    "brightPurple" : "#ad7fa8",
    "brightRed" : "#ef2929",
    "brightWhite" : "#eeeeec",
    "brightYellow" : "#fce94f"
  }
],

あとは、上記のスキーマを良しなに適応してあげればOK。

{
  "guid": "{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}",
  "hidden": false,
  "name": "Ubuntu",
  "colorScheme": "Ubuntu Like", // ここに指定してあげればOK
  "source": "Windows.Terminal.Wsl"
}

これにて、Windows TerminalさんをUbuntuのターミナルっぽくすることができました。
あとは、プロンプトを良しなに設定したりすればよいですね。

ようやくWindowsでもまともなターミナルが使えるようになりました。
ターミナルがまともになったので、Macに移行していた開発環境をWSL上に作ってもよさそうですね。
WSL自体も改良されているのと、Windowsとの親和性も向上するようなので、本格的に開発環境をWindowsで構築してもよさそう。
いい時代になりました。

 

さて、今回はここまで。

おわり

Ruby

こんにちは、しきゆらです。
なんかあれこれしているうちに今年もほぼ半分ほど過ぎていました。
早いものです。

今回は、SeleniumでAlertが表示されるまでの間待機したいことがあったので、調べて解決したのでメモしておきます。

Ruby

こんにちは、しきゆらです。
気が付くと、年が明けて2月です。

今回は、先輩に教えてもらった謎のコードを解読していきます。
謎のコードとは下記のもの。

[ruby]
ObjectSpace.each_object(ActiveRecord::Relation).each(&:reset)
GC.start
[/ruby]

いきさつ

AWS上にあるインスタンスでRailsを動かしていました。
その中で、DBのデータにミスがあったので、1.5万件ほどのデータに紐づく諸々の差し替え作業を行っていました。
このときにおこった問題としては「メモリ使い過ぎで怒られる」という状況でした。
コードを書き換えたりループを工夫したりしても解決せず困っていたとこで先輩が下記のようなコードを教えてくれました。

[ruby]
ModelClass.find_in_batches do |objects|
# 差し替える処理

ObjectSpace.each_object(ActiveRecord::Relation).each(&:reset) # ???
GC.start # ???
end
[/ruby]

このコードが入ると、途中で処理を止められることなく走らせることができるようになりました。

その当時は、先輩すげぇ~と思いながら後で調べておこうと思ってメモしておきました。
そのまま放置されていたものを思い出したので、時間のあるうちに調べてみよう、ということで調べてみました。

ObjectSpaceとは

そもそも、見慣れないクラス名です。
調べてみると、Rubyさんの組み込みモジュールでした。
リファレンスでは

全てのオブジェクトを操作するためのモジュール
module ObjectSpace (Ruby 2.7.0 リファレンスマニュアル)

とのこと。

わかるようなわからないような・・・という感じですが、定義されているメソッド類を見てみると
Rubyで定義したオブジェクトたちに対してあれこれしたり、プロファイルを取るときなどに使われるもののようでした。

ObjectSpace#each_object

その中に、ありました「each_object」メソッド。
「ObjectSpace」が何かわかれば、メソッド名で何をするものなのか大方予想が付きますね。

調べてみると、

指定されたクラスとObject#kind_of?の関係にあるすべてのオブジェクトに対して繰り返す
ObjectSpace.#each_object (Ruby 2.7.0 リファレンスマニュアル)

とのこと。
上記のコードでは「ActiveRecord::Relation」クラスのオブジェクトすべてに対する処理を行うということですね。

こいつは、ブロックを渡すとそのブロックを実行し、繰り返し回数を返すようです。
そして、ブロックが渡らない場合はEnumeratorオブジェクトを返すとのこと。
上記のコードでは、eachメソッドをつなげているので後者ですね。

なお、引数を与えなければすべてのオブジェクトに対して繰り返すようです。
また、Fixnumなどは対象外のようです。

つまり、上記コードの1行目はActiveRecord::Relationクラスのすべてのオブジェクト一つ一つに対して「reset」メソッドを呼び出していることになりますね。

ActiveRecord::Retation#reset

では、「ActiveRecord::Retation#reset」は何者でしょうか。

定義を確認してみると、内部で保持しているデータをすべて破棄しているようです。

つまり、上記コードの1行目が実行されたら、「ActiveRecord::Retationのオブジェクト」はすべて空のデータとなるようです。
1行目の内容は把握できました。
2行目を追っていきます。

GC

見たままGCでしょうね。
一応調べてみると、RubyのGCを制御するためのモジュールでした。
正確な情報は持っていませんが、イメージとしては使用していないデータを解放する仕組みという認識です。
メモリ上にあるいらないものを削除してきれいにしてくれる裏方さん。

GC#start

もう、見たままでしょう。
GC.start (Ruby 2.7.0 リファレンスマニュアル)
GCの処理を始めるためのメソッドです。

別メソッドでGCを禁止するようなこともできるようですが、このメソッドで実行した場合はGCを始めるようです。

すべてを見たうえで

[ruby]
ObjectSpace.each_object(ActiveRecord::Relation).each(&:reset)
GC.start
[/ruby]

たった2行のコードですが、知らないことが満載でした。
処理を簡単にまとめると、この処理の前までに作成されたすべてのActiveRecord::Relationオブジェクトを空にしてGCに削除してもらう感じでしょうか。

1.5万件のデータを処理していると、たくさんの不要なオブジェクトがたまっていき途中で利用できるメモリサイズをオーバーしてしまうということで、それを防ぐために一定の処理を終えると不要になったオブジェクトを削除して次に進む、ということを行っているようですね。

find_eachやfind_in_batchesなどである程度の粒度で処理することなどはわかっていましたが、それですら怒られるのでどうすればいいのかわからないところで、まさか自分でGCを動かして削除させることができるとは・・・。

まだまだ知らないことがいっぱいあるということですね。
まぁよく使うことではないとは思いますが、知っていると困ったときに役に立ちそうです。

まとめ

今回は、先輩が教えてくれた謎のコードを調べながら内容を理解してみました。
ActiveRecordなど、Githubで公開されているコードについては中身を読むことができるので、きちんと中身を知っておくことは大事だなと思いました。

 

今回は、ここまで。
おわり。

Ruby

こんにちは、しきゆらです。
今回は、文字列の先頭・末尾にある特定のものを正規表現で頑張らずとも判定する方法を知ったのでメモしておきます。

文字列の中に、特定のものが入っているかを判定するためには正規表現というものを使う場合があります。
そして、含まれているかどうかを判定するためのメソッドとして「String#match?」があります。
instance method String#match? (Ruby 2.6.0 リファレンスマニュアル)

しかし、文字列の先頭・末尾が特定のものかどうかを判定するためにmatch?を使うのはもったいないことでした。
というのも、この時にはより状況にマッチしたメソッドがあるからです。
それが「String#start_with?」「String#end_with?」です。
instance method String#start_with? (Ruby 2.6.0 リファレンスマニュアル)
instance method String#end_with? (Ruby 2.6.0 リファレンスマニュアル)

これらのメソッドは、機能はシンプルだが高速に処理できるようです。
Ruby: 文字列マッチは正規表現より先に専用メソッドを使おう
Ruby の文字列マッチ判定のパフォーマンス · Yuichi Takada

ということで、知らないメソッドシリーズでした。
ちなみに、これらはrubocop-performanceで怒ってもらえるようです。
Class: RuboCop::Cop::Performance::StartWith — Documentation for bbatsov/RuboCop (master)

今回、はここまで。
おわり