6時だョ!!全員集合!!

Rails・JavaScrictを中心にアウトプットします。

2021年9月28日 現場Rails Chapter5 テストをはじめよう

テストについて

動作を確認する方法として、一般的には以下の3パターンが挙げられます。
1. コンソールでメソッドを呼び出す
2. Webサーバ起動後に、ブラウザを操作して確認する
3. 自動テストを書く

この章では3つ目の「自動テストを書く」について深ぼっていきます。

テストを書くことのメリット

手動テストを自動テストに変更することで、さまざまなメリットを受けられます。

  • テスト全体にかかるコストの削減
  • 変更をフットワーク軽く行えるようになる
  • 環境のバージョンアップやリファクタリングの必須条件
  • 仕様変更の影響の大きさを簡単に把握することができる
  • 仕様を記述したドキュメントとしても機能する
  • 仕様やインターフェイスを深く考えるきっかけとして役立つ
  • 適切な粒度のコードになりやすい
  • 確実性を高めることで開発効率をあげる

現場Railsではテストの重要性が丁寧に説明されています。

テスト用ライブラリ

RSpec

RubyにおけるBDD(Behaviour-Driven Development: 振武駆動開発)のためのテスティングフレームワークです。

本書でRSpecを扱う理由

  • テストが動く仕様書としても機能するということをより分かりやすく示せると判断した
  • RSpecは開発現場で広く利用されており、Railsと共にRSpecについて学べるということに十分に実用性がある
  • 筆者たちはRSpecでの経験が多く、解説もしやすいためです。

TDD(テスト駆動開発)とは

【初心者向け】テスト駆動開発とRspecについて調べてみたが参考になりましたので、以下に引用します。

TDDとは以下の手順で開発を行っていく手法である
1.プロダクトコードを書く前にテストコードを書き、それが失敗することを確認する (レッド)
2.テストに成功するようにプロダクトコードを書く (グリーン)
3.プログラムの振る舞いを変えないように、プロダクトコードの重複などを整理する (リファクタリング) (最初に戻る)
またTDDには以下の原則がある
・テストに失敗しない限り、プロダクトコードを書いてはいけない。
・プロダクトコードはテストを通るように書く。
・テストは少しずつ書き進めていく。

BDD(振舞駆動開発)とは

現場Railsに詳しく書いてあるので、以下に引用します。

TDD(テスト駆動開発)から派生したのもので、動く仕様書でありテストでもあるBehaviour(振舞)をまず先に作り、その後でプロダクトコードを書いていくという開発手法のことを指します。

Capybara

E2Eテストが出来るテスト用フレームワークです。 Rails5.1からGemとしてデフォルトで同梱されており、MinitestやRSpecなどのテスティングライブラリと組み合わせて使います。
ブラウザ操作をシミュレーション出来ます。

UIテストとは

UIテストは、人間がチェックする時と同じ内容をテストします。
つまり、UIの操作・サーバーへのレスポンスとリクエスト・サーバーでのロジック処理と、全てのレイヤーを通したテストを行うことができるのがUIテストです。

画像引用

FactoryBot

テストデータの作成をサポートするGemで、ダミーデータを簡単に用意することが出来ます。また、Railsが標準で用意しているFixtureという仕組みを代替したGemでもあり、開発現場ではFactoryBotが広く利用されています。

テストの種類

主に使用されやすいのはシステムスペックとモデルスペックです。
システムスペックでブラウザの挙動を、モデルスペックでバリデーションのテストを主に行います。

System Specを書くための準備

RSpecのインストール

1. Gemfileにrspec-railsというGemを追加します。

gem 'rspec-rails'

2. bundleコマンド実行して、インストールします。

$ bundle

3. generateコマンドで、RSpecに必要なディレクトリや設定ファイルを作成します。

$ bin/rails g rspec:install  

生成される主なファイル ファイルの概要
spec/spec_helper.rb RSpecの全体的な設定を書くためのファイル
spec/rails_helper.rb Rails特有の設定を書くためのファイル

RSpecはspecディレクトリに格納していくため、Railsのデフォルトのminitestのディレクトリであるtestディレクトリは不要になるので削除しておきましょう。

Capybaraの初期準備

Capybaraはデフォルトでインストール済みのため、spec_helper.rbで以下のように設定を行います。

# RSpecでCapybaraを扱うために、必要な機能を読み込む
require 'capybara/rspec'

# System Specを実行するドライバの設定
RSpec.configure do |config|
  config.before(:each, type: :system) do
    # ブラウザでHeadless Chromeを使うように設定したい→ドライバとしてselenium_chrome_headlessを設定
    driven_by :selenium_chrome_headless
  end
  
 # rspec-expectations config goes here. You can use an alternate 

Headless Chromeについて、[Rails]雑にSystem TestでHeadless Chromeを使うが参考になりましたので、以下に引用します。

Rails 5.1の時点で、System Testは標準ではHeadless Chromeをサポートしていません。その為、Headless Chromeを使用するには、自分でHeadless Chrome用のオプションを指定する、または、独自のdriverを自分で準備する等の必要があります。

※ドライバとは、Capybaraを使ったテストにおいて、ブラウザ相当の機能を利用するために必要なプログラムのことです。
(参照) ヘッドレスモードのchromeで実行する

  • 調べた限り、現場Railsの書き方はRails5.1の書き方をしていて、Rails5.2からRails6.0においては以下のようにしてドライバを設定します。 (パーフェクトRubyonRails参照)
# spec/rails_helper.rb
# ヘッドレスモード(画面を起動しないモード)でchromeで実行する
driven_by :selenium, using: :headless_chrome

FactoryBotのインストール

group :development, :test do
略)
  gem 'factory_bot_rails', '-> 4.11' # 本書ではバージョンを指定
end

以上でシステムスペックを書く準備が整いました。

spec_helper.rbとrails_helper.rbの違い

RSpec 3 時代の設定ファイル rails_helper.rb についてが参考になりましたので、以下に引用します。

rspec-rails のREADMEを読むと、これからは spec/rails_helper.rb に Rails 特有の設定を書き、spec/spec_helper.rbには RSpec の全体的な設定を書く、というようにお作法が変わるそうです。これによって、Railsを必要としないテストを書きやすくなるんだとか。

参照

【初心者向け】テスト駆動開発とRspecについて調べてみた

RSpec 3 時代の設定ファイル rails_helper.rb について

ヘッドレスモードのchromeで実行する

[Rails]雑にSystem TestでHeadless Chromeを使う

2021年9月27日 現場Rails Chapter8 React

Reactとは

Facebook社が開発しているJavaScriptのUIライブラリです。Reactは仮想DOMと呼ばれるデータ構造をメモリ上に持ち、ページ変化の差分のみをレンダリングすることで効率的にページを表示・更新する事ができるという特徴があります。

UIライブラリとは、 いくつかの種類のあるUI(ユーザーインタフェース)を実現するための集合体です。

画像引用

DOMとは?

DOMとは、HTMLやXMLのような文書をプログラムを通して、直接オブジェクトを変更できるインターフェイスのことです。

仮想DOMとは

仮想DOMは本当に“速い”のか? DOM操作の新しい考え方を、フレームワークを実装して理解しように詳しく解説されているので、以下に引用します。

仮想DOMは、ブラウザが持っていたDOMツリーを、JavaScriptのオブジェクト(仮想DOMツリー)として表現します。そして、メモリ上の仮想DOMツリーを用いて差分検知を行い、必要最低限の差分のみをリアルDOMに反映するため、一般的にパフォーマンスが向上すると言われています。

仮想DOMを用いたDOM動作の流れ

  1. 仮想DOMツリーを2種類用意(変更前後の2種類)
  2. データの変更を検知
  3. 仮想DOMを再構築
  4. 変更前後の仮想DOMツリーを用いて差分検知する
  5. 差分があった箇所だけDOMに反映する

画像引用

Reactのインストール

ブラウザ上で実行するにはReactDOMも必要になるので次のようにインストールします。今回、本書ではyarnでインストールしていますが、npmでもインストール可能です。

$ bin/yarn add react react-dom

app/javascript/taskleaf/hello.js

import React from 'react';
import ReactDOM from 'react-dom';

document.addEventListener('DOMContentLoaded', () =>{
  ReactDOM.render(
    React.createElement('div', null, 'Hello World'),
    document.body.appendChild(document.createElement('div')),
  );
});

エントリポイントapp/javascript/packs/application.jsで、先ほど作成したtaskleaf/hello.jsモジュールをimportします。 (エントリポイントとは、WebブラウザからJavaScriptで読み込ませるための基点です。)

import 'taskleaf/hello';

javascript_pack_tagヘルパーメソッドを記述していなければ、共通レイアウトファイルapp/views/layouts/application.html.erbに次のように記述します。

<%= javascript_pack_tag 'application' %>

エントリポイントとは?

エントリーポイントとは、WebブラウザからJavaScriptで読み込ませるための基点のことです。 webpackerでは、app/javascript/packs/application.jsをデフォルトで、エントリーポイントとしています。packsディレクトリ配下に入れるファイルは、エントリーポイントとなるファイルになります。

app/javascript/
├── javascripts
│   ├── a.js
│   └── b.js
├── packs
│   └── application.js # エントリーポイント。a.js, b.js, c.cssを1ファイルにまとめたファイル。
└── stylesheets
    └──c.css
    └──application.css

app/javascript/packs/application.js」をエントリーポイントとする場合は、

<%= javascript_pack_tag 'application' %>

で、Viewから呼び出すことができます。ここで記述しているapplicationは、エントリポイント名です。このように記述することで、application.jsというエントリポイントであるファイルから、JSやCSSをビュー側で読み込ませることが出来るのです。

Railsでモダンなフロントエンド環境を手に入れる

JavaScriptライブラリを利用するのに、今まではGemやSprocketsを使用しました。しかし、これらを使用せずに、yarn(npm)とWebpackerを使用することで、"最新のJavaScriptパッケージ" や "モダンなフロントエンド環境" を手に入れられます。

参照

仮想DOMは本当に“速い”のか? DOM操作の新しい考え方を、フレームワークを実装して理解しよう

新人フロントエンドエンジニアが仮想 DOM について色々調べてみた

npm

【Rails入門】Webpackerではじめるフロントエンド開発!Rails5.1対応 | 侍エンジニアブログ

2021年9月24日 現場Rails Chapter8 Webpacker

Webpackerとは?

JavaScriptのビルドツールである「Webpack」のラッパーで、Webpackを使ってJavaScriptを管理することを簡単にしてくれるGemです。

Railsアプリケーションを新規作成する時にWebpackerを導入する方法

rails new コマンドのオプション「--webpack」を使って、アプリケーションを作成すると、Gemfilewebpacker gemを追加し、必要なファイルの生成やJavaScriptパッケージのインストールをしてくれます。

$ rails new app_name --webpack

Webpackerを使うには、Yarnパッケージマネージャー(1.x以上)とNode.js(10.13.0以上)のインストールが必要です。[Railsガイドより]

既存のRailsアプリケーションにWebpackerを導入する方法

Gemをインストールします。 このGemをインストールする工程はRails6ではデフォルトで行うので必要ありません。bin/rails webpacker:installから実行しましょう。

gem 'webpacker'

以下のコマンドを実行します。

bin/rails webpacker:install

これにより、Webpackerで利用する設定ファイルやディレクトリなどが生成されて、必要なJavaScriptパッケージがインストールされます。

Webpackerを用いて、app/javaScript/packs配下にあるファイルを全てコンパイルできます。このコンパイルを開始するファイルをエントリーポイントといいます。

(※)デフォルトではpacksがエントリーポイントになっていますが、webpacker.ymlファイルで設定することも出来ます。

コンパイルしたJavaScriptファイルはヘルパーメソッドである「javascript_pack_tag」で読み込むことが出来ます。

# view
<% javascript_pag_tag 'appliation' %>
# エントリーポイントのファイル名がapplication.jsの場合は上記のように記載します。

WebpackerとWebpackの違い

【基本】webpackerとは何か学ぼうが大変参考になりましたので、以下に引用します。

Webpackerとは、Webpackを使用してRuby on Rails上でJavaScript開発をするために必要な一連のまとまりを、標準で実装することができるgemパッケージです。Rails6.0より、webpackerが標準実装になりました。 そもそもWebpackとは何かというと、CSSJavaScript、画像などのプログラムを作成する際の部品であるモジュールを、1つのファイルとしてまとめるためのモジュールバンドラーです。 Node.jsで、サーバーサイドで動きます。 平たく言うと、WebpackはJavaScriptファイルのコーディングにおいて、開発を効率的におこなうことができるよう助けるような役割を担っているということです。

画像引用

また、Ruby on Rails には、「Asset Pipeline」と呼ばれるwebpackerとは別のモジュールバンドラーが存在しますが、進化しているJavaScriptなどのフロントエンドの環境と比較をすると、Asset Pipelineは徐々に古いモジュールハンドラーになりつつあります。 つまりwebpackerの登場は、近年成長を遂げたフロントエンド環境に沿った、時代の変化に合わせたモジュールハンドラーであると言えます。

(※)しかしRails7においてはwebpackerは廃止になるそうです。フロントエンドのトレンドは移り変わりが激しいと言われる由縁なのかなと感じました。

※モジュールハンドラーとは?

はじめてのモジュールバンドラーに詳しく説明されているので、引用します。

モジュールバンドラー(module bundler)は、文字通りモジュールをひとまとめにする(bundle)ツールです。JavaScriptの依存関係を解決し、それらをインクルードしたひとつのファイルにまとめてくれます。


画像引用

require で表現された依存関係を解決していき、 コンパイルする際にそれらを全て内包したファイルを作ってくれるのが一般的なモジュールバンドラーの振る舞いです。

つまり、requireを使って、取り込まれたJSファイルがたくさんあるモジュールでもコンパイル時に、取り込まれたファイルも全て含めた一つのモジュールとして扱ってくれるのが、モジュールバンドラーです。

Babel(バベル)とは

【JavaScript】Babelとは何かに詳しく説明されているので、引用します。

JavaScriptのコードを新しい書き方から古い書き方に変換するツールである。具体的には、JavaScriptの言語仕様であるES2015以上の仕様のJavaScriptで記述すると、Internet Explorer11といった古いブラウザでは動作しない。そこで、Babelを使ってES2015・ES2016といった仕様で記述したJavaScriptファイルを互換性のあるEXMAScript5に変換する。

画像引用

ビルドとコンパイルの違い

コンパイルソースコードを機械が理解できるような機械語に変換することです。 ビルドはコンパイルしたファイルを一つにまとめ、実際に実行まですることです。
画像引用
上記の図のようにコンパイルして、機械語に翻訳したファイル等を組み合わせて、実行できるようにする作業のことをビルドと言います。つまり、コンパイルの作業も含めてソースコードから実際のプログラムを作り上げる作業がビルドという訳です。

Sprockets とは?

Rails Sprocketsとのお別れの仕方 - 最初の一歩 -に詳しく説明されているので、引用します。

Rails 3.1 から導入された gem で、アセットファイル(JS, CSS, 画像など)を効率的に管理するための Asset Pipeline という仕組みの基盤です。

Webpackerをインストールする際にyarnが必要ですと書いてあるのはなぜか?

yarnはJavaScriptのパッケージを管理してくれるものですが、それを使ってインストールするということは、そもそもWebpackerはパッケージなのでしょうか? または、Gemfileからインストールするので、Gemなのでしょうか?詳しく調べてみました。Webpacker移行ガイド / Migrating from Webpacker to Simpackerが大変参考になったので、以下に引用します。
画像引用
上記の図によると、Gemであるwebpackerと、npmまたはyarnでインストールする@rails/webpackerを合わせて一般的なWebpackerが構成されてることが分かります。GemのWebpackerと@rails/webpackerにはそれぞれ役割があり、Webpackerまとめの章で詳しく説明します。

以上の内容を整理すると、Webpackerを使用するためには、webpacker gemと@rails/webpacker パッケージのインストールが必要です。@rails/webpackerはnpmまたはyarnを用いてインストールします。どちらもインストールすることで、Webpackerを使用できるようになります。

  • webpacker gemをインストールする
    (※)このGemをインストールする工程はRails6ではデフォルトで行うので必要ありません。
gem 'webpacker'

gemfileに記載後、bundle install

  • @rails/webpackerをyarnまたは、npmを使ってインストールする
# yarn/npmコマンドは実行していないが、裏側で、yarn/npmを使ってインストールが行われています。
# Webpackerで利用する設定ファイルやディレクトリ、必要なJavaScriptモジュールがインストールされます。
bin/rails webpacker:install

Webpackerまとめ

これら全てをひっくるめてWebpackerです。

Webpacker 提供してくれている機能
gem webpacker rails webpacker:installコマンド, ヘルパーメソッド
npmもしくはyarn @rails/webpacker webpack, webpack-assets-manifest, babel, postcss

参照

コンパイルとビルドの違い

【基本】webpackerとは何か学ぼう

【JavaScript】Babelとは何か

Rails Sprocketsとのお別れの仕方 - 最初の一歩 -

はじめてのモジュールバンドラー

webpack学習の基本のき

Webpacker移行ガイド / Migrating from Webpacker to Simpacker

2021年9月23日 現場Rails Chapter8 npmについて深掘りしました

先日の続き

※先日学んだJavaScriptのパッケージマネージャーであるyarnとnpmで、yarnはアウトプットしたので今回はnpmについて学んでいきます。yarnはnpmを改造して作られたものなので根幹は同じという認識です。

npmとは?

npmは、Node.js 関連のパッケージをインストールするためのコマンドラインツールです。 WindowsMacOS であれば、npm は Node.js に同梱されており、Node.js をインストールすることにより npm も使えるようになります。基本的には、JavaScript関連のパッケージを管理するのに使います。

wiki)参照↓

npmとはパッケージ管理システムの一種。Node Package Managerの意[3]。なおnpmとは「Node Package Manager」の頭文字を取ったものではなく、実際はバクロニムである。 Node.jsのパッケージ管理システムであり、V8 JavaScriptエンジンで動作する。npm自身もJavaScriptで記述されている。 Node.jsは、サーバ上で動作するJavaScriptであるが、Node.jsを使ったツールが開発されるようになると、これらを管理するバージョン管理システムの必要性が生まれた。

npmでのパッケージインストール方法

npmでインストールされたパッケージは、node_modulesディレクトリに配置されます。これは、yarnでインストールする時と同じです。

# package.json
{ 
  "name": "sample",
  "dependencies": {#=> 通常は、dependenciesにパッケージが入ります。
    "request": "^2.81.0"
  },
  "devDependencies": {#=> 開発環境のみで、使いたいパッケージが入ります。
    "mocha": "^3.4.2"
  }
} 

//このほかの要素は省略します 
$ npm install
// package.jsonに記載されているパッケージを全てインストール(dependencies、devDependenciesに書かれているパッケージも全てインストールされます。)
// あらかじめ、インストールしたいパッケージをpackage.jsonに記載しておく必要があります。(bundle installコマンドのようなもの)
$ npm install {パッケージ名}
// dependenciesにパッケージを指定してインストール
// npm v5 以降はインストール時にデフォルトで package.json の dependencies に追加してくれるようになったため、--saveオプションは不要になりました。
// 前もって、package.jsonにパッケージを記載しておく必要はなく、パッケージ名を指定して、コマンドのみで、パッケージをインストール出来ます。
$ npm install --save-dev {パッケージ名}
// devDependenciesにパッケージを指定してインストール(devDependenciesには、開発に必要なパッケージのみを書きます。)

npmとyarnの違い

npm v6以降、npmのパッケージインストール速度が向上したので、yarnとの性能の差はあまりありません。 npmもyarnもpackage.jsonというファイルでパッケージを管理します。管理するパッケージは同じということです。(Gemで言えばGemfileです。)

バージョンのロックファイル
yarn yarn.lock
npm package.lock.json

yarnnpmを共存させることも出来るのですが、どちらかに統一してパッケージをインストールするようにしましょう。共存していると、デプロイ時にwarningが出ることがあります。
yarnもnpmもパッケージをインストールするための手段が異なるだけで、結果として、javascriptのパッケージをインストールして、実際に使えるようにしています。インストール時にnode_moduleディレクトリにパッケージを配置するなどの挙動はほぼ同じです。インストール後に、インストールの結果が書かれたファイル(gemfile.lockのようなもの)が異なるだけです。

そもそもライブラリとパッケージ、モジュールの違いとは?

画像引用

モジュールとは?

プログラム内で、繰り返し使えるような部品として提供されているものがモジュールです。自分で作成することも出来ますし、誰でも使えるように提供されているものもあります。提供されているものを使うときは、requireを使って、モジュールファイルを取り込む必要があります。

ライブラリとは?

モジュールの集まったものがライブラリとなります。

パッケージとは?

パッケージとは、ライブラリで集めたプログラムを、似た機能ごとにあつめたものです。つまり、ライブラリの集合がパッケージです。

例えると

例えた内容
モジュール 部品
パッケージ
ライブラリ 似た箱を揃えて荷詰め

モジュール < パッケージ < ライブラリという関係性をイメージすると良いです。

議論の途中でフレームワークとライブラリの違いについて気になったので調べました。

React, Vue.js はフレームワーク?ライブラリ?がとても参考になりましたので、以下に引用させていただきます。

フレームワークとは?

アプリケーションを動かすために必要な処理・機能が一通り実装されている。 その他に必要な処理などがあれば自分で実装して、フレームワークに組み込んで利用することができる。 開発者が一からフルスクラッチで作るのは大変だけど、フレームワークを利用することで、楽するとこは楽してコアな部分にフォーカスすることができる。

例)Vue.js, Ruby on Rails, Bootstrap

ライブラリとは?

いろいろな便利な機能が準備されていて、必要に応じて必要な機能のみをピックアップして利用する。 主体はライブラリではなく、主体のプログラムから呼ばれて使われる。

例)React, jQuery

料理で例えると

例えた内容
フレームワーク 料理セット一式
ライブラリ 調味料

yarnとnpmコマンドの違いをまとめました

注) npm 5.0.0 以降からは、--saveオプションは省略できます。

yarn npm
yarn install npm install
yarn add パッケージ名 npm install パッケージ名
yarn add --dev パッケージ名 npm install --save-dev パッケージ名

参照

バクロニム

npm (パッケージ管理ツール))

npm/cli

npmとyarnのコマンド早見表

会計freeeがyarnからnpmに出戻った本当の理由

npm入門

【npm,yarn】今さら聞けないlockファイル

モジュール・パッケージ・ライブラリの違い。

ライブラリとパッケージとは?

React, Vue.js はフレームワーク?ライブラリ?

【いまさらですが】package.jsonのdependenciesとdevDependencies

2021年9月22日 bundle installとbundle updateについて気になることをさらに深掘りました

※先日のブログ記事の内容を一部転載し補足しています。

bundle install と bundle updateの違い

bundlerをインストールすると、bundle installbundle updateのコマンドが使えるようになるのですが、「そもそもそれらのコマンドの違いって、何?」と思ったので、違いを以下に記述していきます。

bundle install

bundle installを実行すると、railsは、Gemfileを元にインストールを行います。(バージョンが指定されてないGemはGemfile.lockのバージョンを参照します) この時、Gemfile.lockに記述されていない、且つGemfileに記述されているGemがある場合、そのGemとそのGemに関連するGemをインストール後、Gemfile.lockを更新します。

↓bundle installでGemfile.lockにあるGemのバージョンを変更可能か否か気になったので実際に検証してみました。

上記のようにエラーが起こり更新に失敗します。 Gemのバージョンを変更をするにはbundle updateする必要があるとエラー文には出てきますが、以下のような問題点があります。

bundle update

bundle updateを実行すると、Bundlerは、Gemfileを元にgemのインストールを行います。その後、Gemfile.lock内に記載しているバージョンを無視して更新します。

bundle updateGemfileに記載されているgemを全て、最新のバージョンに更新するので、アプリケーションが通常通り動かなくなってしまう場合があります。gemは相互に関係し合っており、最新のバージョンをインストールすることで、互換性が取れなくなることがあるからです。
※これはGemfileにバージョンを指定していない場合の話です。

ではGemfileでバージョン指定していない状態でGemfile.lockにあるGemのバージョン変更する場合はどうするのがいいのかと思い調べました

bundle install ではバージョン変更は行えないが、bundle updateには上記のリスクがあるため、以下のコマンドが重宝します。

$ bundle update [Gem名]

ただし、このコマンドには注意点があります。
それは入力したGemと依存関係のあるGemも更新してしまう点です。

これを解決し、指定したGemのみを更新した場合はconservativeオプションをつけると良いです。

$ bundle update --conservative [Gem名]

これでGemfile.lockにあるGemのバージョン変更を安全に行えます。 場面に応じて適切なコマンドを使用しましょう。

まとめ

コマンド 説明
bundle install Gemfileにはあるが、Gemfile.lockに記載のないものをインストールします
bundle update --conservative[Gem名] 指定したGemのバージョンを更新します
bundle update[Gem名] 指定したGemと依存関係のあるGemを含めてバージョンを更新します
bundle update GemfileからGemfile.lockを生成します。 現行のGemfile.lockは破棄します。

参照

bundle updateで特定のgemのみ更新する

bundle update | Bundler日本語ドキュメント |

Ruby のバージョンアップで気をつけるべきこと

2021年9月21日現場Rails Chapter8 Turbolinks

Turbolinksを無効化する

Turbolinksには高速化できるというメリットがある反面、ブラウザのページ遷移が発生しないなどのデメリットもあります。そのため、Turbolinksの性質をよく調べてから、使うようにしましょう。 Turbolinksをよく知らない場合は、無効化するのも一つの手です。無効化する方法は、いくつかあるので以下に記載します。

rails newコマンド実行時に、Turbolinksを無効化する

Rails4以降ではTurbolinksはデフォルトで導入済みになっていますが rails new時点で除外する場合は以下のようにskipコマンドを使用します。

rails new app_name --skip-turbolinks

既存アプリケーションのTurbolinksを無効化する

Tubolinksが有効になっている場合は以下の手順で無効化出来ます。

1.Gemfileからturbolinks gemを削除します。

# Gemfile
gem 'turbolinks', '~> 5' # 削除

2.bundle installします。bundle install後、サーバーを再起動します。

bundle install

3.app/assets/javascripts/application.jsなどのマニフェストファイルからTurbolinksの読み込み処理を削除します。

// マニフェストファイル
//= require turbolinks // 削除

4.app/views/layouts/application.html.erbなどのレイアウトファイルからdata-turbolinks-track: 'reload'属性を削除します。

<%= stylesheet_link_tag 'application', media: 'all' %>  
<%= javascript_include_tag 'application' %>

結局bundlerとは何なのか?

【Rails】 結局bundlerって何?bundlerの仕組みを図解形式で徹底解説 上のサイトに詳しい説明があるので、引用します。

bundlerとは、GemのバージョンやGemの依存関係を管理してくれるgemです。bundlerを使うことで、複数人での開発やgemのバージョンが上がってもエラーを起こさずに開発できます。

つまり、gem同士のバージョンを管理してくれるのがbundlerです。bundlerを使うことで、以下のことが出来ます。

bundlerを使って出来ること

  • bundlerを使ってgemをインストールするとgem同士の互換性を保ってくれるので、Gemを追加したり時間が経ってもエラーを起こさず開発できます

  • Gemfileという1つのファイルにGemを書くのでgemの管理がしやすいです

  • Gemfileを使ってアプリごとにGemを管理できます

  • 環境ごとにインストールするGemを管理できます

  • gemの互換性を保ってくれるので、Gemfileさえ共有すれば複数人でアプリを開発してもエラーを起こさないです 引用:pikawaka

bundle install と bundle updateの違い

bundlerをインストールすると、bundle installbundle updateのコマンドが使えるようになるのですが、「そもそもそれらのコマンドの違いって、何?」と思ったので、違いを以下に記述していきます。

bundle install

bundle installを実行すると、railsは、Gemfileを元にインストールを行います。(バージョンが指定されてないGemはGemfile.lockのバージョンを参照します) この時、Gemfile.lockに記述されていない、且つGemfileに記述されているGemがある場合、そのGemとそのGemに関連するGemをインストール後、Gemfile.lockを更新します。

bundle update

bundle updateを実行すると、Bundlerは、Gemfileを元にgemのインストールを行います。その後、gemfile.lockを更新します。

bundle updateGemfileに記載されているgemを全て、最新のバージョンに更新するので、アプリケーションが通常通り動かなくなってしまう場合があります。gemは相互に関係し合っており、最新のバージョンをインストールすることで、互換性が取れなくなることがあるからです。

bundle install ではバージョン変更は行えないため、以下のコマンドが必要です。

$ bundle update --conservative [Gem名]

Gemfileはgemをインストールするための「設計図」
Gemfile.lockは、実際にGemをインストールした後の「結果図」

モダンなJavaScript管理を行う

Yarnとは何?

Yarnとは、Facebook社が開発したJavaScriptのパッケージマネージャです。Yarnを用いることで、JavaScriptのパッケージを外部からインストールしたり、パッケージ毎の依存性を管理できます。

パッケージマネージャーとは?

Package Manager は「そのソフトにどのソフトのバージョン何以上が必要か」、「今インストールされているソフトは何か」といった情報を持っているため、必要に応じてソフトを勝手にダウンロードしてきてインストールしてくれます。 引用:Package Manager(パッケージマネージャー)の必要性、Xcode のインストール、Homebrew のインストール、Homebrewを使ってみる

つまり、パッケージマネージャーを使うことで、ソフト(パッケージ)間の依存関係やバージョンを管理し、さらにパッケージのインストールやアンインストールを簡単に行うことが出来るようになっています。

package.jsonとは

Yarnコマンドでインストールしたいパッケージを記述する場所であるとともに、パッケージを定義するファイルです。Gemfileと同じようなものとイメージできます。

Yarnとnpm

JavaScriptのパッケージマネージャとして一般的にYarnnpmが挙げられます。 Gemfile.lockのようなバージョン・ロックの機構として、yarn.lockがあり、 ライブラリの内容に予期せぬ変更が変わっていないことを確認してくれるためセキュリティが高いという特徴があります。

Yarn使い方

以下のコマンドでパッケージの追加とインストールを同時に行います。 インストールされたパッケージは、node_modulesディレクトリに配置されます。

$ bin/yarn add [パッケージ名]

開発環境のみで利用するパッケージとして指定したい場合は「--dev」オプションをつけます。

予め、package.jsonにインストールしたいパッケージを記述しておき、その記述したパッケージを一括でインストールする場合、以下のコマンドを実行します。このコマンドは、bundle installに似たものとイメージ出来ます。

# 一括でパッケージをインストールする
$ bin/yarn install

Yarnでパッケージを削除する場合、以下のコマンドを実行します。

$ bin/yarn remove [パッケージ名]

yarnまたは、npmとgemのどちらを使うのが正解?

JSのライブラリは、yarnかnpm(どちらもJSのパッケージマネージャー)を使って、インストールするべきです。gem(rubyのライブラリ)として対応したJSのライブラリを使用することも出来ますが、バージョン対応が遅いなどのデメリットがあるので、yarnまたは、npmを使うことをオススメします。

参照

【Rails】 結局bundlerって何?bundlerの仕組みを図解形式で徹底解説

bundle install と bundle updateの違いについて

npmとyarnのコマンド早見表

会計freee が yarn から npm に出戻った本当の理由

2021年9月20日現場Rails Chapter8 Turbolinks

Turbolinksとは?

全てのリンクに対するページ遷移を自動的にAjaxする事で、ページ遷移を高速化する仕組みです。Turbolinks自体はJavaScriptのライブラリとして提供されていますが、Railsでは利用しやすいようにGemとしてrals newすることでデフォルトで組み込まれています。
画像引用

  1. リンクのクリックイベントが発火
  2. 画面遷移を阻害し、非同期でリクエストを送る
  3. HTMLをレスポンスとして返す
  4. headタグに含まれているJSとCSSが、現在のページと一致しているかチェック
  5. headタグは統合、bodyタグは書き換えることで画面遷移が起きたように見せかける

つまり、Turbolinksは、リンク(aタグ)をクリックした際にページを遷移させるのではなく、Ajaxを使って、headタグを統合、bodyタグを書き換えます。head内のタグを統合することで、titleタグ以外のcss,Javascriptファイルを毎回読み込む必要がなくなるので、高速でページを表示できます。

ここまでのまとめ:なぜTurbolinksを使うと高速化できるの?

Turbolinksはページ遷移を行うのではなく、head要素のcssJavascriptを統合(titleは書き換え)し、body要素を書き換えます。そうすることで、不必要な要素を再度読み込む必要がなくなり、高速化が実現できるのです。

Turbolinksが有効な環境での注意点

  • ブラウザのページ遷移が発生しないことが多くなります。
// tubolinksはリンクをクリックすることで、発火するので、ページ全体が読み込まれるイベント(window.onload)は発生しなくなります。
window.onload = function() {
  console.log('Hello World!');
};

on loadはページ全体が読み込まれた際に発生するイベントを定義しています。

しかし、Turbolinksは通常のページ遷移を発生させないため、このロードイベントは最初のページが表示されるとき以外は発火されません。Turbolinks使用下では以下のようにturbolinks:loadイベント(Turbolinks専用のイベント)を使用する必要があります。

document.addEventListener('turbolinks:load', function() {
  console.log('Hello World');
});

scriptタグはhead要素内に記述する

scriptタグをheadタグに書くことで、リクエスト毎のJavaScript取得を防げます。 そのためscriptタグはheadタグに書くべきです。turbolinksでは、headタグ内に新しいscriptタグがあった時に、そのタイミングで一回統合を行います。 body要素にscriptタグを配置してしまうと毎回読み込まれてしまうため書くべきではありません。(JavaScriptを毎回読み込まないことで高速化しているのでTurbolinksの恩恵を受けられない)

またTurbolinksはページ遷移が発生しないためwindowやdocumentといったグローバルオブジェクトが変わらずに、処理内容が重複してしまうためです。

グローバルオブジェクトとは?

グローバルオブジェクトは、グローバルスコープ上に常時存在するオブジェクトです。 ウェブブラウザーでは、明示的にバックグランドタスクとして起動されるコードを除き、 Window がグローバルオブジェクトになります。 ウェブにおける JavaScript コードのほとんどはこのケースに該当します。

参照

【Rails】初心者向け!画面遷移の高速化を行うTurbolinksについて図を用いて詳しく解説

turbolinks/turbolinks