Ruby

新しいItemの作成

Items

最新コメント

既存のRailsアプリへのDev Containerの導入

wakairo @wakairo

Rails 7.2においてDev Container設定を生成する機能が追加されました。 例えば既存アプリでは、以下のコマンドで既存アプリ用のDev Container設定を生成できるようになりました。

rails devcontainer

生成した設定は、Visual Studio Codeで利用でき、Dev Containerを利用した既存アプリの開発が可能となります。 必要となるソフトウェアのインストール等、Dev Containerでの開発を開始するための手順についてはDev Containerでの開発ガイドが参考になります。

なお、Visual Studio Code以外のエディタでもDev Containerで開発できるようにするべくDev Container CLIというツールの開発が進んでいますが、2024年12月現在では、ポートフォワーディングに対応していないなど、今のところはまだまだ開発途中のツールであり、実開発に投入するにはまだ早い段階である印象です。

0
Raw
https://www.techtips.page/ja/comments/646

既存のRailsアプリへのRuboCopの導入

wakairo @wakairo
最終更新

Rails 7.2からRuboCopが新規アプリケーションでデフォルトで有効になりました。 このTopicでは、7.1以前で作成した既存RailsアプリにRuboCopを後から導入して、RuboCopに関して7.2の新規アプリ相当の状態にセットアップする方法をご紹介します。

RuboCop (Omakase Ruby styling for Rails) のインストール

基本的にはrubocop-rails-omakaseの公式ドキュメントのインストール手順に従います。

まず以下のように、Gemfileのgroup :development, :testのところにrubocop-rails-omakaseを追加します。

group :development, :test do

  # Omakase Ruby styling [https://github.com/rails/rubocop-rails-omakase/]
  gem "rubocop-rails-omakase", require: false

end

次にbundle installを実行して、RuboCop等をインストールします。

bundle install

さらに、必須ではありませんが、bin/rubocopでRuboCopを実行できるように、以下のコマンドを実行します。

bundle binstubs rubocop

最後に.rubocop.ymlという名前でファイルを作成し、以下の内容を記述します。

# Omakase Ruby styling for Rails
inherit_gem:
  rubocop-rails-omakase: rubocop.yml

以上でRuboCop (Omakase Ruby styling for Rails) のセットアップが出来ました。

ローカル環境でのbin/rubocopの実行とその結果に対する対応の進め方

以下のコマンドでbin/rubocopを実行でき、omakaseのチェックを行えます。

bin/rubocop

このチェックでの指摘事項が多かった場合、以下のオプションを付けて実行することで、 無視設定を記述した.rubocop_todo.ymlというファイルが作成され、 .rubocop.ymlにもこの無視ファイルを参照する設定が追加されますので、 とりあえず全ての指摘事項を無視するように設定が出来ます。

bin/rubocop --auto-gen-config

設定が出来たら、bin/rubocopを実行して、とりあえず指摘事項の数が0となることを確認します。

1つずつ指摘事項へ対応

ここから先は、以下の手順を繰り返します。

1項目ずつ対応を進め、.rubocop_todo.ymlの中身が無くなったら、.rubocop_todo.ymlを削除すると共に、.rubocop.yml内で.rubocop_todo.ymlを参照している設定を削除します。ここまで終わればRuboCopの諸規則への対応は完了となります。お疲れ様でした。

GitHubワークフロー(CI)でのrubocopの実行

.github/workflows/ci.ymlに相当するファイルがなければ作成します。 この.ymlファイルを編集して、以下のようにjobsの下にlintジョブを追加します。

注意点
jobs:
  lint:
    runs-on: ubuntu-latest
    timeout-minutes: 10

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: .ruby-version
          bundler-cache: true

      - name: Lint code for consistent style
        run: bin/rubocop -f github

公式情報

0
Raw
https://www.techtips.page/ja/comments/545
😄2
🔧1
💯1
❤️1

既存のRailsアプリでのDependabotへの対応

wakairo @wakairo
最終更新

Rails 7.2から新規アプリケーションにおいてDependabotがデフォルトで有効になりました。 具体的には、rails newで生成される新規アプリにおいて、Dependabotの設定ファイルである.github/dependabot.ymlが生成されるようになりました。

Dependabotとは

Dependabotとは、GitHubのサービスであり、リポジトリで使用しているソフトウェアを最新の状態に保つことをサポートしてくれるサービスです。 具体的なDependabotの機能としては、以下の3つがあります

  • Dependabot alerts — リポジトリで使っている依存関係に内在する脆弱性について通知します。
  • Dependabot security updates — 使っている依存関係のうち、既知のセキュリティ脆弱性があるものを更新するための pull request を自動的に生成します。
  • Dependabot version updates — 依存関係を最新に保つための pull request を自動的に発行します。

Dependabotの詳細な理解にはクイックスタート ガイドなどをご利用ください。

既存のRailsアプリでのDependabotへの対応方法

脆弱性の通知機能(Dependabot alerts)は、GitHubのWebページから設定を変更するだけで利用できます

脆弱性に関するpull requestの自動生成機能(Dependabot security updates)も、GitHubのWebページから設定を変更するだけで利用できますが、詳細な設定が必要な場合はdependabot.ymlを通して行います

脆弱性対応以外も含めて最新の状態にするためのpull requestを自動生成する機能(Dependabot version updates)は、dependabot.ymlを通した設定が必要です

(参考)デフォルトのdependabot.ymlの内容

このリンク先で閲覧できるrails newで生成される新規アプリのdependabot.ymlの設定内容は、既存アプリでも参考になるかもしれません。 このdependabot.ymlには、Rails 7.2の時点では、railsアプリで利用しているgemとGitHub Actions(GitHubのCI)で利用しているアクションを最新に保つための設定が記述されています。

0
Raw
https://www.techtips.page/ja/comments/447
😄3
🔄1
🔧1
💡1
💯1

BootstrapとTurbo Driveを組み合わせたときの問題と対処法

wakairo @wakairo
最終更新

問題

HotwireのTurbo Driveでは高速化を図るために、ページ遷移時に全体をリロードせずに<body>タグ内のコンテンツを置き換える動作が基本となっています。 そのためか、Turbo Driveを有効にしていると、JavaScriptの動作が必要なBootstrapのコンポーネントが適切に動作しない場合があります。

例えば、タブのコンポーネントにおいて、ページ遷移の直後はカーソルキーでのタブの切り替えが動作しません。

対策

HotwireのStimulusを利用して、必要なBootstrapオブジェクトをページ遷移時に作成します。

対策の具体例

タブ・コンポーネントの場合、まず以下のようにタブの各要素を対象にしてgetOrCreateInstance()をconnect内で呼び出すStimulusコントローラapp/javascript/controllers/foo_controller.jsを作成します。

import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  connect() {
    const triggerTabList =
          this.element.querySelectorAll(".nav-link");
    triggerTabList.forEach(triggerEl => {
      bootstrap.Tab.getOrCreateInstance(triggerEl);
    });
  }
}

次に以下のように、このStimulusコントローラfooを指定したhtmlタグでタブコンポーネントを囲みます。

<div data-controller="foo">
  <ul class="nav nav-tabs" id="myTab" role="tablist">
    <li class="nav-item" role="presentation">
      <button class="nav-link active" id="home-tab" data-bs-toggle="tab" data-bs-target="#home-tab-pane" type="button" role="tab" aria-controls="home-tab-pane" aria-selected="true">Home</button>
    </li>
    <li class="nav-item" role="presentation">
      <button class="nav-link" id="profile-tab" data-bs-toggle="tab" data-bs-target="#profile-tab-pane" type="button" role="tab" aria-controls="profile-tab-pane" aria-selected="false">Profile</button>
    </li>
  </ul>
  <div class="tab-content" id="myTabContent">
    <div class="tab-pane fade show active" id="home-tab-pane" role="tabpanel" aria-labelledby="home-tab" tabindex="0">...</div>
    <div class="tab-pane fade" id="profile-tab-pane" role="tabpanel" aria-labelledby="profile-tab" tabindex="0">...</div>
  </div>
</div>

以上で、Turbo Driveによるページ遷移時に、このタブ・コンポーネントを含むHTMLがロードされるとconnect()が呼び出され、 タブ用のBootstrapオブジェクトが存在していなかった場合には作成されるようになり、 その結果タブ・コンポーネントが正しく動作するようになります。

0
Raw
https://www.techtips.page/ja/comments/446
🔧5
😄1
🔄1
💡1
😿1

Brakemanの--safe-methodsオプションはXSSチェック専用

wakairo @wakairo

役立つ情報ありがとうございます。

リンク先のGitHubのディスカッションを覗いてみたのですが、「poor naming」という表現があり、--safe-methodsというオプション名が紛らわしいということは認識されているみたいですね。
それから、"use the ignore file instead"というポリシーだそうですので、XSSチェック以外のタイプの警告は、1つずつ無視の設定をして欲しいというのがBrakemanの開発側の考えのようですね。

0
Raw
https://www.techtips.page/ja/comments/419
🙋1
❤️1

既存のRailsアプリへのBrakemanの導入

wakairo @wakairo
最終更新

Rails 7.2から新規アプリケーションにおいてBrakemanがデフォルトで有効になりました。 このTopicでは、7.1以前で作成した既存RailsアプリにBrakemanを後から導入して、Brakemanに関して7.2の新規アプリ相当の状態にセットアップする方法をご紹介します。

Brakemanのインストール

まず以下のように、Gemfileのgroup :development, :testのところにbrakemanを追加します。

group :development, :test do

  # Static analysis for security vulnerabilities [https://brakemanscanner.org/]
  gem "brakeman", require: false

end

次にbundle installを実行します。

bundle install

以上でBrakemanのインストールが出来ました。

さらに、必須ではありませんが、bin/brakemanでBrakemanを実行できるように、以下のコマンドを実行します。

bundle binstubs brakeman

ローカル環境でのBrakemanの実行

以下のコマンドでBrakemanを実行でき、デフォルトのチェックを行えます。

bin/brakeman

全てのチェックを実行する場合には、以下のオプション付けて実行します。

bin/brakeman -A

警告の無視に関する設定と管理を行う場合は、以下のオプション付けて実行します。

bin/brakeman -I

以下のように、これら2つのオプションを同時に指定して実行することも出来ます。

bin/brakeman -IA

なお、Brakemanの詳細については公式ドキュメントをご覧ください。 また、brakemanコマンドのオプションについては日本語訳もあります。

GitHubワークフロー(CI)でのBrakemanの実行

.github/workflows/ci.ymlに相当するファイルがなければ作成します。 この.ymlファイルを編集して、以下のようにjobsの下にscan_rubyジョブを追加します。

ymlファイルの設定に関する注意点
  • timeout-minutes:の設定は、実行時間に対して十分余裕を持たせて下さい。
  • ruby-version: .ruby-version」という設定は、プロジェクトルートにある.ruby-versionという名前のファイルで指定されているrubyのバージョンという意味になります。この設定についての詳細はこちらのTopicをご覧下さい。
jobs:
  scan_ruby:
    runs-on: ubuntu-latest
    timeout-minutes: 10

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: .ruby-version
          bundler-cache: true

      - name: Scan for common Rails security vulnerabilities using static analysis
        run: bin/brakeman --no-pager
0
Raw
https://www.techtips.page/ja/comments/418
🔧3
😄2
💡1
💯1
❤️1

Brakemanの--safe-methodsオプションはXSSチェック専用

takuma_tech Takuma @takuma_tech
最終更新

こちらの公式ドキュメントを読むと、--safe-methodsオプションでメソッド名を指定することで様々なタイプの警告を抑制できるように思えるのですが、このオプションで抑制できるのはXSS (cross-site scripting)チェックのみです。

オプションのマニュアルには「特定のメソッドが適切にエスケープされた値を出力し、そのメソッドがXSSチェックで警告されないようにするためには、次の(--safe-methods)オプションを使います。」と書かれていますし、BrakemanのGitHubのディスカッションでも、「--safe-methods is really only for use with cross-site scripting checks.」という回答が寄せられています。

0
Raw
https://www.techtips.page/ja/comments/417
😄3
🔧1
😿1
❤️1

minitestにおける不等号などの二項演算子を用いたアサーション

wakairo @wakairo
最終更新

minitestにおいて、不等号などの二項演算子(例:<, >, <=, =>)を用いたアサーションをしたいときには、 assert_operator()が利用できます。

assert_operator()を用いるメリット

assert_operator()を用いるメリットとして、アサーションが失敗した時の情報が多くなることが挙げられます。

以下のように、assert_operator()を使用した場合は、

x, y = 0, 1
assert_operator x, :>, y

アサーション失敗のメッセージにおいて、以下のように変数の中身も表示してくれます。

Expected 0 to be > 1.

比較して、以下のように単純に記述した場合は、

x, y = 0, 1
assert( x > y )

以下のようにアサーションに失敗した以外の情報を得ることが出来ません。

Expected false to be truthy.

(参考)assert_not_operator

ちなみにrailsのテスト環境では、assert_not_operatorもあります。

0
Raw
https://www.techtips.page/ja/comments/347
🙋1
❤️1

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

wakairo @wakairo

Rails 7.1で追加されたパスワード関連エラーメッセージへの対応

has_secure_passwordを利用しているモデルがあり、かつ、英語以外のロケールへ対応している既存アプリでは、 rails 7.1で追加されたエラーの種類であるpassword_too_longに対応するエラーメッセージの訳文を追加する必要があります。 (追加をしないとパスワードが長すぎた場合のエラーメッセージが英語で表示されます。)

なお、本件の詳細についてはこちらをご覧下さい。

0
Raw
https://www.techtips.page/ja/comments/333
❤️1

Rails 7.1では、パスワードに関してエラーメッセージの種類が増えた

wakairo @wakairo
最終更新

Rails 7.1に取り込まれたこちらのプルリクエストによって、 ActiveModel::SecurePasswordhas_secure_passwordメソッドを利用している場合のパスワードのバリデーションにおいて、 パスワード文字列が72バイト以内かどうかのチェックが行われるようになりました。 そして、72バイトを超えている場合には、password_too_longという新しい種類のエラーが出るようになりました。

この変更に伴って、日本語表示のRailsアプリでは、password_too_longのエラーメッセージの日本語訳を用意する必要があります。 具体的には、以下の階層の所に以下のような日本語訳が必要となります。

ja:
  errors:
    messages:
      password_too_long: が長すぎます
0
Raw
https://www.techtips.page/ja/comments/332
🔄1
🔧1