Volt Introduction and Docs

なぜ [:property] のかわりにアンダースコアアクセサを使うのか?

Volt に関するよくある質問として、「なぜアンダースコア アクセサ」を使うのか、というものがあります。これは、プロパティ名を事前に定義することなく、モデルが set/get プロパティを利用できるようにするために必要となるいくつかの理由があるためです。

1. 予期しないエラーの防止

単純に、モデルにどんなメソッドでも設定できるようにすることは可能です。

item = Volt::Model.new
item.name = 'Ryan'

しかし、このときの問題は、Volt では、アサインされていないプロパティは nil を返す必要があるということです。そうすることで、事前の設定なしにプロパティをバインドすることが可能になり、バインディングは nil を適切に扱うことができるようになります。(例えば、テキストフィールドにバインドされた value は nil を空文字列であるとして扱います) 上記した問題というのは、もし存在しないメソッドを呼び出した場合にも、NoMethodError の代わりに常に nil が返される、ということです。

item = Volt::Model.new
item.savr! # => nil
# ※意図していたのは .save!

2. 簡潔であること/self なし

モデルのプロパティへのアクセスは非常によくある操作です。いくつかの JS フレームワークは .set/.get のような記法を利用していますが、単純なプロパティへのアクセスでタイピング量が多くなってしまうことを不満と感じる人が非常に多いです。Volt ではできるだけ簡潔にしたいと考えています。Ruby では以下のようなことが可能です。

item = Volt::Model.new
item[:name] # => nil

これはコントローラーのコードでは問題なく動作しますが、Volt で ModelController を使用する場合、コントローラーのモデルをモデルのインスタンスにセットしたい場合があるでしょう。その場合、バインディングで以下の設定をする必要があります (Ruby の仕様のためです):

<input value="{{ self[:name] }}" />

これは動作自体には問題ないですが、可読性が悪く、混乱の原因になる可能性があると考えています。

_property という記法は Ruby では一般的ではありませんが、一度慣れてしまえば、多くのコードのタイピングや読解から解放されます。もしこれがあまり良い方法ではないとお考えであれば、フィールド を利用することも可能だということを覚えておいてください。