「||=」(or equals) について
「||=」(or equals) について、きちんと理解をしておきたかったのでRuby on Rails チュートリアルの記事を参考に記録しました。
この「||=」(or equals) という代入演算子はRubyで広く使われているイディオムであり、Ruby開発者を志すならこの演算子に習熟することが重要です。
or equalsという概念は一見不思議にみえますが、他のものになぞらえて考えれば難しくありません。
多くのコンピュータプログラムでは、次のような記法で変数の値を1つ増やすことができます。
x = x + 1
そして、Ruby およびC、C++、Perl、Python、Javaなどの多くのプログラミング言語では、上の演算を次のような短縮形で表記することもできます。
x += 1
他の演算子についても同様の短縮形が利用できます。
$ rails console
>> x = 1
=> 1
>> x += 1
=> 2
>> x *= 3
=> 6
>> x -= 8
=> -2
>> x /= 2
=> -1
いずれの場合も、●という演算子があるときの「x = x ● y」と「x ●= y」の動作は同じです。
Rubyでは、「変数の値がnilなら変数に代入するが、nilでなければ代入しない (変数の値を変えない)」という操作が非常によく使われます。
or演算子 || を使えば、次のように書くことができます。
>> @foo
=> nil
>> @foo = @foo || "bar"
=> "bar"
>> @foo = @foo || "baz"
=> "bar"
nilの論理値はfalseになるので、@fooへの最初の代入「nil || "bar"」の評価値は"bar"になります。
同様に、2つ目の代入「@foo || "baz"」("bar" || "baz"など) の評価値は"bar"になります。
Rubyでは、nilとfalseを除いて、あらゆるオブジェクトの論理値がtrueになるように設計されています。
さらにRubyでは、||演算子をいくつも連続して式の中で使う場合、項を左から順に評価し、最初にtrueになった時点で処理を終えるように設計されています。
なお、このように||式を左から右に評価し、演算子の左の値が最初にtrueになった時点で処理を終了するという評価法を短絡評価 (short-circuit evaluation) と呼びます。
論理積の&&演算子も似たような設計になっていますが、項を左から評価して、最初にfalseになった時点で処理を終了する点が異なります。
上記の演算子をコンソールセッション上で実際に実行して比較してみると、@foo = @foo || "bar"はx = x O yに該当し、Oが||に置き換わっただけであることがわかります。
x = x + 1 -> x += 1
x = x * 3 -> x *= 3
x = x - 8 -> x -= 8
x = x / 2 -> x /= 2
@foo = @foo || "bar" -> @foo ||= "bar"
これで「@foo = @foo || "bar"」は「@foo ||= "bar"」と等価であることが理解できます。
この記法をcurrent_userの文脈
@current_user = @current_user || User.find_by(id: session[:user_id])
で使うと
次のような簡潔なコードになります。
@current_user ||= User.find_by(id: session[:user_id])
補足:
技術的には、「@foo || @foo = "bar"」と書いた場合、Rubyの内部では実際にすべての項が評価されます (||が左辺にある点に注意)。
これは@fooがnilやfalseでない場合に、無駄な代入を避ける必要があるためです。
しかしこの式の動作では||=記法の動作と同じにならず、説明上不都合なので、上の解説では@foo = @foo || "bar" という式を用いて説明しました。
テストについて (Ruby on Rails Tutorialから)
Ruby on Rails Tutorialにおいて、どんなふうにテストを行えばよいかについての記載がありましたので、整理を兼ねてブログにしました。
この点を理解するために、テストを行う目的を確認すると、テストには次の3つのメリットがあります。
- テストが揃っていれば、機能停止に陥るような回帰バグ (Regression Bug: 以前のバグが再発したり機能の追加/変更に副作用が生じたりすること) を防止できる。
- テストが揃っていれば、コードを安全にリファクタリング (機能を変更せずにコードを改善すること) ができる。
- テストコードは、アプリケーションコードから見ればクライアントとして動作するので、アプリケーションの設計やシステムの他の部分とのインターフェイスを決めるときにも役に立つ。
上の3つのメリットは、テストを先に書かなくても得ることができますが、テスト駆動開発 (TDD) という手法をいつでも使えるようにしておけば、間違いなく多くの場面で役に立つと考えられています。
テストの手法やタイミングは、ある意味テストをどのぐらいすらすら書けるかで決まると言ってよく、たいていの開発者は、テストを書くのに慣れてくるとテストを先に書くようになるとのことです。
その他にも、アプリケーションのコードと比べてテストがどのぐらい書きにくいか、必要な機能をどのぐらい正確に把握しているか、その機能が将来廃止される可能性がどのぐらいあるかによっても異なってくるようです。
こういうときのために、
「テスト駆動」にするか「一括テスト」にするかを決める目安となるガイドラインがあると便利なので、チュートリアルでは 次のようにまとめてありました。
- アプリケーションのコードよりも明らかにテストコードの方が短くシンプルになる (=簡単に書ける) のであれば、「先に」書く
- 動作の仕様がまだ固まりきっていない場合、アプリケーションのコードを先に書き、期待する動作を「後で」書く
- セキュリティが重要な課題またはセキュリティ周りのエラーが発生した場合、テストを「先に」書く
- バグを見つけたら、そのバグを再現するテストを「先に」書き、回帰バグを防ぐ体制を整えてから修正に取りかかる
- すぐにまた変更しそうなコード (HTML構造の細部など) に対するテストは「後で」書く
- リファクタリングするときは「先に」テストを書く。特に、エラーを起こしそうなコードや止まってしまいそうなコードを集中的にテストする
上のガイドラインに従う場合、
現実には最初にコントローラやモデルのテストを書き、続いて統合テスト (モデル/ビュー/コントローラにまたがる機能テスト) を書く、ということになります。
また、不安定な要素が特に見当たらないアプリケーションや、
(主にビューが) 頻繁に改定される可能性の高いアプリケーションのコードを書くときには、思い切ってテストを省略してしまうこともあるとのことです。
尚、チュートリアルのカリキュラムにおいては、
主要なテストは、コントローラテスト、モデルテスト、統合テストの3つとなっており、3章からコントローラテスト、6章からモデルテスト、7章から統合テストとなっています。
統合テストは、ユーザーがWebブラウザでアプリケーションとやりとりする操作をシミュレートできるので特に強力で、テストにおける最も主要な武器の1つとなっています。
今後、この内容を参考に自分なりのやり方を工夫していきたいと考えております。
チュートリアルでクラウドIDEを使っています
クラウドIDE(クラウド統合開発環境 )
Ruby on Rails のスキルアップを図るため、 Ruby on Rails チュートリアルを進めております。
その中で、OSの違い、バージョンの違い、テキストエディタの設定の違い、IDEの違いなど、環境にばらつきがあると、さまざまな問題が複合して発生することから、
それに対応する方法としてチュートリアルでは、クラウド統合開発環境 (クラウドIDE) を使うことをオススメしており、実際使っています。
・デバッガ(エラーの箇所を見つけて修正するためのツール)
・ソースコード管理ツール
等の各種ツール類をまとめて、
1つのアプリケーションで実行できるように整備されたものとなっております。
クラウドIDEはWebブラウザの中で実行できるため、OSが異なっても同じように扱え、この特長は、Rails開発環境の構築が面倒なOSでは特に便利とされています。
さらに、クラウドIDEでは作業の状態もクラウド上に保存されるので、チュートリアル中に中座して他の作業を行い、また戻ったときにもすぐ再開できるといったメリットもあります。
今回のチュートリアルでは、AWSの Cloud9というクラウドIDEサービスを使って進めておりますが、他にも
等々があります。
AWS Cloud9ではRubyやRubyGems、Gitなど、Railsの開発環境の構築に必要なソフトウェアがほとんど組み込まれていますが、RailsやHerokuなどの一部のソフトウェアはインストールされていないので、インストールする必要がありました。
また、クラウドIDEのテキストエディタでは、Ruby on Railsの大きなプロジェクトには不可欠とも言うべき横断的ファイル検索も利用可能となっております。
➡︎例えばfooという名前のメソッド定義を見つけるには、「def foo」をグローバル検索します。
クラウドIDEの良さ悪さについては一長一短あり、まだはっきり言ってわからない状況です。
ただ自分自身で思うことは、初めから学習する場合は「テキストエディタ」と、「コマンドプロンプト(ターミナル)」を使って学習し、学習の進行具合に合わせて、エディタからクラウドIDEへ移行していく方が良いのではと感じました。
今回、Ruby on Railsチュートリアルをやって、初めてクラウドIDEのことを知りました。 初めてのブログとして、自分自身へのメモを兼ねて、クラウドIDEのことを書かせて頂きました。
引き続き、学習していく上で何かわかったことがあれば、また書かせて頂くつもりです。