単項マイナスと構文解析
単項マイナスとは 単項マイナスと括弧 括弧なし単項マイナスを許容する場合のBNF calcの場合
Rubyの最も人気のあるアプリケーションであるRuby on Railsを取り上げようと思い、書き始めました。 予想してはいましたが、相当な分量になってしまいました。 そのため、何回かに分けて記事にすることにします。 また、対象となる読者のレベルをどうしようかと考えましたが、「徒然Ruby」が基礎的な内容から始まったことに鑑み、初心者レベルから始めることにしました。 Railsを仕事で使っているような方には面白くないかもしれませんが、ご容赦ください。
定番のドキュメントを3つ挙げておきます。
「Rails Guide」「API reference」「ソースコード」を理解すれば完璧ですが、初心者には難しいかと思います。 「Railsチュートリアル」(無料でもよい)から始めるか、または「Railsガイド」の第1章から読み始めると良いと思います。
RailsはRubyのgemです。 gemコマンドでインストールできます。
$ gem install rails
RailsではSqlite3データベースが標準です。 あらかじめインストールしておきます。 また、gitを使うので未インストールの場合はここでインストールしておいてください。
$ sudo apt install sqlite3 git
本記事でRailsの例として作ろうと考えているのは、minitestのところで作った単語帳アプリWordbookのRails版です。 ただし、ウェブでの一般公開ではなく、ローカル(自分のPC)での使用を考えています。
wordbookはReadlineを使ったCUI(Character User Interface: 文字ベースのユーザ・インターフェース)でした。 これをGUI(Graphical User Interface: グラフィック画面ベースのユーザ・インターフェース)にしたいのですが、RubyのGUIはまだ定番がありません。 そこで、ウェブ・ブラウザ上のGUIを利用してwordbookを動かそうというのが狙いです。
Railsのnewコマンドは、ウェブ・アプリ開発に必要な材料を揃えてくれます。
$ rails new word_book_rails
create
create README.md
create Rakefile
... ... ...
... ... ...
run git init from "."
Initialized empty Git repository in /ユーザディレクトリ・・・/word_book_rails/.git/
create app
create app/assets/config/manifest.js
... ... ...
... ... ...
run bundle install
Fetching gem metadata from https://rubygems.org/...........
Resolving dependencies.......
Using rake 13.0.6
... ... ...
... ... ...
Bundle complete! 15 Gemfile dependencies, 72 gems now installed.
... ... ...
... ... ...
$ ls
Gemfile Gemfile.lock README.md Rakefile app bin config config.ru db lib log public storage test tmp vendor
newコマンドは沢山の仕事をします。
git init
によってそのディレクトリでgitが使えるよう初期化するディレクトリをリスティングすると様々なファイルとフォルダ(フォルダとディレクトリは同じ。Railsでは「フォルダ」ということが多い)が作成されています。
この段階でテンプレートのウェブを表示することができます。
$ bundle exec rails server
=> Booting Puma
=> Rails 7.0.4 application starting in development
=> Run `bin/rails server --help` for more startup options
Puma starting in single mode...
* Puma version: 5.6.5 (ruby 3.1.2-p20) ("Birdie's Version")
* Min threads: 5
* Max threads: 5
* Environment: development
* PID: 5144
* Listening on http://127.0.0.1:3000
* Listening on http://[::1]:3000
Use Ctrl-C to stop
「rails server」はローカルでサーバーを立ち上げるコマンドです。
このフォルダではbundlerでgemがインストールされているので、プログラムの起動には常に「bundle exec」をつけます。
「rails server」の短縮形「rails s」でも動作は同じです。
ローカル・ホストのポート3000(http://localhost:3000/
)をブラウザで見ると、テンプレートのウェブを見ることができます。
サーバを終了するには、コマンドラインから「CTRL-C」を入力します。
ここまでやったことがどういう意味を持つのかを次のセクションで説明しましょう。
インターネットでは「サーバ」に対して「クライアント」という言葉を使います。 もしあなたがインターネットでウェブを見ているとしたら、そのあなたのPCがクライアントです。 また、ネット上のコンピュータは「ホスト」とも呼ばれます。
ネット上のサーバとクライアントを詳しく見ると、通信をしているのは、サーバコンピュータ内の「ウェブサーバーアプリ」とクライアントコンピュータ内の「ブラウザ」です。 コンピュータ同士ではなく、コンピュータ内のアプリケーション同士が繋がっていることに注意してください。
それに対して、前のセクションではRailsとブラウザがひとつのPC内にネットワークを作って接続されていました。
図では「puma」と「rails」がセットになってサーバを構成しています。 pumaはサーバ機能を提供するアプリケーションです。 ひとつのコンピュータの中でサーバとクライアントが動いていて、ちょうどインターネット接続のようなことが行われています。
ひとつのPC内にネットワークを作ることに意味はあるのでしょうか?
アプリケーション作成においては多少の意味があります。 一般にアプリケーションにGUIインターフェースを持たせるのはかなり大変です。 特にRubyの場合はこれといったGUIの決定版がありません。 それに対するひとつの答えがブラウザのGUIを利用することです。 もちろんこれがベストだとは思いませんが、選択肢のひとつだとは思います。
もっと重要なのは、ウェブサービスアプリのテストを行えるということです。 これがローカルでサーバとブラウザを使う最大の意義だと思います。
さて、具体例に戻りましょう。
ブラウザが「http://localhost:3000
」にアクセスしました。
「localhost」はIPアドレスでは「127.0.0.0」で、そのPC自身を表します。
localhostの「ローカル」は自分(の場所)「ホスト」はPCのことです。
したがって、「ローカルホスト」は自分のPCのことを指しているわけです。
「3000」はポート番号を表します。 ポートとは、サーバ内の様々なサーバーアプリケーションに割り当てられる番号です。 この割当は、ある程度決まったものがあります。 そのごく一部を表にしました。
ポート番号 | サービス | 意味 |
---|---|---|
80 | HTTP | ウェブサービス |
21 | FTP | ファイル転送 |
110 | POP3 | メールサーバとクライアント通信 |
443 | HTTPS | 暗号化されたウェブサービス |
これらは、システムポート番号(0から1023まで)に属するポートです。
これに対して1024から49151はユーザポート番号といいます。 この範囲でも公式または非公式に決まった使い方があります。 3000はRuby on Railsの開発用ポート(非公式)ですが、他の用途に用いられることもあります。 49152から65535は決まった割当のない「動的・私的ポート番号」になっています。 (ウィキペディア「ポート(コンピュータ・ネットワーク」より)
http://localhost:3000
は自分のPCのrailsの提供するサービスを指しています。
ブラウザがそこをアクセスするとrailsとpumaがウェブ画面のデータを送ってきて、それが表示されたわけです。
bundle exec rails serve
によってhttp://localhost:3000
はword_book_rails
以下のディレクトリに作られたrailsのウェブアプリケーションに割り当てられました。
同様にhttp://localhost:3000/abc.html
も同じウェブアプリケーションに対するリクエストになります。
このアドレスを2つの部分に分けて
http://localhost:3000
の部分はシステムによって(pumaと)railsのウェブアプリケーションに処理が任される/abc.html
の部分はrails内部でどのように処理するかを決めるこのうち2番めの処理は、ルーティング、コントローラ、ビューに分かれます。
abc.html
のようなアドレスの下位の部分」に対応する「コントローラ」へ処理を移すルーティングは/config/routes.rb
で設定します。
初期状態では設定は空の状態になっています。
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"
end
ルーティングはdoとendの間のブロック部分に書きます。
例えば、root
(これは/
と同じで、アドレスでhttp://localhost:3000/
に相当する)に対してWordsコントローラのindexアクションに対応させるには、
root "words#index"
と書きます。
また、/abc.html
に対してAbcコントローラのindexアクションに対応させるには、
get "/abc.html", to: "abc#index"
と書きます。
getはHTTPプロトコルのリクエスト・メソッドです。 HTTPはウェブサーバとクライアント(ブラウザ)が通信するためのプロトコル(手続き方法)です。 HTTPではクライアントがリクエストを送り、サーバがそれに応答するというパターンで通信が進みます。 このリクエストでよく使われるのがgetとpostというメソッドです。
ルーティングの詳細はまた別の記事で説明します。
コントローラはデータの種類ごとにひとつずつ作ります。 例えばブログサービスのrailsアプリでは、ユーザ管理のコントローラUsers、記事管理のコントローラArticlesなどがあります。
今回作る単語帳は単語のコントローラWordsのみで十分です。 コントローラを作るにはrailsのgenerateコマンドが便利です。
$ bundle exec rails generate controller Words
create app/controllers/words_controller.rb
invoke erb
create app/views/words
invoke test_unit
create test/controllers/words_controller_test.rb
invoke helper
create app/helpers/words_helper.rb
invoke test_unit
$
コントローラは大文字で書きはじめ、通常複数形にします。 複数形にする理由は、単語1個のデータだけでなく、複数の単語を扱うからです。 コントローラ名が2語以上からなる場合はキャメルケース(例えばWordBooks)を使います。
app/controllers/word_controller.rb
が、さきほど生成されたコントローラのファイルなので見てみましょう。
class WordsController < ApplicationController
end
コントローラは、Ruby言語のクラス定義に相当します。 この中にインスタンスメソッドを定義して、コントローラの動作を記述します。 Railsではこのインスタンスメソッドを、コントローラの「アクション」と呼びます。
本格的にコントローラを書くのは後の記事になります。 ここでは、indexというアクションを書いてみましょう。
class WordsController < ApplicationController
def index
end
end
空のメソッドindexを定義しました。
ルーティング(config/routes.rb)を次のように設定しましょう。
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
コメント部分は取り去っても構いません。
これでhttp://localhost:3000
またはhttp://localhost:3000/
(末尾にスラッシュがある)はWordsコントローラのindexアクションにルーティングされます。
これを”words#index”と書きます。
コントローラで特にHTMLを書き出す記述がなければ、対応するビューが呼ばれHTMLを出力します。
“words#index”のアクションに対応するビューはapp/views/words/index.html.erb
です。
このファイルはまだ作成されていません。
次のような内容で作成しましょう。
Hello, world.
これでブラウザ画面に「Hello, world.」が表示されるはずです。
読者の中には「HTMLデータにしては、ヘッダもボディタグもなくておかしいな」と思った方がいらっしゃるのではないでしょうか。
実は、このファイルはレイアウトファイルの中に埋め込まれるパーツなのです。
レイアウトファイルはapp/views/layouts/application.html.erb
と決まっています。
このファイルを見てみましょう。
<!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_importmap_tags %>
</head>
<body>
<%= yield %>
</body>
</html>
このファイルの<% ... ... %>
と<%= ... ... %>
の部分はRubyコードの埋め込みです。
それ以外はHTML文書になっています。
<% ... ... %>
は単なるRubyコードの記述<%= ... ... %>
はRubyコードを実行した値をHTMLに埋め込む。
例えば、<%= 1+2 %>
は文字列の3をその部分に埋め込む。
ブラウザで表示すると、その部分に3が表示されるRubyの埋め込みは全部で5つありますが、そのうちのはじめの4つの内容説明は省略します。
最後の<%= yield %>
の部分にapp/views/words/index.html.erb
の内容が埋め込まれます。
先程作ったファイルの場合は「Hello, world」が埋め込まれることになります。
3つのファイルを変更、作成しました。
config/routes.rb
app/controllers/word_controller.rb
app/views/words/index.html.erb
これをテストしてみましょう。
$ bundle exec rails server
ブラウザでhttp://localhost:3000
を見てみましょう。
今度は左上に「Hello, world.」が表示されているはずです。
このように、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の最も基本的なオブジェクトである整数について説明します。
「徒然なるままに」をネットで調べてみると、「することもなく、手持無沙汰なのにまかせてという意味」とありました。 まさに、自分の現状を言い当てた言葉。 しかも、ブログに書くネタもなかなか思いつかない日々。