my_back_pages

プログラミング学習の記録 Ruby / Rails / FjordBootCamp

Anacondaをアンインストールしたのに、CONDA_CHANGEPS1 という環境変数が消えない -> zshのプロンプトのテーマによって設定されていた話

まとめ

  • Rubyを勉強する前に、Pythonの学習のためにAnacondaというソフトをインストールしていた
  • Pythonの環境構築についてよくわからないままインストールしていた上に、zshの設定ファイルに関連設定が色々と書き込まれているのが気持ち悪かったので、Anacondaを削除することにした
  • 削除したのにCONDA_CHANGEPS1というAnaconda関連っぽい環境変数が消えない
  • zshのプロンプトのテーマであるpureの中で設定されていた

CONDA_CHANGEPS1でググっても同様のケースと思われる内容にヒットしなかったので、シェアしようと思います。

Anacondaのアンインストール

下のページを参考にさせていただきました。

weblabo.oscasierra.net

Anaconda関連の環境変数の確認

 ❯ env | grep CONDA                               
 CONDA_CHANGEPS1=no

シェルを再起動しても、なぜかこの環境変数が消えない。

pureの中で設定されていた

pureは私が使っているzshのプロンプトのテーマです。

github.com

このpureの設定ファイルの中に、当該の環境変数を設定している箇所がありました。

pure/pure.zsh at a02209d36c8509c0e62f44324127632999c9c0cf · sindresorhus/pure · GitHub

     # Guard against (ana)conda changing the PS1 prompt
    # (we manually insert the env when it's available).
    export CONDA_CHANGEPS1=no

コメントを読む限り、pureで設定したプロンプトをAnacondaが上書きしないようにするための処理のようです。

Anaconda自体の設定ファイルが消し忘れで残っている、とかではないようなので、Anacondaのアンインストールを完遂するという観点では、この環境変数が残っていること自体は無視してよさそうです。

Annacondaって?

Python.jpさんに、以下のような記述がありました。

もう一つは、データサイエンスをはじめとする科学技術計算のためのプラットフォームである、Ananconda を利用する方法です。AnacondaはPythonの実行環境として知られていますが、本来、データサイエンスのためのいろいろなツールやライブラリの実行環境で、Pythonにかぎらず、さまざまなコマンドやプログラミング言語も提供しています。

(中略)

Anacondaの注意点

Webプログラミングなどの、科学技術計算以外の一般的なプログラミング分野では、あまりAnacondaは使われていません。このため、一般的なPython入門書やWeb上で見かけるPythonの解説記事などの多くは公式版のPythonを対象としており、PyPIとpipコマンドを使っています。

PythonとAnaconda: Python環境構築ガイド - python.jp

Rubyを始める前に、Udemyの講座でなんとなくPythonを勉強していたときに(当時の私には難しく、基礎文法の途中でやめてしまいましたが……)、指示に従って何も考えずにインストールしたのがAnacondaでした。

今回のアンインストールのためにその講座の環境構築パートを見直してみたのですが、初心者ができる限りターミナルを叩かず、簡単にPythonの環境構築を完了できるようにするためにAnacondaを選択した、というような雰囲気でした。

実際、Pythonコードを実行するということ自体は苦もなくできていたので、その講座の指針・Anacondaには感謝です。

もし今後Pythonを勉強し直すということがあれば、Anacondaに頼らず環境構築をしてみたいなと思っています。

【Rails】rails g コマンドで --force-plural オプションを使用した際の生成物を rails destroy コマンドで削除するときは、同じオプションを指定する必要がある

タイトル通りです。

--force-pluralオプションを使用して複数形を使ったモデル名のscaffoldを行う

rails g scaffold JazzCafes name:string --force-pluralを実行。

ポイント

  • --force-pluralオプションを使ったので、モデルのファイル名が複数形のapp/models/jazz_cafes.rbになっている。
    • 指定しないと単数系のjazz_cafe.rbとなる。
 ❯ rails g scaffold JazzCafes name:string --force-plural           
       invoke  active_record
       create    db/migrate/20240419024627_create_jazz_cafes.rb
       create    app/models/jazz_cafes.rb
       invoke    test_unit
       create      test/models/jazz_cafes_test.rb
       create      test/fixtures/jazz_cafes.yml
       invoke  resource_route
        route    resources :jazz_cafes
       invoke  scaffold_controller
       create    app/controllers/jazz_cafes_controller.rb
       invoke    erb
       create      app/views/jazz_cafes
       create      app/views/jazz_cafes/index.html.erb
       create      app/views/jazz_cafes/edit.html.erb
       create      app/views/jazz_cafes/show.html.erb
       create      app/views/jazz_cafes/new.html.erb
       create      app/views/jazz_cafes/_form.html.erb
       create      app/views/jazz_cafes/_jazz_cafes.html.erb
       invoke    resource_route
       invoke    test_unit
       create      test/controllers/jazz_cafes_controller_test.rb
       create      test/system/jazz_cafes_test.rb
       invoke    helper
       create      app/helpers/jazz_cafes_helper.rb
       invoke      test_unit
       invoke    jbuilder
       create      app/views/jazz_cafes/index.json.jbuilder
       create      app/views/jazz_cafes/show.json.jbuilder
       create      app/views/jazz_cafes/_jazz_cafe.json.jbuilder

rails destroyによるジェネレーターによる生成物の削除

ジェネレーターコマンドで生成したものを削除できるのがrails destroyコマンド。

  • 生成の例
    • rails g scaffold JazzCafes
  • 削除の例
    • rails destroy scaffold JazzCafes

ActiveRecorddestroyとは別のものです、念の為)

--force-pluralオプションをつけずにrails destroyコマンドを実行する

rails destroy scaffold JazzCafesを実行。

 ❯ rails destroy scaffold JazzCafes
 [WARNING] The model name 'JazzCafes' was recognized as a plural, using the singular 'JazzCafe' instead. Override with --force-plural or setup custom inflection rules for this noun before running the generator.
       invoke  active_record
       remove    db/migrate/20240419030925_create_jazz_caves.rb
       remove    app/models/jazz_cafe.rb
       invoke    test_unit
       remove      test/models/jazz_cafe_test.rb
       remove      test/fixtures/jazz_caves.yml
       invoke  resource_route
        route    resources :jazz_caves
       invoke  scaffold_controller
       remove    app/controllers/jazz_caves_controller.rb
       invoke    erb
       remove      app/views/jazz_caves
       remove      app/views/jazz_caves/index.html.erb
       remove      app/views/jazz_caves/edit.html.erb
       remove      app/views/jazz_caves/show.html.erb
       remove      app/views/jazz_caves/new.html.erb
       remove      app/views/jazz_caves/_form.html.erb
       remove      app/views/jazz_caves/_jazz_cafe.html.erb
       invoke    resource_route
       invoke    test_unit
       remove      test/controllers/jazz_caves_controller_test.rb
       remove      test/system/jazz_caves_test.rb
       invoke    helper
       remove      app/helpers/jazz_caves_helper.rb
       invoke      test_unit
       invoke    jbuilder
       remove      app/views/jazz_caves
       remove      app/views/jazz_caves/index.json.jbuilder
       remove      app/views/jazz_caves/show.json.jbuilder
       remove      app/views/jazz_caves/_jazz_cafe.json.jbuilder

app/models/jazz_cafe.rbを消そうとしています。上で見たように、最初に私が生成したのはファイル名が複数形になっているapp/models/jazz_cafes.rbなので、目的の生成物を消すことができていません。

[WARNING] The model name 'JazzCafes' was recognized as a plural, using the singular 'JazzCafe' instead. Override with --force-plural or setup custom inflection rules for this noun before running the generator

上の警告で出ているように、複数形のJazzCafesrails destroyコマンドの対象に指定したので、Railsの通常のルールに則って単数系のJazzCafeを指定したものとして消去するパスの組み立てが行われた、ということのようです。

--force-pluralオプションをつけてrails destroyコマンドを実行する

rails destroy scaffold JazzCafes --force-pluralを実行。

 ❯ rails destroy scaffold JazzCafes --force-plural 
       invoke  active_record
       remove    db/migrate/20240419024627_create_jazz_cafes.rb
       remove    app/models/jazz_cafes.rb
       invoke    test_unit
       remove      test/models/jazz_cafes_test.rb
       remove      test/fixtures/jazz_cafes.yml
       invoke  resource_route
        route    resources :jazz_cafes
       invoke  scaffold_controller
       remove    app/controllers/jazz_cafes_controller.rb
       invoke    erb
       remove      app/views/jazz_cafes
       remove      app/views/jazz_cafes/index.html.erb
       remove      app/views/jazz_cafes/edit.html.erb
       remove      app/views/jazz_cafes/show.html.erb
       remove      app/views/jazz_cafes/new.html.erb
       remove      app/views/jazz_cafes/_form.html.erb
       remove      app/views/jazz_cafes/_jazz_cafes.html.erb
       invoke    resource_route
       invoke    test_unit
       remove      test/controllers/jazz_cafes_controller_test.rb
       remove      test/system/jazz_cafes_test.rb
       invoke    helper
       remove      app/helpers/jazz_cafes_helper.rb
       invoke      test_unit
       invoke    jbuilder
       remove      app/views/jazz_cafes
       remove      app/views/jazz_cafes/index.json.jbuilder
       remove      app/views/jazz_cafes/show.json.jbuilder
       remove      app/views/jazz_cafes/_jazz_cafe.json.jbuilder

ちゃんと複数形のapp/models/jazz_cafes.rbを消してくれています。 その他、rails g scaffold JazzCafes name:string --force-pluralの生成物をまるっと消してくれています。

生成時に--force-pluralした場合は、削除時も同じオプションが必要になる、ということですね。

なんでこんなことを調べたの?

そもそも、JazzCafeモデルを作ろうとした時に、Railsがなぜか複数形をjazz_cavesと認識して各種ファイルを生成したことから、これらのことを調べ始めることになりました。

モデル名はJazzCafeで、複数形はjazz_cafesとしたいけれど、実際に生成される複数形はjazz_cavesになってしまう。

 ❯ rails g scaffold JazzCafe name:string                
       invoke  active_record
       create    db/migrate/20240419024225_create_jazz_caves.rb
       create    app/models/jazz_cafe.rb
       invoke    test_unit
       create      test/models/jazz_cafe_test.rb
       create      test/fixtures/jazz_caves.yml
       invoke  resource_route
        route    resources :jazz_caves
       invoke  scaffold_controller
       create    app/controllers/jazz_caves_controller.rb
       invoke    erb
       create      app/views/jazz_caves
       create      app/views/jazz_caves/index.html.erb
       create      app/views/jazz_caves/edit.html.erb
       create      app/views/jazz_caves/show.html.erb
       create      app/views/jazz_caves/new.html.erb
       create      app/views/jazz_caves/_form.html.erb
       create      app/views/jazz_caves/_jazz_cafe.html.erb
       invoke    resource_route
       invoke    test_unit
       create      test/controllers/jazz_caves_controller_test.rb
       create      test/system/jazz_caves_test.rb
       invoke    helper
       create      app/helpers/jazz_caves_helper.rb
       invoke      test_unit
       invoke    jbuilder
       create      app/views/jazz_caves/index.json.jbuilder
       create      app/views/jazz_caves/show.json.jbuilder
       create      app/views/jazz_caves/_jazz_cafe.json.jbuilder

デフォルトと異なる単数・複数形ルールを自分で設定することで、この問題は解決できます。 config/initializers/inflections.rb

ActiveSupport::Inflector.inflections(:en) do |inflect|
  # cafeの複数形がcafesになるようにルールを設定
  inflect.irregular "cafe", "cafes"
end

この調査の過程の中で--force-pluralというオプションを知り、いろいろ試す中で気づいたことが本記事の内容でした。

scrapbox.io

以上、備忘録まで。

楽天KoboのPCアプリで電子版の技術書を読むのがちょっとだけ不便に感じた話

なぜ?

リーダーアプリで、本文のクリップボードへのコピーができないからです。

本文を選択して右クリックした際のメニュー

一応、「検索 -> Google」をクリックすれば、ブラウザが開いてGoogle検索結果に遷移してくれるので、それをコピーすることでやりたいことはできます。

技術書をテーマにされてはいませんでしたが、同じことを解説してくださっている記事もありました。 note100yen.com

どう不便?

技術書の場合、サンプルコードをエディタにコピー&ペーストできることが電子版の大きなメリットになってくると思うのですが、ここでブラウザを経由するという手間を踏まないといけなくなることですね。

また、コピペに頼らず写経して学習する場合でも、手元で学習メモをつける際にコード以外の文章の一部をコピペすることもあると思います。

学習のために、Koboで読む読まないに限らずコードはできるだけ手打ちで写経するように心がけていますが、文章の一部をメモのためにコピペしたくなることはやはりあります。

なぜ楽天で電子版の技術書を買ったの?

ポイント還元でお得に購入できたからでした……😅

電子書籍を買う場合、基本的にはKindleで探すことが多いのですが、技術書はそこそこお値段が張るものもあるので、ポイント還元やクーポン次第で他のサービスに浮気することがあります。

(上記の理由で、たとえば私は『Webを支える技術』電子版を「ブックライブ」で持っています)

そもそも本は電子版ではなく物理派なのですが、技術書の電子版を買う場合はリーダーアプリの使いやすさも地味に考慮すべきポイントになってくるのかなと感じた次第です。

※あくまで「技術書をKoboで読む際に気になったこと」というシェアで、Kobo楽天のサービスそのものを批判する意図はありません。楽天経済圏にはいつもお世話になっています……🙏 またコピペ機能がないのは書籍全体のコピー対策を考慮してのことかもと思いますし、このあたりは難しい問題なのかな……とも感じております。

以上、電子版の技術書に関連した小さなシェアでした。

Macのターミナルでコマンドを右クリックするとman情報を見ることができる

タイトル通りです。

手順

manを参照したいコマンドをMac純正ターミナルに打ち込んで、そのコマンド上で右クリック。

「manページを開く」をクリック。

別ウィンドウでmanが参照できる!

何気なくターミナル上で右クリックをしたときに気づきまして、これまで全く知りませんでした。

ググってみたら、下のページではローカルのドキュメントにコピペしておくことでいつでも参照できるようにする、という活用法が紹介されていました。たしかに便利!

ottan.jp

以上、小ネタ記事でした。

【Rails初心者】createアクションでモデルオブジェクトの保存失敗時に、入力情報を保持したままフォームを表示することができる理由

/cats/newのフォームへの入力内容になんらかのバリデーションエラーなどがあり、@cat.saveに失敗すると、(scaffold状態のRailsアプリなら)入力内容が保持された状態でフォームが表示されます。

よくよく考えると「どんなすごい仕組みで入力内容が保持されているのだろう?」となったのですが。

# app/controllers/cats_controller.rb

   def create
     @cat = Cat.new(cat_params)
 
     if @cat.save
       redirect_to @cat, notice: "Cat was successfully created."
     else
       render :new, status: :unprocessable_entity
     end
   end

@cat = Cat.new(cat_params)インスタンス変数にセットされたCatのオブジェクト(誤った入力内容が各属性にセットされている)が、render :newで呼び出されるnewテンプレートに渡されるから、というとてつもなく基本的なことを意識できていなかったのでした。

そもそも、バリデーションエラーのメッセージを「インスタンス変数に入ったオブジェクトから取り出して表示する」という仕組みがまさにこれでしたね……。

  • newアクションで@cat = Cat.newnewテンプレートに渡す
  • showアクションで@cat = Cat.find(params[:id])showテンプレートに渡す

これらのことと全く同じ、というわけですね。

すごく基本的なことを意識できていなかったんだなという反省記事です。

【RubyMine】Code Vision機能をオフにしたら動作が軽くなった話

シェアしたいことのサマリ

  • MacBook Air (M1, 2020) 8GBでRubyMineを使っているのですが、特にJS関連ファイルで動作が重くなるときがある。
  • 「Code Vision」機能をオフにすると大分軽くなる。

※メモリの割り当て増はすでに行った上での処置です。

詳細

フィヨルドブートキャンプの「チーム開発」というプラクティスで、下のリポジトリのアプリの開発に参加しています。 Rails + Vue / React によるEラーニングアプリです。

github.com

昨年末にRubyMineのライセンスを購入しメインのエディタとして使っていて、大変助けられているのですが、VueやReactのようなJS関連のファイルを開いたときにかなりモッサリすることにストレスを感じていました。

「RubyMine 重い」で検索して最初に出てくる対処法は「メモリの割り当てを増やす」で、こちらはすでに実行済みなのですが効果が薄く……。

pleiades.io

だましだまし使っていたのですが、あるとき画面右下にポップアップで「Code Visionの解析に時間がかかっています(意訳)」と表示されていることに気づきました。

Code Visionってなに?

RubyMineのドキュメントにはなぜか説明チャプターがないので、他のJetBrains製エディタの説明を見てみると、ありました、Code Vision

pleiades.io

コードビジョンは、型および型メンバーのさまざまなメトリックを収集し、その情報を宣言の上または後に表示します

(中略)

コードビジョンは、次の 2 つのサブシステムを使用して、事前に計算されたメトリックを保持します。

ナビゲーションメトリック(シンボル、継承、戻り API などの使用箇所)を計算するためのソリューション全体の分析。

(中略)

コードコントリビューターを表示する統合された VCS クライアント。このメトリックは、現在のソリューションでバージョン管理統合が有効になっている場合に、サポートされているすべての VCS クライアント(Git、MercurialSubversion、TFVC など)に表示されます(バージョン管理設定ページで確認できます)。

リンク先のキャプチャ画像で確認できるように、メソッドが使用されている回数や、バージョン管理システムに記録された実装者などの情報を表示してくれる機能のことだったみたいです。たしかに自分の画面にも出ていた!

RubyMineでどうやってオフにする?

設定 -> エディター -> インレイヒント からオフにできます。

JSのファイルでもそこそこ軽く動いてくれるようになりました。

オフにしたデメリットについて

コードの実装者については、Gitの拡張プラグインのおかげでgit blameがいつでも見られるようになっているので、現時点ではあまり困っていません。

コードの使用回数は、見られるようになっている方がもちろん便利だとは思うのですが、コードジャンプや「どこでも検索」機能が便利なので、実際にはこれらで補うことができているのかな、という感覚です。

(初心者が故に、たくさんのファイルにまたがる重いIssueを振られていないから、というのはあるかもしれませんが……)

とはいえオンにしたい

いい機能であることは間違いなく、できればオンにしたいのですが、そもそもにマシンパワー的にRubyMineはきついということですかね。

Issueに取り組む時は、他のアプリを閉じたり、極力Chromeでタブをたくさん開いたりしないようにしていますが、それでもJSのファイルは重いので。サブディスプレイに繋がなければ軽くできる、とかもありそうですが、そういうわけにもいかないので……。

M3チップのMacbook Airが出るらしいので、その16GBとかが欲しい。

一応、メモリ割り当て以外に、一部の機能を犠牲にして軽くすることもできますよ、的なシェアとして、本記事をポストさせていただければと思います。

【SWR】isLoading が使えるのは SWR 2.0 から【React】

サマリ

  • useSWRの返り値としてのisLoadingが使えるのは SWR 2.0 から

isLoading は useSWR から返される新しい状態で、リクエストが実行中で、ロードされたデータがない ことを示します。これまでは、isValidating は初期ローディングと再検証の状態のどちらも表していたため、初期ローディングかどうかを知るためには data と error が undefined であるかどうかをチェックする必要がありました。

swr.vercel.app

// SWRのバージョン2.0以降であれば、isLoadingを取り出せる
// バージョン1.Xの場合、useSWRの返り値はisLoadingプロパティを持たないため、
// 下の変数isLoadingには「ただのundefined」が入ってしまい、状態の管理には使えない

const { data, isLoading } = useSWR('/api/user', fetcher)

表題の通りですが、本記事はこのことの備忘録です。

なんでわざわざこんなことを記事に?

本記事の執筆時点で、フィヨルドブートキャンプ(以下FBC)のプラクティス「チーム開発」において、下のIssueに取り組んでいます。

github.com

アプリ右上の通知ベル(日報でのメンションなどの各種通知を確認するためのボタン)に、新機能を追加するというIssueです。

既存のベルはVueで実装されており、Reactにリプレイスすることも兼ねているIssueで、これにあたりAPIのコールとフェッチ状態・キャッシュデータの管理にuseSWRを使おう!という流れ。

FBCではReactのカリキュラムの中に「SWRを使ってAPIをコールする」というプラクティスがあります。 ここで生徒はuseSWRのドキュメントを読み、練習課題を解くことで基本的な使い方を学びます。

swr.vercel.app

練習課題はSWRを自分でnpm installしたので、最新版のv2.X系を自然と使うことになり、ドキュメントも上記の最新のものを参照していました。

なのでこのIssueでもプラクティスで学んだ通り、初期ローディング中の状態管理にフックの返り値isLoadingを使ってみようとすると、なにやらうまくいかない。

console.log(isLoading)でプリントデバッグを試すと、ロード中の状態と思われるタイミングでもisLoadingの中身はundefinedだったため、これは何かがおかしいと思い調査したところ、アプリで使われているSWRのバージョンが1.3だった、というのが根本原因でした。

// package.json

// ...
    "sweetalert2": "^11.1.5",
    "swr": "^1.3.0",
    "tailwindcss": "^3.1.8",
// ...

https://github.com/fjordllc/bootcamp/blob/main/package.json#L50

よくよく調べてみると、記事冒頭で引用したようにisLoading2.0でリリースされた返り値ということ。

QiitaなどでSWRの記事を見ているときに、「なんでこの記事ではisLoadingを使用せずに!dataでローディング状態を管理しているのだろう」と思ったことがあるんですが、執筆タイミングでのバージョンの違いだった可能性があるということですね。

学び

  • プロジェクトで使われているライブラリのバージョンをしっかりと確認する
  • 特にネットの記事を読んでインプットする際は、バージョンの差異による挙動のズレが起こる可能性があることを強く意識する

あたりまえのことですね……。改めて、気をつけたいと思います。