単項マイナスと構文解析
単項マイナスとは 単項マイナスと括弧 括弧なし単項マイナスを許容する場合のBNF calcの場合
一般に、HTMLは文書の構造を表し、CSSはその体裁(見栄え)を表します。 Railsは最終的にCSSを含むHTML文書を出力するので、この2つについての理解が必須です。 この記事ではとくにCSSの人気ライブラリであるBootstrapを紹介します。 BootstrapはJavascriptも含んでいます。
RailsとBootstrapの両方とも開発スピードが速いです。 そのため両者を組み合わせてインストールするのは、なかなか難しいものがあります。
今回ここで紹介するのはRails7とBootstrap5の組み合わせで「rails new」コマンドに「-c bootstrap
」または「--css=bootstrap
」オプションをつける方法です。
自分にとっても新しい方法なので、この記事が正しいと保証することができません。
ひとつの体験談として、また数ある情報のひとつとしてお考えいただきたいと思います。
また、この記事に基づいて行ったことから発生する問題に対して何ら保証するものではありませんので、自己責任でお願いします。
(補足)古いバージョンのrailsではgemを使っていました。
たとえば、bootstrap
やbootstrap-sass
などです。
Rails7でもそれらを使うことは可能だと思います。
ただし、bootstrap-sass
はBootstrap3にしか対応していません。
rails7では、newコマンドでBootstrap5の導入が簡単にできるようになりました。
ここで用いた方法以外にCDNを使う方法も可能だと思います(検証不十分)。
CDNはBootstrapで推奨されている方法で、詳しくはBootstrapのサイトを見てください。
私のPC環境は「Ubuntu 22.04」です。
rails new word_book_rails -c bootstrap
を行うと、エラーが出ました。
error @hotwired/turbo@7.2.2: The engine "node" is incompatible with this module. Expected version ">= 14". Got "12.22.9"
error Found incompatible module.
Ubuntu22.04の現在のnodejsのバージョンが12.22.9なので、それが古いというエラーだと思われます。 (注:現在のUbuntu最新版は22.10になりました[2022/11/1]。そのnodejsパッケージのバージョンは18.7.0なので、以下のnodejsの最新版インストールは必要ありません)。 nodejsの新しいバージョンをインストールする情報がnodesource/distributionsにあります。 エラーメッセージではバージョン14以上が必要となっていますが、最新が18なので、それをインストールしてみます。 nodesource/distributionsのREADME.mdの情報によると、次のコマンドを実行すればよいとのことです。
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - &&\
sudo apt-get install -y nodejs
実行したところなぜかエラーになり、その後sudo apt autoremove
、sudo apt remove nodejs
、sudo apt install nodejs
したところ最新版がインストールできました。
エラーが気になりますが、一応次のようになっています。
$ node --version
v18.11.0
word_book_railsフォルダを削除して、再度newコマンドで作成します。
$ rm -rf word_book_rails
$ rails new word_book_rails -c bootstrap
たくさんのメッセージが現れ、数多くの作業が行われていることが感じられます。 途中で
npm WARN set-script set-script is deprecated, use `npm pkg set scripts.scriptname="cmd" instead.
という警告が出ますが、エラーではないので問題ないでしょう。 また、次のようなメッセージも出ます。
File unchanged! The supplied flag value not found! app/assets/config/manifest.js
これがエラーなのか、警告なのか、あるいは問題のない状況なのかは良く分かりませんでした。 しかし、フォルダ内を見渡したところ、Bootstrapはインストールできているので、このまま次の作業に入りたいと思います。
BootstrapはCSSとJavascriptのライブラリです。 これを使うことによって、ウェブの見栄えを美しくしたり、プルダウンメニューのような動的画面を簡単に作ることができます。 これをBootstrap無しで一から作るとしたら、膨大な時間がかかります。 Bootstrapは本当に神様のようなライブラリです(しかも無料)。 また、CSSやJavascriptをよく知らなくても使えるので、学習コストを大幅に下げることができます。
具体的な例はBootstrapのウェブサイトを参照してください。 例えば「Components」の「Buttons」を見ると、サンプルとコードがあります。
<button type="button" class="btn btn-primary">Primary</button>
<button type="button" class="btn btn-secondary">Secondary</button>
<button type="button" class="btn btn-success">Success</button>
<button type="button" class="btn btn-danger">Danger</button>
<button type="button" class="btn btn-warning">Warning</button>
<button type="button" class="btn btn-info">Info</button>
<button type="button" class="btn btn-light">Light</button>
<button type="button" class="btn btn-dark">Dark</button>
<button type="button" class="btn btn-link">Link</button>
サンプルのような色、形のボタンを作るには、対応するコードを書けば(コピペすれば)良いだけです。
また、「Layout」の「Containers」はレスポンシブデザイン(ディスプレイ画面の大きさに合わせて描画領域を自動的に変更する)のコンテナ(箱)です。
bodyタグの内側を<div class="container">
〜</div>
で囲めば、その内容を画面サイズに合うようにサイズ調整してくれます。
この他にも有用な機能が数多くあるので、良く見てください。
今回はBootstrapのコンテナ、コラムとナビゲーションバーを使おうと思います。
作成する単語帳のウェブサイトを「Wordbookサイト」または単に「Wordbook」と呼ぶことにします。
Wordbookのすべてのビュー(画面)はレスポンシブデザインになるように、コンテナの中にいれます。 すべてのビューはapplication.html.erbの中に埋め込まれるので、このファイルにコンテナを設定します。
app/views/layouts/application.html.erb
をエディタで開き、ボディタグの中身を次のように変更します。
<body>
<div class="container">
<div class="col-sm-10 col-lg-8 col-xl-6 mx-auto">
<%= yield %>
</div>
</div>
</body>
それぞれのビューはyieldのところに埋め込まれるので、すべてのビューがclass="container"
のdivタグに囲まれ、レスポンシブになります。
containerは、大きい画面に対して幅を狭くして見やすくしているのですが、それでもWordbookでは幅が広すぎます。
そこで、更に幅の調整をしているのが<div class="col-sm-10 col-lg-8 col-xl-6 mx-auto">
です。
Bootstrapではcontainerで設定された幅を12等分し、そのひとつひとつをカラム(column 列)と呼びます。
col-1
からcol-12
で1カラム分から12カラム分の幅を設定できます。
また、col-sm-10
のように、sm
(smallサイズ以上の画面)をつけて、画面サイズに限定したカラムの設定ができます。
なお、画面サイズを区切るブレークポイント6個定義されています。
ブレークポイント | クラスの接中辞 | 画面幅の範囲 | コンテナの幅 |
---|---|---|---|
X-Small | なし | <576px | 100% |
Small | sm | ≥576px | 540px |
Medium | md | ≥768px | 720px |
Large | lg | ≥992px | 960px |
Extra large | xl | ≥1200px | 1140px |
Extra extra large | xxl | ≥1400px | 1320px |
では、<div class="col-sm-10 col-lg-8 col-xl-6 mx-auto">
の内容を詳しく見ていきましょう。
画面サイズごとのカラム数は次のように成ります。
画面サイズ | カラム数 |
---|---|
xs | 12 |
sm | 10 |
md | 10 |
lg | 8 |
xl | 6 |
xxl | 6 |
例えば、xsは最も小さい画面(スマホ画面など)で、12カラム、すなわちコンテナの全幅を使用します。 また、最も大きい画面のxxl(幅1400px以上)で、6カラム、すなわちコンテナの半分の幅になります。
カラムについてはStandalone Column Classesを参照してください。
Wordbookはナビゲーションバーを常に表示します。 ナビゲーションバーには、append、change、delete、searchなどのメニュー(実際にはリンク)を設定します。
ナビゲーションバーはパーシャルと呼ばれるファイルに記述します。 パーシャルはビューから呼ばれ、そこに埋め込まれるファイルです。 プログラムのサブルーチンに似ています。
例えば、
<%= render "abc" =>
とビューの中で書かれた部分はapp/views/words/_abc.html.erb
の内容で置きかえられます。
ファイル名の先頭にはアンダースコア(_
)がつくことに注意してください。
ナビゲーションバーのサンプルが、Bootstrapのウェブの「Components=>Navbar」にあります。
そのコードをコピペしてから改変します。
以下にパーシャルapp/views/words/_navbar.html.erb
の内容を示します。
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="/">Wordbook</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="/words/append">Append</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/words/change">Change</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/words/delete">Delete</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/words/search">Search</a>
</li>
</div>
</div>
</nav>
変更箇所は、3行目のブランド名をWordbookに、それから9行目から20行目までの項目をAppendからSearchにしたところです。
このパーシャルはレイアウトから呼ばれるようにします。 そのことにより、いつでもナビゲーションバーが現れるようになります。
レイアウトには、この他にフラッシュのパーシャルも読み込ませますが、フラッシュについては別の記事で説明します。 最終的に、レイアウトは次のようになります。
<!DOCTYPE html>
<html>
<head>
<title>WordBookRails</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
</head>
<body>
<div class="container">
<div class="col-sm-10 col-lg-8 col-xl-6 mx-auto">
<%= render "navbar" %>
<%= render "flash" %>
<%= yield %>
</div>
</div>
</body>
</html>
indexのビューは見出しと順序なしリストから構成されます。 リストの項目はナビゲーションバーの説明です。
<h1 class="text-center">単語帳</h1>
<h5 class="my-2">単語帳の使い方</h5>
<ul class="list-group">
<li class="list-group-item">Wordbook: 初期画面に戻ります</li>
<li class="list-group-item">Append: 単語を追加します</li>
<li class="list-group-item">Change: 登録済み単語を変更します</li>
<li class="list-group-item">Delete: 単語を削除します</li>
<li class="list-group-item">Search: 単語を検索しマッチした単語を表示します</li>
</ul>
Bootstrapの効果を確認するために、初期画面のみ実装してみます。 ルーティング、コントローラ、ビューの3つが必要です。
config/routers.rb
にroot "words#index"
の1行を加えます。
Rails.application.routes.draw do
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
# Defines the root path route ("/")
# root "articles#index"
root "words#index"
end
コントローラWordsを作ります。 アクションは初期画面がindexで、AppendからSearchまではそれぞれ同名小文字にします。 railsのgenerateコマンドで作成します。
$ bundle exec rails generate controller Words index append change delete search
create app/controllers/words_controller.rb
route get 'words/index'
get 'words/append'
get 'words/change'
get 'words/delete'
get 'words/search'
invoke erb
create app/views/words
create app/views/words/index.html.erb
create app/views/words/append.html.erb
create app/views/words/change.html.erb
create app/views/words/delete.html.erb
create app/views/words/search.html.erb
invoke test_unit
create test/controllers/words_controller_test.rb
invoke helper
create app/helpers/words_helper.rb
invoke test_unit
コントローラの内容変更は今のところありません。
ビューを作ります。
app/views/words/index.html.erb
を編集します。
編集内容はindexビューで示したコードの通りですapp/views/layouts/application.html.erb
を編集します。
内容はナビゲーションバーとパーシャルで示したコードの通りですapp/views/words/_navbar.html.erb
を作ります。
内容はナビゲーションバーとパーシャルで示したコードの通りですapp/views/words/_flash.html.erb
は当面は空のファイルを作成しておきます以上の準備をしたら、railsでサーバを動作させてブラウザで画面確認します。
今回はbundle exec rails server
を使わずに./bin/dev
を使います。
これは、前者ではJavascriptが動作しないためです。
Rails Guideの「Working with JavaScript in Rails」の「2 Adding NPM Packages with JavaScript Bundlers」に./bin/dev
のことが書かれています。
$ ./bin/dev
21:03:34 web.1 | started with pid 50151
... ... ...
... ... ...
21:03:35 web.1 | * Listening on http://127.0.0.1:3000
21:03:35 web.1 | * Listening on http://[::1]:3000
21:03:35 web.1 | Use Ctrl-C to stop
21:03:36 css.1 | Sass is watching for changes. Press Ctrl-C to stop.
21:03:36 css.1 |
ここでブラウザでhttp://localhost:3000
を見てみます。
コンテンツの幅がコンテナよりもかなり小さくなっていることが分かると思います。 また、上にナビゲーションバーも表示されています。
ブラウザがChromeであれば、スマホ画面でどうなるかを確かめることができます。 右上の3つドットが縦に並んでいるアイコンをクリック=>その他のツール=>デベロッパーツール、と選択します。 中央上に画面サイズ設定のメニューがあります。 そこで、IphoneSEのサイズを選んだのが次の図になります。
スマホ画面いっぱいにコンテンツが表示されていて、レスポンシブ・デザインが効いていることがわかります。 また、ナビゲーションバーも変化しています。 ハンバーガーメニューが右上に現れ、それをクリックするとドロップダウンメニューの中にAppendからSearchまでのメニューが入っています。 このような動的な動きはBootstrapのJavascriptがやっています。
Bootstrapを用いたので労せずメニューやレスポンシブデザインを作ることができました。 BootstrapはRailsに限らず、一般のウェブサイト制作に適用することができます。 どんどん使ってみてください。
単項マイナスとは 単項マイナスと括弧 括弧なし単項マイナスを許容する場合のBNF calcの場合
パーサ・ジェネレータとは 少し複雑な文法 四則(加減乗除)計算のBNF Racc で実装 クラス定義、BNFの記述部分 ヘッダー、インナー、フッター コンパイルと実行 演算子の優先順位と結合における左右の優先順位 まとめ
StrScanライブラリのドキュメント 字句解析とは StrScanライブラリ StrScanライブラリを使った字句解析 実例
lbtというgemを作って公開してみた lbtはどんなgemか ファイルの配置 lbt.gemspec Rakefile gemのビルド RubyGems.orgへのアップロード 補足・・rake/gempackagetaskサブライブラリについて
文字列のエンコーディングに頭を悩ませることはほとんどなくなりました。 なぜなら、どのアプリ、システムもUTF-8を使うようになったからです。 Rubyでもエンコーディングの問題が起こることはまず無いでしょう。 ですが、今回はエンコーディングの考え方を整理してみたいと思います。
Fiberを書いたときから、次はスレッドを書こうと思っていましたが、時間がかかってしまいました。 その理由は、期待したとおりのスレッドの効果がなかったためです。 今回はそのことを書きますが、これはRubyのスレッドの抱えている問題なのか、自分のやり方が悪いのかははっきりしていません。
Fiberは「ノンプリエンプティブな軽量スレッド」とRubyのマニュアルに記載されています。
今回はRubyプログラムから自動的にドキュメントを作成するRDocについて書きたいと思います。 私はこのことについて、エキスパートではありません。 この記事も、初心者の体験談だと考えてください。
Ruby/Gtkの記事を先日書いたときに、「これはかなり使える」という手応えを感じたので、WordBook(Railsで作った単語帳プログラム)のGTK 4版を作りました。 プログラムは「徒然なるままにRuby」のGitHubレポジトリに置いてあります。 レポジトリをダウンロードし、ディレクトリ_example/...
今回はGTK 3とGTK 4をRubyで使うライブラリについて書きたいと思います。
今回もRubyとGUIのトピックです。 Glimmerを取り上げます。
Rubyはグラフィックについて弱い印象があります。 しかし、グラフィックはデバイスに関することなので、言語そのものには直接の関係はないはずで、あるとすればライブラリです。 今後グラフィック関係のgemが開発されることに期待しましょう。
Rails7におけるシステムテストについて書きます。
前回作ったWordbook(リソースフル)のテストを書いてみます。 RailsのテストはminitestをRails用に拡張したものです。
今回はRailsの慣例に沿った形でWordbookを作り直します。
今回はWordBookの検索と削除についてです。
今回はRailsにおけるデータの作成と保存、そして変更について説明します。 そのベースになるモデルとデータベースの話から始め、appendとchangeの動作について詳しく説明します。
一般に、HTMLは文書の構造を表し、CSSはその体裁(見栄え)を表します。 Railsは最終的にCSSを含むHTML文書を出力するので、この2つについての理解が必須です。 この記事ではとくにCSSの人気ライブラリであるBootstrapを紹介します。 BootstrapはJavascriptも含んでいます。
Rubyの最も人気のあるアプリケーションであるRuby on Railsを取り上げようと思い、書き始めました。 予想してはいましたが、相当な分量になってしまいました。 そのため、何回かに分けて記事にすることにします。 また、対象となる読者のレベルをどうしようかと考えましたが、「徒然Ruby」が基礎的な内容から始ま...
Rubyのライブラリ管理システムのRubygemsとコマンドgemおよびbundlerについて説明します。
minitestについて連続して2回書いてきました。 「minitestはドキュメントが少ない」という人がいますが、私も同感です。 例えば、モックとスタブの説明も少ないです。 そこで、今回はmock.rbのソースコードを参考に、モックの私的ドキュメントを書いてみました。 あくまで私個人の考えであり、minites...
今回もminitestの話です。 mockとstubに焦点をあて説明します。
アプリ作成の記事でminitestを使いました。 今回はminitestについて、また一般にテストについて、私の考えを書こうと思います。
今回はメソッドの呼び出し制限ついて説明します。 呼び出し制限にはpublic、private、protectedの3つがあります。
今回は特異メソッド、特異クラス定義、名前空間、モジュール関数について説明します。
2023/10/29 追記:この記事は新しく書き直しました。 古い記事で使っていたGitHubのCalcが大幅にアップデートされたためです。 そこで、この記事に合うようなプログラムsimple_calcを新たに作りました。 このプログラムは本レポジトリの_example/simple_calcにあります。
if〜elsif〜・・・〜else〜endは皆さん良く使うでしょうか? これは場合分けで良く使われる方法です。 これと同様の制御構造にcase文があります。 Cのswitch文に似ていますが、より強力な機能を持っています。 if-else-endよりも高い能力があるといえます。
Procオブジェクトを生成するメソッドlambdaについて説明します。
今回はブロックを一般化したオブジェクトProcを説明します。
ブロック付きメソッドの作り方を説明します。
モジュールには名前空間とミックスイン(Mix-in)の2つの機能があります。 ここではミックスインについて説明します。
クラスの親子関係
Rubyの演算子とその再定義について書きます。
今回からクラスとインスタンスを定義、生成する方法を説明します
Kernelモジュールのメソッドはどこでも使うことができます。 そのメソッドの中には便利で有用なものが多いです。
ここでは私が便利だと思ったメソッドを紹介します。
実数
今回はシンボルとハッシュについて説明します。
文字列は最も使うオブジェクトのひとつです。 特にウェブ・アプリケーションでは、コンテンツだけでなくHTMLのタグやCSSを含めすべてが文字列です。 Rubyは文字列オブジェクトのメソッドが充実しており、またパターンマッチのための正規表現も充実しています。
配列は、どのプログラミング言語にもあると思います。 複数の要素を一括して扱うことができるのが配列です。 Rubyの配列はメソッドが充実しているので、プログラムを効率的、機能的に書くのに役立ちます。
今回の目標はインスタンスです。 インスタンスを説明するために、ローカル変数と文字列オブジェクトを事前に扱います。
今回はメソッド定義です。 メソッド定義はRubyの核心ですが、今回はトップレベルに限って説明します。 この限定によって、内容はかなり易しくなっています。
ブロックはRubyの特長です。 ブロックのおかげで記述が非常にすっきりと分かりやすくなります。 今回はブロックをイテレータの本体として使う方法を説明します。
ここではRubyの最も基本的なオブジェクトである整数について説明します。
「徒然なるままに」をネットで調べてみると、「することもなく、手持無沙汰なのにまかせてという意味」とありました。 まさに、自分の現状を言い当てた言葉。 しかも、ブログに書くネタもなかなか思いつかない日々。