前人未踏の領域へ WEB・インフラ・プログラミング全般編

フロントエンド、バックエンド、インフラ、言語など、アプリ開発、IOT以外の記録

rbenvによるrubyの更新

前提条件

rbenvをインストール済みであること

コマンド

Mac Homeblew

$ brew update
$ brew upgrade ruby-build

Ubuntu

$ cd ~/.rbenv
$ git pull
$ git -C /home/ubuntu/.rbenv/plugins/ruby-build pull

確認

$ rbenv install -l
3.1.6
3.2.5
3.3.5
jruby-9.4.8.0
mruby-3.3.0
picoruby-3.0.0
truffleruby-24.0.2
truffleruby+graalvm-24.0.2

Only latest stable releases for each Ruby implementation are shown.
Use `rbenv install --list-all' to show all local versions.

インストール

$ rbenv install 3.3.5

切り替え

$ rbenv local 3.3.5
$ rbenv global 3.3.5

Git:特定のファイルを無視してgit stashする

内容

編集中のファイル群をgit stash したいがあるファイルだけ対象外にしたい

対応

除外したいファイルだけaddして、それから -keep-index オプションをつけて stashする

git add <除外したいファイル>
git stash --keep-index

ひとこと

Gemini先生に聞いて解決。これまでググったりして調べたものを備忘録的に記事にしていたけど Geminiに聞いたら教えてもらえる程度の内容を記事にする意味はもうないかもしれない。

rbenv: Ruby3.2インストールエラー

内容

rbenv でruby 3.2.2をインストールしようとしたら以下のエラーが発生した。

$ rbenv install 3.2.2
To follow progress, use 'tail -f /tmp/ruby-build.20231021091520.5507.log' or pass --verbose
Downloading ruby-3.2.2.tar.gz...
-> https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.2.tar.gz
Installing ruby-3.2.2...

BUILD FAILED (Ubuntu 18.04 using ruby-build 20230717-11-g4d4678b)

Inspect or clean up the working tree at /tmp/ruby-build.20231021091520.5507.wUPdqj
Results logged to /tmp/ruby-build.20231021091520.5507.log

Last 10 log lines:
make[1]: Leaving directory '/tmp/ruby-build.20231021091520.5507.wUPdqj/ruby-3.2.2'
Generating RDoc documentation
/tmp/ruby-build.20231021091520.5507.wUPdqj/ruby-3.2.2/lib/yaml.rb:3: warning: It seems your ruby installation is missing psych (for YAML output).
To eliminate this warning, please install libyaml and reinstall your ruby.
uh-oh! RDoc had a problem:
cannot load such file -- psych

run with --debug for full backtrace
uncommon.mk:597: recipe for target 'rdoc' failed
make: *** [rdoc] Error 1

対応

必要なライブラリをインストール

$ sudo apt install libyaml-dev libffi-dev

参考

mseeeen.msen.jp

Rails : bundle updateの前にdry-runしたい

課題

bundle updateコマンドを叩いてライブラリを更新したらエラーで動かなくなったので少しずつ進めることに。
じゃあ少しずつ進めるために、どのライブラリに新しいバージョンがあるのかを知るにはどうすればよいか。

対応

bundle outdated を使うと古くなったライブラリを一覧で表示してくれるのでこちらを利用する

$ bundle outdated
Fetching gem metadata from https://rubygems.org/.........
Resolving dependencies..............................................

Gem                       Current   Latest    Requested        Groups
administrate              0.16.0    0.19.0    >= 0             default
airbrussh                 1.4.0     1.4.2
bcrypt                    3.1.16    3.1.19    ~> 3.1.7         default
bootsnap                  1.7.3     1.16.0    >= 1.1.0         default
bugsnag                   6.19.0    6.26.0    ~> 6.12          default
capistrano                3.16.0    3.17.3    ~> 3.16          development
以下略

かなりの量が出てきた。オプションなしだと実際には bundle update では更新されないものも表示されるので--strictオプションをつけ、Gemfileの要件で許可されているライブラリだけをリストアップする。--only-explicit もつけて依存関係は省略してGemfileに記載のあるものだけにする。

$ bundle outdated --strict --only-explicit
Fetching gem metadata from https://rubygems.org/.........
Resolving dependencies...............................................

Gem                       Current   Latest    Requested  Groups
active_hash               3.1.0     3.2.0     >= 0       default
active_model_serializers  0.10.12   0.10.13   >= 0       default
activerecord-import       1.0.8     1.4.1     >= 0       default
administrate              0.16.0    0.19.0    >= 0       default
airbrussh                 1.4.0     1.4.2
bcrypt                    3.1.16    3.1.19    ~> 3.1.7   default
bootsnap                  1.7.3     1.16.0    >= 1.1.0   default
bugsnag                   6.19.0    6.26.0    ~> 6.12    default
以下略

これで目的のものが得られた。--strictとの違いがよく分からないけど --update-strict もつけているといいかもしれない。

この他にもbundle outdated --help を見ると他にも使えそうなオプションがあり、bundle updateのオプションと関連しているものもあったので色々試してみると良さそうだ。

実際にやってみる

bundle outdatedを使って段階的なアプデをしてみよう。

まず--patchを使ってpatchがあるものだけチェック

$ bundle outdated --patch  --strict 
Fetching gem metadata from https://rubygems.org/.........
Resolving dependencies....

Gem                       Current   Latest    Requested  Groups
active_hash               3.1.0     3.1.1     >= 0       default
active_model_serializers  0.10.12   0.10.13   >= 0       default
airbrussh                 1.4.0     1.4.2
bcrypt                    3.1.16    3.1.19    ~> 3.1.7   default
以下略

次に実際に bundle update--patchオプションをつけてパッチバージョンだけ上げる

$ bundle update --patch  --strict 
Fetching gem metadata from https://rubygems.org/.........
Resolving dependencies...
Using rack 2.2.8 (was 2.2.6.4)
Using nio4r 2.5.9 (was 2.5.8)
Using thor 1.2.2 (was 1.2.1)
$ bundle outdated --patch --strict 
Fetching gem metadata from https://rubygems.org/.........
Resolving dependencies...

Bundle up to date!

無事パッチだけ更新されたのでここでSPECの実行、軽い動作チェックを挟つつ、--minor --major と更新していけば問題が起きても比較的早く解決できるだろう。

参考

stackoverflow.com

Rails: "7月15日".to_date

内容

とあるエラー調査をしていたところ、入力された日付とは異なる日付で取り込まれている問題が発生していた。

入力されたデータは 7月15日 。指定した日付フォーマットとは異なる、何年かも分からない日本語書式である。 これを受け取ったコードではだいたい以下のような感じで書いてあった。

d = '7月15日'
I18n.l(d.to_date, format: :system)

入力を疑うことなくDate型に変換しようとしてるのか。そんなことできるのね。まあそれはいいとして、d.to_dateの結果をRailsコンソールで確認したところ、以下のような結果が得られた

irb(main):008:0 > '7月15日'.to_date
=> Thu, 15 Jun 2023

Jun って6月じゃね? ActiveSupportto_dateを見ると以下のようになっている。

  def to_date
    ::Date.parse(self, false) unless blank?
  end
irb(main):011:0> Date.parse('7月15日')
=> Thu, 15 Jun 2023

うむ、なるほど...。ちなみに 7月31日だとinvalid dateでエラーになる。なんなら全部エラーにしてほしかった。

感想

ググれば出てくるようなRubyRails界隈では有名な話なのだろう(← ググれよ) そもそもなんで漢字を受け付けちゃうのかな。
使ってるライブラリのバージョンが古いので最新バージョンではうまく処理してくれたりするんだろうか。

Rails: 条件付きfind

内容

特定のIDでテーブルからfind()を使ってレコード取得したいが、ついでに条件も指定したい。

対応

Whereを先に書いて、最後にfindをつける。 仮にBooksとテーブルがあり、statusactiveなものだけ対象にしたい場合は以下のようになる。

book = Books.where(status: 'active').find(params[id])

参考

api.rubyonrails.org

Stripe: API実行レシピ

RailsコンソールおよびRails内でコピペして使う用の実例サンプル集。

カスタマー

カスタマーを取得する
cus = Stripe::Customer.retrieve("cus_XxwqzgXcn1XXsk")
サブスクリプション付き
cus = Stripe::Customer.retrieve("cus_XxwqzgXcn1XXsk", {expand:'subscriptions'})

サブスクリプション

カスタマーに紐づくサブスクリプションを1件取得する
sub = Stripe::Subscription.retrieve(cus.subscriptions.data[0].id)
サブスクリプションインボイス付きで1件取得する
sub = Stripe::Subscription.retrieve({id:sub.id ,expand: ['latest_invoice']})
sub.latest_invoice でインボイスデータが取得できる
サブスクリプションインボイスとPaymentIntent付きで1件取得する
sub = Stripe::Subscription.retrieve({id:sub.id ,expand: ['latest_invoice.payment_intent']})
sub.latest_invoice.payment_intentでPaymentIndentが取得できる
カスタマーに紐づくサブスクリプション一覧を取得する
subs = Stripe::Subscription.list({customer: cus.id)
カスタマーの特定の商品に紐づく一覧を取得する
subs = Stripe::Subscription.list( { customer: cus.id, 
           price: 'price_1H860RDmZZkQvLJisnZXJvi' } )

インボイス

サブスクリプションに紐づく最新のインボイスを取得する
invoice = Stripe::Invoice.retrieve(sub.latest_invoice)

PaymentIntent

インボイスに紐づくPaymentIntentを取得する
pi = Stripe::PaymentIntent.retrieve(invoice.payment_intent)
PaymentMethodをPaymentIntentに紐づける

支払いに失敗したPaymentIntentに新しい支払い方法を紐づける場合などで使用。statusがrequires_confirmation になるので別途confirmが必要。subscription.statusincompleteだとエラー

pi = Stripe::PaymentIntent.update(pi.id, {payment_method: cus.invoice_settings.default_payment_method })
PaymentMethodをPaymentIntentに紐づつつConfirmする

支払いに失敗したPaymentIntentに新しい支払い方法でcomfirmする。subscription.statusincompleteだとエラー。

pi = Stripe::PaymentIntent.confirm(pi.id, {payment_method: cus.invoice_settings.default_payment_method })
顧客ごとの次回請求分のインボイスを取得する

次回の請求がない場合にはエラーになるので注意

Stripe::Invoice.upcoming({customer: "cus_XxwqzgXcn1XXsk" })
/* Responsive: yes */