プログラマ・アゲイン blog

還暦を過ぎたけどプログラマ復帰を目指してブログ始めました

Ruby on Railsを勉強中に遭遇した問題(1)

PHP+MySQLを勉強しようとしていたんだけど、何となくRuby on Railsが気になって、こちらの勉強を先に始めることにしました。

早速、テキストとして「Ruby on Rails 6 超入門」を購入して勉強を始めました。

 

テキストに従ってやっていくと、テキストには書かれていない問題にいろいろ遭遇しました。

原因は、導入した Ruby がバージョン3.1、Rails が バージョン7.0 によるところが大きいようで、特に Rails はいろいろ変更されているようです。

Ruby on Rails 7の主要な新機能・機能追加・変更点 - Qiita

Rails 7では、JavaScriptフロントエンドの大幅な刷新、CSS BundlingによるTailwind CSSやPostCSSのサポートを含めた、メジャーバージョンアップグレードにふさわしい機能強化が行われています。

 

ちなみに、導入したバージョンは以下のものです。

C:\Windows\System32>ruby -v
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x64-mingw-ucrt]

C:\Windows\System32>rails -v
Rails 7.0.3.1

 

ここでは、遭遇した問題について、内容と対応を記録したいと思います。

 

 

Railsアプリケーションの作成

rails aborted! TZInfo::DataSourceNotFound

rails new アプリケーション名」でアプリケーションを作成しようとすると、以下のようなエラーが出ます。


Webでググったところ、以下の情報がありました。

ruby - rails new を実行した際に、rails aborted !というエラーが出て解決できません。 - スタック・オーバーフロー

Ruby Istallerの64bit版は、3.0系まではmingw64でしたが、3.1系からはucrt64に変更になりました。

(中略)

ucrt64版は対象では無いと判断されます。現在の所、Bundlerにucrt64版を指定するplatformに渡すオプションは存在しません。

(中略)

しかし、このplatformの指定ではucrt64版は対象とはならないため、tzinfo-dataが読み込まれず、railsの実行に失敗する状況になっていました。

根本的に修正されるにはBundler側がucrt64版に対応することとRails側がucrt64版でもtzinfo-dataを対象とするように初期のGemfileを用意するようにすることの二つが必要です。

 

対応として、提示されている解決策の「Gemfile で tzinfo-data を読み込むようにする。」を行いました。
まず、以下の「template.rb」を作成します。

data = File.read('Gemfile')
data.sub!(/^.*gem "tzinfo-data".*$/, 'install_if(-> { RUBY_PLATFORM =~ /mingw|mswin|java/ }) { gem "tzinfo-data" }')
File.write('Gemfile', data)

 

これで、「rails new アプリケーション名 -m template.rb」を実行すると、TZInfo のエラーは出なくなりました。

run  bundle install NameError: uninitialized constant Gem::Source

次に出ていたのは、bundle 時のエラーです。

rails new自体は最後まで処理された感じではあるのですが、以下のエラーが途中に出力されています。

run  bundle install
[14668, #<Thread:0x0000025031c757a8 run>, #<NameError: uninitialized constant Gem::Source

      (defined?(@source) && @source) || Gem::Source::Installed.new

 

これも Webをググると、以下の情報がありました。

【Docker】NameError: uninitialized constant Gem::Source 解消法【Rails】 - Qiita

どうやらBundlerのバージョンが2.3.7だとNameError: uninitialized constant Gem::Sourceが発生するようです。

 

ということで、Bundlerのバージョンを確認しました。

c:\Data\Web_study\Rails>bundler -v
Bundler version 2.3.7

ビンゴです。

早速 Bundler のバージョンをアップしました。

c:\Data\Web_study\Rails>gem install bundler
Fetching bundler-2.3.20.gem
Successfully installed bundler-2.3.20
Parsing documentation for bundler-2.3.20
Installing ri documentation for bundler-2.3.20
Done installing documentation for bundler after 1 seconds
1 gem installed

c:\Data\Web_study\Rails>bundler -v
Bundler version 2.3.20

この状態で「rails new アプリケーション名 -m template.rb」を実行すると、次のように問題なくBundle処理が始まり、Railsアプリケーションが作成されました。

         run  bundle install
Fetching gem metadata from https://rubygems.org/...........
Resolving dependencies.....
・・・
Installing tzinfo-data 1.2022.2
Bundle complete! 15 Gemfile dependencies, 75 gems now installed.

 

Rails Serverを立ち上げてアクセスすると、次のサンプル・ページが表示されました。

 

コントローラーとビュー

assets scss が作成されない

rails generate controllerコマンドで、コントローラーを作成した時、以下のメッセージが出力されます。

c:\Data\Web_study\Rails\RailsApp>rails generate controller hello
      create  app/controllers/hello_controller.rb
      invoke  erb
      create    app/views/hello
      invoke  test_unit
      create    test/controllers/hello_controller_test.rb
      invoke  helper
      create    app/helpers/hello_helper.rb
      invoke    test_unit

 

見たとおり、assets scss が有りません。

テキストで指示されている .scssファイルは、自分で作成することにしました。

cannot load such file -- sassc

テンプレートを使用するために、application.html.erb を使用したところ、以下のメッセージが表示されました。

 

これも Webをググると、解決方法を示されている奇特な方がおられました。

rails 7.00における "cannot load such file --sassc"の解決法 - Qiita

コメントアウトを削除して、bundle installをすることで解決することができます。
rails7.00以前はこのgemが環境構築の際に自動でinstallされていましたが、7.00以降では標準でインストールされないようです.

 

とのことなので、アプリケーションのフォルダーにある Gemfile を変更し、コメントを外しました。

45  # Use Sass to process CSS
46  # gem "sassc-rails"
   ↓
45  # Use Sass to process CSS
46  gem "sassc-rails"

そして、bundle install し直します。

c:\Data\Web_study\Rails\RailsApp>bundle install
・・・
Using sassc 2.4.0
・・・
Bundle complete! 16 Gemfile dependencies, 79 gems now installed.

 

rails server を再度立ち上げてアクセスしたところ、エラーにならずに表示されました。

hello.scss がうまく適用されない

ところが、hello.scss で設定したスタイルになりません。

分かりやすいように、h1 と p で以下のように色を分けてみました。

body {
    color: darkred;
    font-size: 28px;
}

h1 {
    color: darkblue;
    margin: 25px 0px;
}

 

しかし、ヘッダーの方は色が変わったのですが、パラグラフの方は色が変わりません。

デベロッパー・ツールで確認すると、_reboot.scss で定義した方が application... で定義したものより先に有効になっています。


テキストでは、<head> ~ </head>内に、<link rel="stylesheet" href="https:// ... bootstrap.css> のタグを追加するとしか書かれていません。

しかし、書き方の順番が問題です。

そこで、以下のように、<%= stylesheet_link_tag ...>の上にくるように変更しました。

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.css">

    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
    <%= javascript_importmap_tags %>

 

これでうまくスタイルが適用されました。

デベロッパー・ツールで見ても、application... で指定したものが有効になっています。

この辺は、基本中の基本的なことかもしれません。(^ ^);

フォームの送信ができない

テキスト通りに index.html.erb や hello_contrller.rb や routes.rb を修正したはずなのに、フォームの入力画面からテキストを入力して「送信」ボタンを押すとエラーになります。

しかも、テキストで示されているような「ActionController::InvalidAuthenticityToken」というエラーではありません。

ブラウザーGoogle Chrome:バージョン: 106.0.5249.119(Official Build) (64 ビット)」のデベロッパー・ツールで見ると、コンソールにエラーが1件(Form responses must redirect to another location)と警告が2件表示されました。

そこで、「Form responses must redirect to another location」でググってみると、「Turboの動作をオフにする」という情報が、以下のページの引用部分に有りました。

https://factor.xseed.link/2022/04/01/post-17888/#outline__2

Turboの動作をオフにする方法は、以下のページに載っています。

http://Turbo Drive をリンク/フォーム単位で無効化する

formタグでTurboの動作をオフにする

早速、以下の赤字ように formタグに追記してみました。

<form data-turbo="false" method="POST" action="/hello/index">

 

これで正しく?動いて、テキストと同じエラー画面が表示されました。

フォームヘルパーでTurboの動作をオフにする

ところが、フォームヘルパーを使用すると、やはり Turbo の動作が入ってエラーになります。

理由は、テキストにある form_tag を使って Turbo オフを追記してみると、以下のような formタグが生成されてしまうからです。

<%= form_tag(controller: "hello", action: "index", data: {turbo: false}) do %>
↓
<form action="/hello/index?data%5Bturbo%5D=false" accept-charset="UTF-8" method="post">

 

そこで、form_tagヘルパーメソッドは非推奨なので、後継である form_withヘルパーメソッドに変更してみました。

<%= form_with(controller: "hello", action: "index", data: {turbo: false}) do %>
↓
<form data-turbo="false" action="/hello/index" accept-charset="UTF-8" method="post">

 

今度は、formタグに「data-turbo="false"」が作成されており、正しく動作することができました。

javascript_pack_tagがエラーになる

レイアウトを作成するとのことで、hello.html.erb を作成しました。

ところが、テキスト通りに入力し実行すると、javascript_pack_tag が NoMethodError になります。

そこで、もともと application.html.erb で記述されていた以下のものに変更しました。

<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
↓
<%= javascript_importmap_tags %>

 

javascript_importmap_tags では、以下のタグが生成されます。

<script src="/assets/es-module-shims.min-d89e73202ec09dede55fb74115af9c5f9f2bb965433de1c2446e1faa6dac2470.js" async="async" data-turbo-track="reload"></script>
<script type="module">import "application"</script>

 

因みに、javascript_pack_tag は、Webpacker でビルドしたスクリプトを読み込む指定のようですが、Webpacker 自体よく理解できていないので、これ以上の深追いはあきらめました。

circular argument reference エラーになる

メッセージ・ボードを作成するとのことで、msgboard_contoroller.rb を作成しました。

実行したところ、circular argument reference のエラーになります。

Webをググると、やっぱりヒットしました。

以前は、warning だったようです。

ruby2.2.0ではメソッドの引数のデフォルト値に同じ名前の変数を使えない - Qiita

以下のページのように、キーワード引数に括弧 ( ) を付けることで解消されました。

【rails備忘録】エラー:circular argument reference (Ruby on Rails 6 超入門) | マサのライフワーク

 

以上、Ruby on Rails を勉強していく中で、いろいろ経験することができました。

取りあえず ControllerとView の第2章まで終わったので、続きがあれば別のページに載せていきたいと思います。