Libraries

Latest comments

rails 7.1からrails 7.2への移行(アップデート、アップグレード)で必要な作業

wakairo @wakairo
Last edited

rails 7.2におけるannotate_rendered_view_with_filenames

annotate_rendered_view_with_filenamesは、rails 6.1で追加されたビューのテンプレートの開始と終了に対応するHTMLコメントを挿入する機能です。

rails newで生成されるconfig/environments/development.rbにおいて、 7.1以前はこの機能を有効化する以下のコードがコメントアウトされていましたが、 7.2からは以下のように有効になるコードになりました(この変更のPR)。 ちなみに、default値は7.1以前から変わらずfalseですので、 development.rb内の当該設定を意図的に変更しなければ、既存アプリの挙動が勝手に変わることはありません。

  config.action_view.annotate_rendered_view_with_filenames = true

確かにdevelopment環境において便利そうな機能ですので、7.2へのアップデートを機に、使い始めてみるのも良いかもしれません。

0
Raw
https://www.techtips.page/en/comments/321

rails 7.1からrails 7.2への移行(アップデート、アップグレード)で必要な作業

wakairo @wakairo
Last edited

基本的にはRailsガイドの手順に従えば良いと思います。

ガイドの手順にもありますが、ぜひbin/rails app:updateコマンドを活用しましょう。

rails 7.2への移行で対応が必要そうな個別の作業について、以下のコメントでそれぞれ取り上げますので、ご参考になれば幸いです。

0
Raw
https://www.techtips.page/en/comments/320

railsが挿入するfield_with_errorsの要素がBootstrapのinput-groupの表示を乱す問題

wakairo @wakairo
Last edited

問題の内容

フォームヘルパーで作成したフォームの標準の挙動として、 railsは、バリデーション・エラーが起きたフォーム要素を、field_with_errorsクラスを指定したdiv要素で囲みます。 つまり、バリデーション・エラーの有無によって、HTMLの階層構造が変わってしまいます。

その一方で、BootstrapのInput groupは、input-groupクラスを指定した要素の直接の子要素としてフォーム要素があることを前提としています。 そのためバリデーション・エラー時に、input-groupを指定した要素とフォーム要素の間にfield_with_errorsクラスのdiv要素が割り込むことで、Input groupの表示を乱してしまいます。

この問題に対し、インターネット上の情報では、 display: contents;を利用する方法や config.action_view.field_error_procの設定を変更する方法が紹介されていましたが、 私が試した限りでは問題の解決に至りませんでした。

そこで以下では、Input groupの利用を諦めて、Input groupに似た表示を他のBootstrapの機能で実現する方法をご紹介します。

なお、この問題に関して別の何か良い方法をご存じの方がいらっしゃいましたら、コメントをいただけると嬉しいです。

Bootstrapにおいて、Input groupに似た表示をgridで作成する方法

例として、Input groupを利用した以下のフォームの一部分を考えます。

<div class="input-group">
  <span class="input-group-text">@</span>
  <%= f.text_field :username, class: 'form-control' %>
</div>

このフォームの一部分に近い表示を実現する例が以下のコードです。Input groupを利用した表示と比べると、「@」を囲む枠線は無くなりますが、文字やフォームの位置関係は近いものを実現できます。なお、ブラウザの画面幅をいろいろと変えた場合でも、位置関係の近さは大丈夫なはずです。

<div class="row gx-1">
  <div class="col-auto col-form-label">@</div>
  <div class="col">
    <%= f.text_field :username, class: 'form-control' %>
  </div>
</div>

このコードで利用しているBootstrapのクラスについて少し解説します。

まず横幅のバランスに関しては、以下のクラスを利用しています。

  • col-auto:内容の幅、つまり、上述のコードではフォームの左にある文字列である「@」の幅に基づいたカラムの幅になります。
  • col:残っている幅を均等に割り付けた幅になります。例えばcolクラスのカラムが2つあれば残りの幅が2分割されて均等に割り付けられます。上述のコードではcolクラスのカラムは1つですので、左にある「@」のカラムの幅を除いた残りの幅が全てこのtext_fieldのカラムに割り付けられます。

次に文字の位置(この例では「@」の位置)は、以下のクラスで調整しています

  • col-form-label:指定することでフォームと上下位置をそろえられます。
  • gx-*:ガターを調整することで「@」とフォームの間の距離を調整し左右位置を調整しています。なお、左右位置を細かく調整したい場合にはmarginで直接細かく指定しても良いかもしれません。

(参考)Input groupに似せることよりもgridのカラム幅の指定を優先する場合

グリッドにおいて要素間の左右位置をそろえたいとき等では、col-autoを使わずに、以下のコードのようにカラム幅を指定する方法もあります。 このような場合では、文字列の左右位置の調整にtext-endクラスやtext-centerクラスが役立つかもしれません。

<div class="row gx-1">
  <div class="col-2 col-form-label text-end">@</div>
  <div class="col-10">
    <%= f.text_field :username, class: 'form-control' %>
  </div>
</div>

コードの動作確認をしたgemのバージョン

  • rails (7.1.3.4)
  • bootstrap (5.3.3)
0
Raw
https://www.techtips.page/en/comments/314

Railsで複数のセッションを用いたintegration testを行う方法

wakairo @wakairo
Last edited

別々のブラウザから複数のユーザがログインするような状況を再現したintegration testを実装しようとするときなど、 ユーザごとにセッションが必要になるなどして、 1つのテスト内で複数のセッションが必要になることがあります。

Ruby on Railsのintegration testでは、 標準でこのような複数のセッションを用いるテストに対応しており、 公式ドキュメントの中では、ActionDispatch::IntegrationTestのAPIドキュメントに説明があります。

複数のセッションを用いたintegration testの例

公式情報は上述のAPIドキュメントをご覧いただければと思いますが、一応こちらでも簡単な例を使ってintegration testで複数のセッションを用いる方法をご紹介します。

ここではテスト内容として、ログインしているユーザが列挙されるページをテストすることを想定してテストコードを考えます。 具体的には、ユーザ1がログインするとこのページにユーザ1が現れ、 続けてユーザ2がログインすると今度はユーザ1とユーザ2の両方がページに現れることを確認します。

シンプルにopen_session()でセッションを作って用いる場合の例

複数のセッションを用いる場合に鍵となるメソッドは、open_session()です。 このメソッドはセッションのオブジェクト返しますので、必要なセッションの回数分呼び出せば、必要な数のセッションが作成出来ます。 セッションを複数作成したら、各セッションのオブジェクトのインスタンスメソッドとしてget()やassert_response()を呼び出すことで、 セッションを指定してアクションやアサーションを実行できます。

以下にサンプルコードを示します。

require "test_helper"

class MultipleSessionTest < ActionDispatch::IntegrationTest

  test "login users page" do
    user1 = users(:one)
    user2 = users(:two)

    sess1 = open_session
    sess2 = open_session

    sess1.get login_path
    sess1.assert_response :success
    sess1.post login_path,
               params: { {email: user1.email,
                          password: user1.password} }
    sess1.assert_response :found
    sess1.assert_redirected_to root_path
    sess1.follow_redirect!

    sess1.get login_users_path
    sess1.assert_response :success
    assert_match /@#{user1.username}/, sess1.response.body
    assert_no_match /@#{user2.username}/, sess1.response.body

    sess2.get login_path
    sess2.assert_response :success
    sess2.post login_path,
               params: { {email: user2.email,
                          password: user2.password} }
    sess2.assert_response :found
    sess2.assert_redirected_to root_path
    sess2.follow_redirect!

    sess1.get login_users_path
    sess1.assert_response :success
    assert_match /@#{user1.username}/, sess1.response.body
    assert_match /@#{user2.username}/, sess1.response.body
  end
end

繰り返される処理をDSLのメソッドにまとめる例

上述のシンプルな例を見てみると、ログイン処理などで、対象とするセッションは異なるものの、ほぼ同じ処理が繰り返されていることが分かります。 こういった繰り返される処理は、特定のテストで用いるセッションのDSL (Domain-Specific Language) としてまとめることが出来ます。

以下のテストコードは、テストの手順や内容は上述のシンプルな例と同じですが、今度はこのDSLを用いてコードの繰り返しを排除したものになっています。なお、テストコードの読みやすさの観点でも、こちらの例の方が良くなっているのではないでしょうか。

require "test_helper"

class MultipleSessionWithDSLTest < ActionDispatch::IntegrationTest

  test "login users page" do
    user1 = users(:one)
    user2 = users(:two)

    sess1 = open_session_with_dsl
    sess2 = open_session_with_dsl

    sess1.login(user1)

    sess1.get_login_users
    assert_match /@#{user1.username}/, sess1.response.body
    assert_no_match /@#{user2.username}/, sess1.response.body

    sess2.login(user2)

    sess1.get_login_users
    assert_match /@#{user1.username}/, sess1.response.body
    assert_match /@#{user2.username}/, sess1.response.body
  end

  private

    module CustomDsl

      def login(user)
        get login_path
        assert_response :success
        post login_path,
               params: { {email: user.email,
                          password: user.password} }
        assert_response :found
        assert_redirected_to root_path
        follow_redirect!
      end

      def get_login_users
        get login_users_path
        assert_response :success
      end
    end

    def open_session_with_dsl
      open_session do |sess|
        sess.extend(CustomDsl)
      end
    end
end
0
Raw
https://www.techtips.page/en/comments/313
❤️1

Ruby on Railsのサポート終了日(各バージョンのEOL)

wakairo @wakairo

railsの各バージョンについて、セキュリティアップデートが行われる期限(End-of-Life)は以下の通りです。

  • 7.2.x - Supported until August 9, 2026
  • 7.1.x - Supported until October 1, 2025
  • 7.0.x - Supported until April 1, 2025
  • 6.1.x - Supported until October 1, 2024

なお、railsのサポート期間に関するより詳細な情報については本家のメンテナンス・ポリシーを参照してください。

0
Raw
https://www.techtips.page/en/comments/309
😄1
🔧1
❤️1

meta-tags側のtruncateでは、スペース文字のところで切り詰めが行われます

wakairo @wakairo
Last edited

meta-tagsのv2.21.0で'truncate_on_natural_separator'の設定が追加されました。この設定を利用することで、スペース文字のところでの切り詰めを回避できるようになりました。このことを上のコメントに反映しました。

0
Raw
https://www.techtips.page/en/comments/306
😄1
🔄1
🔧1

activerecordでは、firstを使った方が実装とSQLが揃って可読性が上がる

takuma_tech Takuma @takuma_tech

こちらの記事によると、activerecordでlastを使った場合、指定したorderを逆にして"LIMIT 1"とするSQLが発行されるそうです。

一方で、firstを使った場合、指定したorderはそのままで"LIMIT 1"とするSQLとなるので、railsのコードとSQLの対応関係が分かりやすくなります。

したがって、lastよりもfirstを使った方が実装とSQLが揃って可読性が上がるということがこの記事で主張されていました。 ご参考まで。

0
Raw
https://www.techtips.page/en/comments/304
🔧1
💡1
❤️1

commonmarker v1.xは、出力の編集が必要ならまだ時期尚早?

wakairo @wakairo
Last edited

2023/12/25にcommonmarker v1.0.0がリリースされました。 それから4ヶ月以上が経過していますが、v1.xを採用せずにv0.xに留まっているライブラリやプロジェクトが多いように見受けられます。

たとえば、 jekyll-commonmarkのgem指定commonmarker-rougeのgem指定は、 2024/05/13現在ではv0.xになっています。

v0.xで出来ていた編集操作がv1.xではまだ出来ない?

commonmarkerにMarkdownを入力して、出力されたHTMLをそのまま使う分には現在のv1.xで十分でしょう。 しかし、スタイル変更やJavaScriptによる機能付与などで、出力されるHTMLを多少変更したいことがあります。 v0.xではこういうときに使えるものとして、任意のHTMLを挿入する方法があったのですが、少なくともこのv0.xの方法はv1.xでは出来なくなったようです。

Pluginの活用か何かで、v1.xでもv0.xと同じように、出力のHTMLを部分的に好き勝手な形に編集することは出来るのでしょうか? ご存じの方がいらっしゃいましたら、コメントをいただけると嬉しいです。

0
Raw
https://www.techtips.page/en/comments/293
😿1

WSL2上にてrails serverで立ち上げたサーバに別デバイスからのアクセスを可能にする方法

wakairo @wakairo
Last edited

別デバイスからhttpsでrails serverにアクセスする方法

前述の方法で別デバイスからhttpでアクセスできるようになりますが、httpsでアクセスする必要がある場合には、 local-ssl-proxyを使ってhttpsをhttpに振り向けることで、httpsアクセスが可能になります。具体的な方法は以下をご覧ください。 なお別デバイスからhttpsでアクセスするには、前述のポートフォワーディングとファイアウォールの設定をhttpsのポート番号で行う必要があります。

0
Raw
https://www.techtips.page/en/comments/292
🔧1
💡1

local-ssl-proxyを使ってhttpsでhttp://localhost:3000/へアクセスする方法

wakairo @wakairo
Last edited

背景

Webの機能には、httpsでアクセスしているときにしか利用できないものがあります。 例えば、navigator.clipboardを用いてクリップボードへ書き込む機能はhttpsでアクセスしているときにのみ利用可能です。 ローカル環境においてhttpで走っている開発中のアプリに対して、こういった機能をテストするために、httpsでアクセスしたい場合があります。

ローカルでhttpsアクセスをhttpアクセスへ振り向ける方法

以下のコマンドを実行すれば、httpで走っている( http://localhost:3000/ )アプリに、ブラウザからhttps( https://localhost:3001/ )からアクセスできるようになります。

npx local-ssl-proxy --source 3001 --target 3000

なお、アプリが走っているPCとは別のデバイスからアクセスする場合には、httpのポートのために行ったポートフォワーディングやファイアウォールの設定がhttpsのポートにも必要となります。

余談その1

Copilot先生によれば、httpで走っているアプリにhttps相当でアクセスするための別の方法としては、以下のものがあるそうです。

  • localtunnelなど、ローカルで走っているアプリをインターネットに公開するサービスを利用してしまう。
  • Chrome DevToolsのリモートデバッグ機能を利用する。

なお、Copilot先生の回答全文はこちらです。

余談その2

local-ssl-proxyは、Copilot先生に教えてもらいました。Google検索ではlocal-ssl-proxyにはたどり着いていませんでした。

0
Raw
https://www.techtips.page/en/comments/291
😄1
🔧1
❤️1