【Ruby 3.0 Advent Calendar 2020】ArrayやStringのメソッドの返り値が変更された話【15日目】

はじめに

Ruby 3.0 Advent Calendar 2020 15日目の記事になります。

昨日は、「Ruby3.0で導入される型定義!TypeprofでBlockやProcを解析してみる」です。

qiita.com

今日は、ArrayStringの返り値が変更された話を紹介します。

これまでの返り値

これまでのRubyではArrayStringを継承したクラスで新しくオブジェクトを作成し、メソッドを実行した際の戻り値が一定のものではありませんでした。

class SubArray < Array
end

sub = SubArray.new([1, 2, 3])
p sub
p sub.class.name
# => SubArray
p sub.uniq.class.name
# => SubArray
p sub.rotate.class.name
# => Array

その為、戻り値のオブジェクトがどのクラスかを確認しなければならなくなり、非常に能率の良くない状況がありました。

実際にArrayの戻り値のクラスが一定ではないことに関してチケットも作成されていました。

bugs.ruby-lang.org

Ruby 3.0ではどうなるのか?

Ruby 3.0ではArrayStringを継承したクラスを使って作成されたに対して継承元(ArrayとかString)のクラスのメソッドを実行すると以下のように継承元のクラスのオブジェクトが返ります。

class SubArray < Array
end

sub = SubArray.new([1, 2, 3])
p sub
p sub.class.name
# => SubArray
p sub.uniq.class.name
# => Array
p sub.rotate.class.name
# => Array

継承を使って作成したSubArrayから一律でArrayが返ってくるので分かりやすくなってますね。 こういうケースだと、SubArrayが返ってくれた方が良かったりすんじゃないかと思ったりもしますが、どちらかにそろっているのは分かり易くてよさそうです

参考

github.com

bugs.ruby-lang.org

【Ruby 3.0 Advent Calendar 2020】Win32APIが廃止された【11日目】

はじめに

Ruby 3.0 Advent Calendar 2020 11日目の記事になります。

昨日は、【Ruby 3.0 Advent Calendar 2020】Arguments forwardingがちょっと便利になった【10日目】です。

gamelinks007.hatenablog.com

今日は、Win323APIが廃止されたことを紹介します。

Win32APIとは?

WIndowsの32bit用のAPIのことで、WindowsAPIを使うことで簡単にメッセージボックスなどを作成することができます。 WindowsではそれらのAPIを経由してWindowsアプリケーションを作ることが出来たりします。

廃止されたWin32API

今回廃止されたのはWin32APIをRubyから呼び出す部分のようですね。 Rubyでは、1.9.1以降からdeprecatedとなっていたようで、今回のRuby3.0のリリースに合わせて廃止されたようです。

github.com

ちなみにチケットはこちら

bugs.ruby-lang.org

ちなみに、代替としてfiddleというライブラリを使うようです。 fiddleからダイナミックリンクライブラリを読み込んで、読み込んだライブラリ経由でAPIを実行する感じっぽい?

docs.ruby-lang.org

ちなみに、他のRuby内部のコードでWin32APIを使っている箇所はfiddleに置き換えられたりしてます。

github.com

Windowsを使うRubyユーザーでWin32APIを使っているという人たちは対応が必要そうですが、母数はあまり多くないかもしれませんね。

参考

ruby-trunk-changes.hatenablog.com

bugs.ruby-lang.org

github.com

【Ruby 3.0 Advent Calendar 2020】Arguments forwardingがちょっと便利になった【10日目】

はじめに

Ruby 3.0 Advent Calendar 2020 10日目の記事になります。

昨日は、【Ruby 3.0 Advent Calendar 2020】Ruby 3.0.0-preview2 がリリースされた【9日目】です。

secret-garden.hatenablog.com

今日はRuby 3.0で入ったArguments forwardingの変更について解説します。

Arguments forwardingって?

Arguments forwardingとはRuby 2.7で入った機能で、メソッドに渡された引数をそのままフォワード(転送)するというものです。

def hoge(arg)
    puts "arg is #{arg}"
end

def foo(...)
    hoge(...)
end

foo(1)

上記のようにメソッドfooに渡された引数をそのままメソッドhogeに渡すことができます。 ちなみに、今回の例では引数を一つだけ渡していますが、複数の引数を以下のように渡すこともできます。

def hoge(arg1, arg2)
    puts "arg1 is #{arg1}"
    puts "arg2 is #{arg2}"
end

def foo(...)
    hoge(...)
end

foo(1, 2)
# => arg1 is 1
# => arg2 is 2 

Ruby 3.0で入った変更

以下のようにフォワード(転送)された引数の最初の引数を受け取ることができます。

def hoge(arg1, arg2)
    puts "arg1 is #{arg1}"
    puts "arg2 is #{arg2}"
end

def foo(first, ...)
    puts "first is #{first}"
    hoge(...)
end

foo(1, 2, 3)
# => first is 1
# => arg1 is 2
# => arg2 is 3

引数をそのまま渡したいが、引数の最初だけ特定のメソッドに渡したいケースなどで重宝しそうです。

ちなみに、この機能を使うと以下のようなコードが簡単に書けます。

def arg_forward(arg, ...)
    puts arg
    arg_forward(...)
rescue => e
    puts :finish
end

arg_forward(1, 2, 3)
# => 1
# => 2
# => 3
# => finish

再帰させて引数を一つづつ出力することが簡単に書けます。

再帰周りとかのコードは書きやすそうなので重宝しそうですね。

参考

github.com

bugs.ruby-lang.org

koic.hatenablog.com

さくらのVPSでのNginx+ティラノスクリプトでのリリース処理

はじめに

この記事は過去に書いた以下の記事のティラノスクリプトのゲームをさくらのVPSにリリースした時の覚書です。

gamelinks007.hatenablog.com

前提

さくらのVPSとNginxを使い、ティラノスクリプトのゲームをリリースする手順。 前提として標準OSのインストールでUbuntu18.04を選択してインストール済みであること

またLetsencryptを使ってSSL化するまでの処理も記載しておく

基本的にパッケージマネージャからNginxやLestsencryptをインストールので他のUbuntu(20.04とか)でも基本的にリリースできると思う

手順

まずは、さくらのVPSへとログインする。ログイン用のパスワードやアカウントはOSの標準インストール時に設定したユーザー名とパスワードでログイン

login: ubuntu
passowrd: hogehoge

ログイン後、まずはパッケージのアップデートをする

sudo apt update

アップデートが完了後、必要なパッケージをインストールしていく

sudo apt install -y nginx letsencrypt git

今回はGitHubで管理しているティラノスクリプトのゲームを使用するためgitをインストールしている

インストール完了後、ホームディレクトリ以下にティラノスクリプトのゲームをcloneしてくる

git clone https://github.com/username/tyrano_game_name.git

次に、Nginxの設定を編集する。編集する内容としてはNginxが静的なコンテンツを返している部分を編集するので/etc/nginx/sites-enabled/defaultviなどで開いて以下のようにする

server {
    listen 80;
    listen 80 [::]:80
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl default_server;
    listen 443 [::]:443 ssl default_server;
    
    root /home/ubuntu/tyrano_game_name/;
}

なお、ポートの80にアクセスした場合は強制的に443へとリダイレクトさせている。

次に、SSL証明書の設定を行う。

まずはNginxをいったん止める

sudo systemctl stop nginx

これはSSL証明書の発行時にエラーが発生するのを回避するため

次に、Letsencryptを使って証明書を発行する

sudo letsencrypt certonly --standalone -d domain

証明書発行後、証明書が格納されているディレクトリへのアクセス権限を付与

cd /etc/letsencrypt && sudo chmod 777 live && sudo chmod 777 domain

最後に、SSL証明書を使うようにNginxの設定を変更

server {
    listen 80;
    listen 80 [::]:80
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl default_server;
    listen 443 [::]:443 ssl default_server;
    ssl_certificate     /etc/letsencrypt/live/domain/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/domain/privkey.pem;
    
    root /home/ubuntu/tyrano_game_name/;
}

これで設定はOK!

あとは設定を再読み込みして、Nginxを動かせばリリースは完了

sudo systemctl reload nginx
sudo systemctl start nginx

注意点

SSL証明書ディレクトリへの権限はreadonlyにした方が良いかもしれないので変更しておくといいかも

あと、80にアクセスするときのリクエストは別にわたさなくてもいいかもしれない

【Ruby 3.0 Advent Calendar 2020】Ruby3.0で非推奨から廃止になるメソッドたち【4日目】

はじめに

Ruby 3.0 Advent Calendar 2020 4日目の記事になります。

昨日は、【Ruby 3.0 Advent Calendar 2020】Ruby3.0でRubyで実装されたメソッドたち【3日目】です。

gamelinks007.hatenablog.com


長らく非推奨だったメソッドを「Ruby3.0のリリースに合わせて廃止しようぜ」みたいな動きがあったりします(最近のruby-trunk-changesやGitHub上にあるRubyリポジトリとか見てると)

今日は長らく非推奨だったがRuby3.0で廃止されるメソッドについて一部紹介します。

廃止されるメソッド

ENV#index

github.com

1.9のあたりからdeprecatedの警告が表示されていたENV#indexを廃止しています。
引数に渡された値に対応するkeyを返すメソッドです。今後は代わりにENV#keyを使うことになりまね

IO周りのメソッドとARGF周りのメソッド

github.com

IO#linesIO#bytesIO#charsIO#codepoints
ARGF#linesARGF#bytesARGF#charsARGF#codepointsが廃止されています。

IO#linesARGF#linesは今後IO#each_lineARGF#each_lineを使うことになりです。
その他のメソッドも同様にeachがprefixについたメソッドを使うことになりそうです

リリースまでに廃止されそうなメソッド

github.com

このPRに記載されているメソッドなどはまとめて廃止されそうですね。
とはいえ、まだ議論中のようで廃止されるのは濃厚ですが、Ruby3.0で廃止されるかはまだわかりません。

また、こちらのTime#succもRuby3.0で廃止される可能性が高そうです。

github.com

おわりに

ここで紹介したメソッドは廃止されるため、使用されているgemなどを見かけたらコントリビューションチャンスかもしれませんね。
また廃止されるメソッドを知っておくことでRuby3.0へのバージョンアップ対応もスムーズに行けそうですね。

【Ruby 3.0 Advent Calendar 2020】Ruby3.0でRubyで実装されたメソッドたち【3日目】

はじめに

Ruby 3.0 Advent Calendar 2020 3日目の記事になります。

昨日は、【Ruby 3.0 Advent Calendar 2020】Ruby3.0に投げたPull Request【2日目】です。

gamelinks007.hatenablog.com

今日はRuby 2.7から対応されている一部メソッドがRubyで実装されていることに触れつつ、Ruby3.0でRubyで実装されたメソッドたちを一部紹介します。

RubyRubyを実装する

まずRubyRubyを実装するというのがいまいちピンとこない方もいると思いますので軽く説明します。

RubyRubyを実装するという提案はko1さんがRubyKaigi 2019で発表された内容を元に導入されました。

rubykaigi.org

youtu.be

発表されている内容をかいつまむと、組み込みメソッドでキーワード引数を受け取るメソッドやメソッドの内部で例外処理(Cのコードでrb_rescue()を使用しているケース)をしている場合などで高速化できるというものです。
ただし、キーワード引数周りで高速化する場合はキーワード引数を渡さず実行すると遅くなる可能性があります。

また最近ではInteger#to_iのような自分自身を返す組み込みメソッドなども高速化(またはCのコードで実装した場合と同程度の速度)ができることが分かっています。

実はRuby 2.7の段階で既に一部のメソッドはRuby(とC)で書かれていたりします。
具体的にはKernel#warnとかTracePoint#inspectとかですね。

今日はRuby3.0で新しくRuby(とC)で実装されたメソッドを一部ですが紹介していきます。

Rubyで実装されたメソッドたち

Arrayクラス

*** Array#shuffle! & Array#shuffle

github.com


github.com


Array#shuffle!Array#shuffleはキーワード引数としてramdomを指定でき、渡したRamdomオブジェクトを元に疑似乱数列を作ることができます。

キーワード引数を使っている組み込みメソッドなので高速化の一環としてRubyで実装されていると思われますね。

*** Array#sample

github.com


こちらも同様にキーワード引数としてramdomを指定できます。こちらは乱数ジェネレータとして使用されているようです。
同様に高速化の一環としてRubyで実装されていると思われます。

Dirクラス

*** Dir.open & Dir.new

github.com


github.com


引数に渡したpathを元にディレクトリストリームを開く特異メソッドです。
キーワード引数でディレクトリのエンコーディングを指定することができます。

なので、今後は少しディレクトリを開くのが速くなるかもしれませんね。

*** Dir.[] & Dir.glob

github.com

github.com


パターンにマッチするファイル名を文字列の配列として返す特異メソッドです。
basesortなどのキーワード引数でベースディレクトリの指定やソートなどが指定できます。

キーワード引数周りの高速化の一環として導入されているようです。
つまりRuby3.0では今までより少し速くディレクトリの走査ができそうですね!

Integerクラス

Integer#abs & Integer#magnitude


github.com

自分自身の絶対値を返すメソッドです。
このメソッドはキーワード引数などは使われていませんが、高速化出来ているものです。
また特徴的な点は、selfをCの関数に渡している点ですね。

この実装が入る少し前にRuby側の変数をCの関数に渡すことができるようになるコミットが入っています(ただし、組み込みメソッドの実装でのみですね)
これを使って実装されているため速度向上などが図れたと思われます。

Kernelモジュール

Kernel#clone

github.com

オブジェクトの複製を返すメソッドです。キーワード引数を使うことでfreezeされたオブジェクトを返すこともできます。
これもキーワード引数周りの高速化で導入されたものですね。

ちなみにこれは僕がPR出したやつだったりします。

Kernel#Float

github.com

引数に渡されたものをFloatへと変換を試みるメソッドです。
キーワード引数で例外を返すかどうかを選ぶことができます。

これも僕がPR出したもので結構速くなってます。

おわりに

ここで紹介したメソッドたちはRubyで実装されたメソッドの中の一部です。
これ以外にもいくつかのメソッドがRubyで実装されています。

また現在、僕が投げている提案ではTrueClassのいくつかのメソッドをRubyで書いて高速化できるんじゃないかと考えています。

bugs.ruby-lang.org

このようにRubyを書くことでRuby本体の性能向上に一役買うことも今後できるかもしれません
「Cは書けないけど、Rubyなら書ける」という方も今後コントリビューションできるようになるかもしれないので夢が広がりそうですね

【Ruby 3.0 Advent Calendar 2020】Ruby3.0に投げたPull Request【2日目】

はじめに

Ruby 3.0 Advent Calendar 2020 2日目の記事になります。

昨日は、【Ruby 3.0 Advent Calendar 2020】Ruby に右代入がやってくる【1日目】です。
secret-garden.hatenablog.com

右代入、このまま何事もなく入るといいなぁ……

この記事では、僕が投げたPull Requestで何をやっているかを書いています。

ちなみに

これまでマージされたPull Requestの数を数えてみたんですが、26個みたいです(以下のリンクから確認できます)

github.com

テスト修正関係

基本的には`make test-all`を複数回動かす際のテスト修正になっています。

github.com

これはdid_you_meanのテストでBook::Coverが二回目のテストで定義済みのため落ちていたのを修正しています。
当初はBook.send(:remove_const, :Cover)するだけで対応できそうかと思ったんですが、別の個所でCoverageが期待される挙動となってしまったので、Book::Spineへとリネームしています。

そのうえで既に定数として定義済みであればそれを削除するようにしています。

github.com

これは二回目以降のテスト時にAWESOMEが既に定義済みである警告を無くす対応です。
先ほど同様remove_constで削除しています。

github.com

こちらも同様に二回目以降のテストで警告が出ていたので、定義済みの定数MyBookStructremove_constで削除しています。

github.com

で、先ほどの修正で漏れていた箇所(シンボルで渡していなかったの)を修正したものです

github.com

複数回テストを回す際にdid_you_meanで使用するフォーマッタの初期化がされていなかったため意図しない挙動になっていたのを修正しています。
setupDidYouMean.formatter = DidYouMean::VerboseFormatter.newしているだけの対応ですが、原因が上手くつかめず苦労した覚えがありますね……

github.com

二回目以降のテストでwebrickserver[:DocumentRootOptions][:NondisclosureName]が初期化されていないため失敗していたのを修正しています。
具体的にはserver[:DocumentRootOptions][:NondisclosureName] = []のように初期化しています。

github.com

make test-all TESTS="--repeat-count="50""のように実行すると時々テストが落ちるという問題に対応したものです。
原因としてはReadline.special_prefixesなどの区切り文字の設定周りが初期化されていないことでテストが落ちていました。

そこでteardownにそのあたりを初期化するように修正しています。

CI修正関係

github.com

RubyではWindows用のCIとしてAppVeyorを使っているんですが、これが時々なぜか落ちるという現象がありました。
調べてみたところshallow_clone: trueと設定している場合でうまくソースコードをcloneできないということがあるとわかりました。

github.com

そこで、cloneする深さをclone_depth: 10のように設定して落ちないようにしています。
正直落ちるかどうか不安でたまらなかった覚えがあります……。

github.com

で、治ったみたいだったんですが、PR時のCIチェックが別のエラーを出してきたので直したのがこれです。
原因としてはソースコードをcloneしてくるときにGitのユーザーなどが設定されていないのでエラーになっていました。

で、とりあえず初期設定でユーザーなどを設定したんですが、あまりいい直し方ではなかった感じですね……。

ドキュメント関係

github.com

最近のRubyではRubyRuby自身(と一部のCコード)で組み込みメソッドを書くと高速化するケースがあります。
そういったケースでRuby内部のRubyソースコード上にドキュメント用のコメントが記載されてます。

github.com


それらのコメントは.documentに追記することでビルド時によしなにドキュメント生成を行ってくれます。
で、array.rbが無かったのでそれを追加しているPRですね。

github.com

これはHash#deleteのドキュメントで矢印になっていないのを修正したものですね。

github.com

これはドキュメント内のリンクがOracleのドキュメントにリダイレクトされたのでわかった修正ですね。
リダイレクト先のURLに変更しています。

github.com

これはrb_class_realの挙動についてのドキュメントでtypoしてそうと思って投げたPRですね。
実際にはドキュメントが違ってた模様(typoではなかった)

またこの一件でコードの修正とかもされてます(詳しくは下記を参照)

github.com


ruby-trunk-changes.hatenablog.com



github.com

これはアクセス先のURLがhttpsに変更されていたので修正しています。

性能向上関係

github.com

ko1さんがRubyKaigi2019で発表されていた「RubyRubyを実装して高速化する」件をPRにしたものですね。
今回はKernel#cloneでそれを行っています。

github.com

こちらはKernel#Floatのバージョンですね。

コードの修正関係

github.com

これはrb_str_clearが宣言されているが使われていないのでそれを削除しています。
多分、以前は使うこともあって残っていたんだろうなぁというコードですね。

github.com

これはstaticを付けてもよさそうな関数だったので付けた方がいいのではと投げたPRですね。

github.com

これも同様にstaticを付けてます。

github.com

hash.c内でいくつかの関数にstaticを付けています。

github.com

こちらも同様にstaticを付けています。

github.com

こちらはrb_int_ceilrb_int_floorにstaticを付けています。

github.com

int_even_prb_int_odd_pで現在では使われてなさそうな処理を削除しています。

github.com

flo_prevflo_nextの処理がほとんど同じだったのでまとめています。

バグ修正関係

github.com

Time#strftimeの引数にTimezoneを渡した時に表示される出力結果がおかしいのを修正しています。
直近で似たような修正をnobuさんがされていたのでそれを参考に修正したやつですね。

github.com

Time#to_aでも同じようにTimezoneを渡した時の出力がおかしいのを修正しています。

雑感

そこそこ色々と投げれているなぁと感慨深くなりました。

自分が投げたパッチが取り込まれてるRuby3.0がリリースされるのが楽しみですね